From e5764aecfdfcae26869f4fecc49c3252ccff5d5b Mon Sep 17 00:00:00 2001 From: "qiang.xue" <> Date: Sun, 2 Nov 2008 16:50:26 +0000 Subject: fixed version info. --- HISTORY | 4 + UPGRADE | 358 +++++++------- framework/PradoBase.php | 1238 +++++++++++++++++++++++------------------------ index.html | 2 +- 4 files changed, 805 insertions(+), 797 deletions(-) diff --git a/HISTORY b/HISTORY index 319100ef..8ed6d4d8 100644 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,7 @@ +Version 3.1.4 To be released +============================== + + Version 3.1.3 November 1, 2008 ============================== BUG: Ticket#595 - ControlCssClass not applied correctly if using multiple validators on same control (Michael) diff --git a/UPGRADE b/UPGRADE index ecb5225b..05fe6547 100644 --- a/UPGRADE +++ b/UPGRADE @@ -1,177 +1,181 @@ - - Upgrading Instructions for PRADO Framework v3.1.3 - ================================================= - -!!!IMPORTANT!!! - -The following upgrading instructions are cumulative. That is, -if you want to upgrade from version A to version C and there is -version B between A and C, you need to following the instructions -for both A and B. - -Upgrading from v3.1.2 ---------------------- -- The Translation configuration now also accepts type 'Database' to - ease the setup of DB base translation. A valid ConnectionID has to - be supplied in the source parameter: - - Type 'MySQL' can still be used but is deprecated and might be removed - in a later release. -- TinyMCE (used by THtmlArea component) has been upgraded to version 3.1.0.1. - Since the 3.X branch of TinyMCE has a different API than 2.X, you should - upgrade your Customs Plugins if you use any. - See http://wiki.moxiecode.com/index.php/TinyMCE:Migration_guide for more information. -- If you use EnableStateEncryption, the PageState of your current user sessions - will no longer be valid, since we optimized the encryption/compression logic. -- You can now use # and $ characters in your SQL statements with SQLMap by - escaping them as ## and $$. That induces that you can't have consecutive - parameters like #param1##param2# or $param1$$param2$ in your statements anymore. - - -Upgrading from v3.1.1 ---------------------- -- The RELATIONS type declaration in Active Record classes for Many-to-Many using - an association table was change from "self::HAS_MANY" to "self::MANY_TO_MANY". - E.g. change - 'albums' => array(self::HAS_MANY, 'Artist', 'album_artists') - to - 'albums' => array(self::MANY_TO_MANY, 'Artist', 'album_artists') -- Active Record no longer automatically adds/removes/updates related objects. -- 'Raw' mode for TCheckboxList and TRadioButtonList (and their active counter parts) now render - a surrounding tag to allow client scripts to identify them with the ClientId. You may - have to check your CSS. - - -Upgrading from v3.1.0 ---------------------- -- The RELATIONS declaration in Acive Record classes is changed from - "protected static $RELATIONS" to "public static $RELATIONS". -- IFeedContentProvider adds a new method: getContentType(). This affects any - class implementing this interface. -- TUrlMapping now only uses the PATH_INFO part of URL for matching, and the matching - is for the whole PATH_INFO. -- IUserManager adds two new methods: getUserFromCookie() and saveUserToCookie(). - This affects classes that implements this interface and does not extend from - TUserManager. -- The order of application lifecycles is changed. The loadState and loadStateComplete - are moved to right after onBeginRequest. -- TDropDownList will be in an unselected state if no initial selection is specified. - That is, its SelectedIndex will be -1. Previously, the first item will be considered as selected. - -Upgrading from v3.1b --------------------- -- Comment tag (introduced in v3.1a) is changed to -- When TDataList.RepeatLayout is Raw, the items will render
instead of -- TActiveRecord finder methods will always return a new object instance (identity mapping was removed). -- TActiveRecord::findBySql() will return an object rather than an array -- TActiveRecord::findAllBySql() will return an array of objects. - -Upgrading from v3.1a ---------------------- -- The signature of TActiveRecord::finder() is changed. This affects - all TActiveRecord-descendant classes that override this method. - Please use the following code to override the method: - public static function finder($className=__CLASS__) - { - return parent::finder($className); - } - -- The way to specify the table name for an active record class is changed. - Previously, it used the static class member '_tablename'. - Now it uses class constant as follows: - class UserRecord extends TActiveRecord - { - const TABLE='users_table'; - } - -- Changed TActiveRatingList's javascript control class - name from "Prado.WebUI.TRatingList" to "Prado.WebUI.TActiveRatingList". - -- PRADO's javascript library locations moved from Web/Javascripts/xxx to Web/Javascripts/source/xxx - -- IPostBackDataHandler added a new method getDataChanged(). Any control - implementing this interface will be required to implement this new method. - -Upgrading from v3.0.x ---------------------- -- Validators ClientSide.OnSuccess becomes ClientSide.OnValidationSuccess, -- Validators ClientSide.OnError becomes ClientSide.OnValidationError, -- Validator OnSuccess event becomes OnValidationSuccess. -- Validator OnError event becomes OnValidationError. -- Content enclosed in is now parsed as normal template content. - Previously, it was not parsed and was rendered as is. - -Upgrading from v3.0.7 ---------------------- - -Upgrading from v3.0.6 ---------------------- - -Upgrading from v3.0.5 ---------------------- -- TRepeater does not render anymore for empty item template. -- constructUrl() now encodes ampersand by default. This should have minimal - impact on any existing PRADO applications, though. -- TDataGrid does not generate default table styles. This may affect - the appearance of existing PRADO applications that use TDataGrid. -- If TUrlMapping is used, you need to set the UrlManager property of - THttpRequest to the module ID of TUrlMapping. -- TJavascriptLogger toggle key is changed from ALT-D to ALT-J. - Use the ToggleKey property chanage to a different key. -- Javascript Library rico was REMOVED. - -Upgrading from v3.0.4 ---------------------- -- TFileUpload::saveAs() will return false instead of raising an exception - if it encounters any error. -- TDropDownListColumn.DataField is renamed to DataTextField and - DataFormatString is renamed to DataTextFormatString. - A new property named DataValueField is added. - -Upgrading from v3.0.3 ---------------------- -- The 'Static' value is changed to 'Fixed' for the Display property of - all validators as well as TValidationSummary, due to conflict with PHP keywords. -- The 'List' value is changed to 'SimpleList' for TValidationSummary.DisplayMode. -- The 'List' value is changed to 'DropDownList' for TPager.Mode -- This change affects existing client-side javascript handlers such as - - All ClientSide javascript event handlers (such as ClientSide.OnSuccess) - are by default wrapped within the function block. - function(sender, parameter){ // handler code } - You may override this behaviour by providing your own javascript statement block - as "javascript:MyHandlerFunction", e.g. ClientSide.OnSuccess="javascript:MyHandlerFunction" - or ClientSide.OnSuccess="javascript:function(validator,sender){ ... }" - - -Upgrading from v3.0.2 ---------------------- -- The minimum PHP version required is raised to 5.1.0 and above. - If your server is installed with a lower version of PHP, you will - have to upgrade it in order to run PRADO applications. -- The signature of TControl::broadcastEvent() is changed from - broadcastEvent($sender,TBroadCastEventParameter $param) to - broadcastEvent($name,$sender,$param). - This makes the call to broadcastEvent() to be consistent with raiseEvent(). - -Upgrading from v3.0.1 ---------------------- -- Postback enabled control will always disable default client-side browser action. - This is due to google toolbar's interference of event stopping scheme. - This modification should only affect user-derived postback javascripts. - -Upgrading from v3.0.0 ---------------------- -- URL format is modified when THttpRequest.UrlFormat=='Path'. - This modification affects both the URLs generated by calling constructUrl() - and the URLs understood by PRADO. In particular, PRADO now understands - the following URL format: - /index.php/ServiceID,ServiceParam/Name1,Value1/Name2,Value2/... - In v3.0.0, the above URL is written as: - /index.php/ServiceID/ServiceParam/Name1/Value1/Name2/Value2/... -- TControl::onBubbleEvent() has been changed to TControl::bubbleEvent(). - This change only affects user controls that override this method. - -Upgrading from v2.x and v1.x ----------------------------- -PRADO v3.x is not backward compatible with v2.x and v1.x. + + Upgrading Instructions for PRADO Framework v3.1.4 + ================================================= + +!!!IMPORTANT!!! + +The following upgrading instructions are cumulative. That is, +if you want to upgrade from version A to version C and there is +version B between A and C, you need to following the instructions +for both A and B. + +Upgrading from v3.1.3 +--------------------- + + +Upgrading from v3.1.2 +--------------------- +- The Translation configuration now also accepts type 'Database' to + ease the setup of DB base translation. A valid ConnectionID has to + be supplied in the source parameter: + + Type 'MySQL' can still be used but is deprecated and might be removed + in a later release. +- TinyMCE (used by THtmlArea component) has been upgraded to version 3.1.0.1. + Since the 3.X branch of TinyMCE has a different API than 2.X, you should + upgrade your Customs Plugins if you use any. + See http://wiki.moxiecode.com/index.php/TinyMCE:Migration_guide for more information. +- If you use EnableStateEncryption, the PageState of your current user sessions + will no longer be valid, since we optimized the encryption/compression logic. +- You can now use # and $ characters in your SQL statements with SQLMap by + escaping them as ## and $$. That induces that you can't have consecutive + parameters like #param1##param2# or $param1$$param2$ in your statements anymore. + + +Upgrading from v3.1.1 +--------------------- +- The RELATIONS type declaration in Active Record classes for Many-to-Many using + an association table was change from "self::HAS_MANY" to "self::MANY_TO_MANY". + E.g. change + 'albums' => array(self::HAS_MANY, 'Artist', 'album_artists') + to + 'albums' => array(self::MANY_TO_MANY, 'Artist', 'album_artists') +- Active Record no longer automatically adds/removes/updates related objects. +- 'Raw' mode for TCheckboxList and TRadioButtonList (and their active counter parts) now render + a surrounding tag to allow client scripts to identify them with the ClientId. You may + have to check your CSS. + + +Upgrading from v3.1.0 +--------------------- +- The RELATIONS declaration in Acive Record classes is changed from + "protected static $RELATIONS" to "public static $RELATIONS". +- IFeedContentProvider adds a new method: getContentType(). This affects any + class implementing this interface. +- TUrlMapping now only uses the PATH_INFO part of URL for matching, and the matching + is for the whole PATH_INFO. +- IUserManager adds two new methods: getUserFromCookie() and saveUserToCookie(). + This affects classes that implements this interface and does not extend from + TUserManager. +- The order of application lifecycles is changed. The loadState and loadStateComplete + are moved to right after onBeginRequest. +- TDropDownList will be in an unselected state if no initial selection is specified. + That is, its SelectedIndex will be -1. Previously, the first item will be considered as selected. + +Upgrading from v3.1b +-------------------- +- Comment tag (introduced in v3.1a) is changed to +- When TDataList.RepeatLayout is Raw, the items will render
instead of +- TActiveRecord finder methods will always return a new object instance (identity mapping was removed). +- TActiveRecord::findBySql() will return an object rather than an array +- TActiveRecord::findAllBySql() will return an array of objects. + +Upgrading from v3.1a +--------------------- +- The signature of TActiveRecord::finder() is changed. This affects + all TActiveRecord-descendant classes that override this method. + Please use the following code to override the method: + public static function finder($className=__CLASS__) + { + return parent::finder($className); + } + +- The way to specify the table name for an active record class is changed. + Previously, it used the static class member '_tablename'. + Now it uses class constant as follows: + class UserRecord extends TActiveRecord + { + const TABLE='users_table'; + } + +- Changed TActiveRatingList's javascript control class + name from "Prado.WebUI.TRatingList" to "Prado.WebUI.TActiveRatingList". + +- PRADO's javascript library locations moved from Web/Javascripts/xxx to Web/Javascripts/source/xxx + +- IPostBackDataHandler added a new method getDataChanged(). Any control + implementing this interface will be required to implement this new method. + +Upgrading from v3.0.x +--------------------- +- Validators ClientSide.OnSuccess becomes ClientSide.OnValidationSuccess, +- Validators ClientSide.OnError becomes ClientSide.OnValidationError, +- Validator OnSuccess event becomes OnValidationSuccess. +- Validator OnError event becomes OnValidationError. +- Content enclosed in is now parsed as normal template content. + Previously, it was not parsed and was rendered as is. + +Upgrading from v3.0.7 +--------------------- + +Upgrading from v3.0.6 +--------------------- + +Upgrading from v3.0.5 +--------------------- +- TRepeater does not render anymore for empty item template. +- constructUrl() now encodes ampersand by default. This should have minimal + impact on any existing PRADO applications, though. +- TDataGrid does not generate default table styles. This may affect + the appearance of existing PRADO applications that use TDataGrid. +- If TUrlMapping is used, you need to set the UrlManager property of + THttpRequest to the module ID of TUrlMapping. +- TJavascriptLogger toggle key is changed from ALT-D to ALT-J. + Use the ToggleKey property chanage to a different key. +- Javascript Library rico was REMOVED. + +Upgrading from v3.0.4 +--------------------- +- TFileUpload::saveAs() will return false instead of raising an exception + if it encounters any error. +- TDropDownListColumn.DataField is renamed to DataTextField and + DataFormatString is renamed to DataTextFormatString. + A new property named DataValueField is added. + +Upgrading from v3.0.3 +--------------------- +- The 'Static' value is changed to 'Fixed' for the Display property of + all validators as well as TValidationSummary, due to conflict with PHP keywords. +- The 'List' value is changed to 'SimpleList' for TValidationSummary.DisplayMode. +- The 'List' value is changed to 'DropDownList' for TPager.Mode +- This change affects existing client-side javascript handlers such as + + All ClientSide javascript event handlers (such as ClientSide.OnSuccess) + are by default wrapped within the function block. + function(sender, parameter){ // handler code } + You may override this behaviour by providing your own javascript statement block + as "javascript:MyHandlerFunction", e.g. ClientSide.OnSuccess="javascript:MyHandlerFunction" + or ClientSide.OnSuccess="javascript:function(validator,sender){ ... }" + + +Upgrading from v3.0.2 +--------------------- +- The minimum PHP version required is raised to 5.1.0 and above. + If your server is installed with a lower version of PHP, you will + have to upgrade it in order to run PRADO applications. +- The signature of TControl::broadcastEvent() is changed from + broadcastEvent($sender,TBroadCastEventParameter $param) to + broadcastEvent($name,$sender,$param). + This makes the call to broadcastEvent() to be consistent with raiseEvent(). + +Upgrading from v3.0.1 +--------------------- +- Postback enabled control will always disable default client-side browser action. + This is due to google toolbar's interference of event stopping scheme. + This modification should only affect user-derived postback javascripts. + +Upgrading from v3.0.0 +--------------------- +- URL format is modified when THttpRequest.UrlFormat=='Path'. + This modification affects both the URLs generated by calling constructUrl() + and the URLs understood by PRADO. In particular, PRADO now understands + the following URL format: + /index.php/ServiceID,ServiceParam/Name1,Value1/Name2,Value2/... + In v3.0.0, the above URL is written as: + /index.php/ServiceID/ServiceParam/Name1/Value1/Name2/Value2/... +- TControl::onBubbleEvent() has been changed to TControl::bubbleEvent(). + This change only affects user controls that override this method. + +Upgrading from v2.x and v1.x +---------------------------- +PRADO v3.x is not backward compatible with v2.x and v1.x. diff --git a/framework/PradoBase.php b/framework/PradoBase.php index ead66e1b..4a64d6dd 100644 --- a/framework/PradoBase.php +++ b/framework/PradoBase.php @@ -1,619 +1,619 @@ - - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System - */ - -/** - * Defines the PRADO framework installation path. - */ -if(!defined('PRADO_DIR')) - define('PRADO_DIR',dirname(__FILE__)); -/** - * Defines the default permission for writable directories and files - */ -if(!defined('PRADO_CHMOD')) - define('PRADO_CHMOD',0777); - -/** - * PradoBase class. - * - * PradoBase implements a few fundamental static methods. - * - * To use the static methods, Use Prado as the class name rather than PradoBase. - * PradoBase is meant to serve as the base class of Prado. The latter might be - * rewritten for customization. - * - * @author Qiang Xue - * @version $Id$ - * @package System - * @since 3.0 - */ -class PradoBase -{ - /** - * File extension for Prado class files. - */ - const CLASS_FILE_EXT='.php'; - /** - * @var array list of path aliases - */ - private static $_aliases=array('System'=>PRADO_DIR); - /** - * @var array list of namespaces currently in use - */ - private static $_usings=array(); - /** - * @var TApplication the application instance - */ - private static $_application=null; - /** - * @var TLogger logger instance - */ - private static $_logger=null; - - /** - * @return string the version of Prado framework - */ - public static function getVersion() - { - return '3.1.3a'; - } - - /** - * Initializes error handlers. - * This method set error and exception handlers to be functions - * defined in this class. - */ - public static function initErrorHandlers() - { - /** - * Sets error handler to be Prado::phpErrorHandler - */ - set_error_handler(array('PradoBase','phpErrorHandler'),error_reporting()); - /** - * Sets exception handler to be Prado::exceptionHandler - */ - set_exception_handler(array('PradoBase','exceptionHandler')); - } - - /** - * Class autoload loader. - * This method is provided to be invoked within an __autoload() magic method. - * @param string class name - */ - public static function autoload($className) - { - include_once($className.self::CLASS_FILE_EXT); - if(!class_exists($className,false) && !interface_exists($className,false)) - self::fatalError("Class file for '$className' cannot be found."); - } - - /** - * @param integer the type of "powered logo". Valid values include 0 and 1. - * @return string a string that can be displayed on your Web page showing powered-by-PRADO information - */ - public static function poweredByPrado($logoType=0) - { - $logoName=$logoType==1?'powered2':'powered'; - if(self::$_application!==null) - { - $am=self::$_application->getAssetManager(); - $url=$am->publishFilePath(self::getPathOfNamespace('System.'.$logoName,'.gif')); - } - else - $url='http://www.pradosoft.com/images/'.$logoName.'.gif'; - return 'Powered by PRADO'; - } - - public static function metaGenerator() - { - return 'PRADO - http://www.pradosoft.com/'; - } - - /** - * PHP error handler. - * This method should be registered as PHP error handler using - * {@link set_error_handler}. The method throws an exception that - * contains the error information. - * @param integer the level of the error raised - * @param string the error message - * @param string the filename that the error was raised in - * @param integer the line number the error was raised at - */ - public static function phpErrorHandler($errno,$errstr,$errfile,$errline) - { - if(error_reporting()!=0) - throw new TPhpErrorException($errno,$errstr,$errfile,$errline); - } - - /** - * Default exception handler. - * This method should be registered as default exception handler using - * {@link set_exception_handler}. The method tries to use the errorhandler - * module of the Prado application to handle the exception. - * If the application or the module does not exist, it simply echoes the - * exception. - * @param Exception exception that is not caught - */ - public static function exceptionHandler($exception) - { - if(self::$_application!==null && ($errorHandler=self::$_application->getErrorHandler())!==null) - { - $errorHandler->handleError(null,$exception); - } - else - { - echo $exception; - } - exit(1); - } - - /** - * Stores the application instance in the class static member. - * This method helps implement a singleton pattern for TApplication. - * Repeated invocation of this method or the application constructor - * will cause the throw of an exception. - * This method should only be used by framework developers. - * @param TApplication the application instance - * @throws TInvalidOperationException if this method is invoked twice or more. - */ - public static function setApplication($application) - { - if(self::$_application!==null) - throw new TInvalidOperationException('prado_application_singleton_required'); - self::$_application=$application; - } - - /** - * @return TApplication the application singleton, null if the singleton has not be created yet. - */ - public static function getApplication() - { - return self::$_application; - } - - /** - * @return string the path of the framework - */ - public static function getFrameworkPath() - { - return PRADO_DIR; - } - - /** - * Serializes a data. - * The original PHP serialize function has a bug that may not serialize - * properly an object. - * @param mixed data to be serialized - * @return string the serialized data - */ - public static function serialize($data) - { - $arr[0]=$data; - return serialize($arr); - } - - /** - * Unserializes a data. - * The original PHP unserialize function has a bug that may not unserialize - * properly an object. - * @param string data to be unserialized - * @return mixed unserialized data, null if unserialize failed - */ - public static function unserialize($str) - { - $arr=unserialize($str); - return isset($arr[0])?$arr[0]:null; - } - - /** - * Creates a component with the specified type. - * A component type can be either the component class name - * or a namespace referring to the path of the component class file. - * For example, 'TButton', 'System.Web.UI.WebControls.TButton' are both - * valid component type. - * This method can also pass parameters to component constructors. - * All parameters passed to this method except the first one (the component type) - * will be supplied as component constructor parameters. - * @param string component type - * @return TComponent component instance of the specified type - * @throws TInvalidDataValueException if the component type is unknown - */ - public static function createComponent($type) - { - self::using($type); - if(($pos=strrpos($type,'.'))!==false) - $type=substr($type,$pos+1); - if(($n=func_num_args())>1) - { - $args=func_get_args(); - $s='$args[1]'; - for($i=2;$i<$n;++$i) - $s.=",\$args[$i]"; - eval("\$component=new $type($s);"); - return $component; - } - else - return new $type; - } - - /** - * Uses a namespace. - * A namespace ending with an asterisk '*' refers to a directory, otherwise it represents a PHP file. - * If the namespace corresponds to a directory, the directory will be appended - * to the include path. If the namespace corresponds to a file, it will be included (include_once). - * @param string namespace to be used - * @param boolean whether to check the existence of the class after the class file is included - * @throws TInvalidDataValueException if the namespace is invalid - */ - public static function using($namespace,$checkClassExistence=true) - { - if(isset(self::$_usings[$namespace]) || class_exists($namespace,false)) - return; - if(($pos=strrpos($namespace,'.'))===false) // a class name - { - try - { - include_once($namespace.self::CLASS_FILE_EXT); - } - catch(Exception $e) - { - if($checkClassExistence && !class_exists($namespace,false)) - throw new TInvalidOperationException('prado_component_unknown',$namespace,$e->getMessage()); - else - throw $e; - } - } - else if(($path=self::getPathOfNamespace($namespace,self::CLASS_FILE_EXT))!==null) - { - $className=substr($namespace,$pos+1); - if($className==='*') // a directory - { - self::$_usings[$namespace]=$path; - set_include_path(get_include_path().PATH_SEPARATOR.$path); - } - else // a file - { - self::$_usings[$namespace]=$path; - if(!$checkClassExistence || !class_exists($className,false)) - { - try - { - include_once($path); - } - catch(Exception $e) - { - if($checkClassExistence && !class_exists($className,false)) - throw new TInvalidOperationException('prado_component_unknown',$className,$e->getMessage()); - else - throw $e; - } - } - } - } - else - throw new TInvalidDataValueException('prado_using_invalid',$namespace); - } - - /** - * Translates a namespace into a file path. - * The first segment of the namespace is considered as a path alias - * which is replaced with the actual path. The rest segments are - * subdirectory names appended to the aliased path. - * If the namespace ends with an asterisk '*', it represents a directory; - * Otherwise it represents a file whose extension name is specified by the second parameter (defaults to empty). - * Note, this method does not ensure the existence of the resulting file path. - * @param string namespace - * @param string extension to be appended if the namespace refers to a file - * @return string file path corresponding to the namespace, null if namespace is invalid - */ - public static function getPathOfNamespace($namespace,$ext='') - { - if(isset(self::$_usings[$namespace])) - return self::$_usings[$namespace]; - else if(isset(self::$_aliases[$namespace])) - return self::$_aliases[$namespace]; - else - { - $segs=explode('.',$namespace); - $alias=array_shift($segs); - if(($file=array_pop($segs))!==null && ($root=self::getPathOfAlias($alias))!==null) - return rtrim($root.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR ,$segs),'/\\').(($file==='*')?'':DIRECTORY_SEPARATOR.$file.$ext); - else - return null; - } - } - - /** - * @param string alias to the path - * @return string the path corresponding to the alias, null if alias not defined. - */ - public static function getPathOfAlias($alias) - { - return isset(self::$_aliases[$alias])?self::$_aliases[$alias]:null; - } - - protected static function getPathAliases() - { - return self::$_aliases; - } - - /** - * @param string alias to the path - * @param string the path corresponding to the alias - * @throws TInvalidOperationException if the alias is already defined - * @throws TInvalidDataValueException if the path is not a valid file path - */ - public static function setPathOfAlias($alias,$path) - { - if(isset(self::$_aliases[$alias])) - throw new TInvalidOperationException('prado_alias_redefined',$alias); - else if(($rp=realpath($path))!==false && is_dir($rp)) - { - if(strpos($alias,'.')===false) - self::$_aliases[$alias]=$rp; - else - throw new TInvalidDataValueException('prado_aliasname_invalid',$alias); - } - else - throw new TInvalidDataValueException('prado_alias_invalid',$alias,$path); - } - - /** - * Fatal error handler. - * This method displays an error message together with the current call stack. - * The application will exit after calling this method. - * @param string error message - */ - public static function fatalError($msg) - { - echo '

Fatal Error

'; - echo '

'.$msg.'

'; - if(!function_exists('debug_backtrace')) - return; - echo '

Debug Backtrace

'; - echo '
';
-		$index=-1;
-		foreach(debug_backtrace() as $t)
-		{
-			$index++;
-			if($index==0)  // hide the backtrace of this function
-				continue;
-			echo '#'.$index.' ';
-			if(isset($t['file']))
-				echo basename($t['file']) . ':' . $t['line'];
-			else
-			   echo '';
-			echo ' -- ';
-			if(isset($t['class']))
-				echo $t['class'] . $t['type'];
-			echo $t['function'] . '(';
-			if(isset($t['args']) && sizeof($t['args']) > 0)
-			{
-				$count=0;
-				foreach($t['args'] as $item)
-				{
-					if(is_string($item))
-					{
-						$str=htmlentities(str_replace("\r\n", "", $item), ENT_QUOTES);
-						if (strlen($item) > 70)
-							echo "'". substr($str, 0, 70) . "...'";
-						else
-							echo "'" . $str . "'";
-					}
-					else if (is_int($item) || is_float($item))
-						echo $item;
-					else if (is_object($item))
-						echo get_class($item);
-					else if (is_array($item))
-						echo 'array(' . count($item) . ')';
-					else if (is_bool($item))
-						echo $item ? 'true' : 'false';
-					else if ($item === null)
-						echo 'NULL';
-					else if (is_resource($item))
-						echo get_resource_type($item);
-					$count++;
-					if (count($t['args']) > $count)
-						echo ', ';
-				}
-			}
-			echo ")\n";
-		}
-		echo '
'; - exit(1); - } - - /** - * Returns a list of user preferred languages. - * The languages are returned as an array. Each array element - * represents a single language preference. The languages are ordered - * according to user preferences. The first language is the most preferred. - * @return array list of user preferred languages. - */ - public static function getUserLanguages() - { - static $languages=null; - if($languages===null) - { - if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) - $languages[0]='en'; - else - { - $languages=array(); - foreach(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']) as $language) - { - $array=split(';q=',trim($language)); - $languages[trim($array[0])]=isset($array[1])?(float)$array[1]:1.0; - } - arsort($languages); - $languages=array_keys($languages); - if(empty($languages)) - $languages[0]='en'; - } - } - return $languages; - } - - /** - * Returns the most preferred language by the client user. - * @return string the most preferred language by the client user, defaults to English. - */ - public static function getPreferredLanguage() - { - static $language=null; - if($language===null) - { - $langs=Prado::getUserLanguages(); - $lang=explode('-',$langs[0]); - if(empty($lang[0]) || !ctype_alpha($lang[0])) - $language='en'; - else - $language=$lang[0]; - } - return $language; - } - - /** - * Writes a log message. - * This method wraps {@link log()} by checking the application mode. - * When the application is in Debug mode, debug backtrace information is appended - * to the message and the message is logged at DEBUG level. - * When the application is in Performance mode, this method does nothing. - * Otherwise, the message is logged at INFO level. - * @param string message to be logged - * @param string category of the message - * @see log, getLogger - */ - public static function trace($msg,$category='Uncategorized') - { - if(self::$_application && self::$_application->getMode()===TApplicationMode::Performance) - return; - if(!self::$_application || self::$_application->getMode()===TApplicationMode::Debug) - { - $trace=debug_backtrace(); - if(isset($trace[0]['file']) && isset($trace[0]['line'])) - $msg.=" (line {$trace[0]['line']}, {$trace[0]['file']})"; - $level=TLogger::DEBUG; - } - else - $level=TLogger::INFO; - self::log($msg,$level,$category); - } - - /** - * Logs a message. - * Messages logged by this method may be retrieved via {@link TLogger::getLogs} - * and may be recorded in different media, such as file, email, database, using - * {@link TLogRouter}. - * @param string message to be logged - * @param integer level of the message. Valid values include - * TLogger::DEBUG, TLogger::INFO, TLogger::NOTICE, TLogger::WARNING, - * TLogger::ERROR, TLogger::ALERT, TLogger::FATAL. - * @param string category of the message - */ - public static function log($msg,$level=TLogger::INFO,$category='Uncategorized') - { - if(self::$_logger===null) - self::$_logger=new TLogger; - self::$_logger->log($msg,$level,$category); - } - - /** - * @return TLogger message logger - */ - public static function getLogger() - { - if(self::$_logger===null) - self::$_logger=new TLogger; - return self::$_logger; - } - - /** - * Converts a variable into a string representation. - * This method achieves the similar functionality as var_dump and print_r - * but is more robust when handling complex objects such as PRADO controls. - * @param mixed variable to be dumped - * @param integer maximum depth that the dumper should go into the variable. Defaults to 10. - * @param boolean whether to syntax highlight the output. Defaults to false. - * @return string the string representation of the variable - */ - public static function varDump($var,$depth=10,$highlight=false) - { - Prado::using('System.Util.TVarDumper'); - return TVarDumper::dump($var,$depth,$highlight); - } - - /** - * Localize a text to the locale/culture specified in the globalization handler. - * @param string text to be localized. - * @param array a set of parameters to substitute. - * @param string a different catalogue to find the localize text. - * @param string the input AND output charset. - * @return string localized text. - * @see TTranslate::formatter() - * @see TTranslate::init() - */ - public static function localize($text, $parameters=array(), $catalogue=null, $charset=null) - { - Prado::using('System.I18N.Translation'); - $app = Prado::getApplication()->getGlobalization(false); - - $params = array(); - foreach($parameters as $key => $value) - $params['{'.$key.'}'] = $value; - - //no translation handler provided - if($app===null || ($config = $app->getTranslationConfiguration())===null) - return strtr($text, $params); - - if ($catalogue===null) - $catalogue=isset($config['catalogue'])?$config['catalogue']:'messages'; - - Translation::init($catalogue); - - //globalization charset - $appCharset = $app===null ? '' : $app->getCharset(); - - //default charset - $defaultCharset = ($app===null) ? 'UTF-8' : $app->getDefaultCharset(); - - //fall back - if(empty($charset)) $charset = $appCharset; - if(empty($charset)) $charset = $defaultCharset; - - return Translation::formatter($catalogue)->format($text,$params,$catalogue,$charset); - } -} - -/** - * TReflectionClass class. - * This class was originally written to cope with the incompatibility between different PHP versions. - * It is equivalent to ReflectionClass for PHP version >= 5.1.0 - * @author Qiang Xue - * @version $Id$ - * @package System - * @since 3.0 - */ -class TReflectionClass extends ReflectionClass -{ -} - -/** - * Includes the classes essential for PradoBase class - */ -PradoBase::using('System.TComponent'); -PradoBase::using('System.Exceptions.TException'); -PradoBase::using('System.Util.TLogger'); - -?> + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2008 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System + */ + +/** + * Defines the PRADO framework installation path. + */ +if(!defined('PRADO_DIR')) + define('PRADO_DIR',dirname(__FILE__)); +/** + * Defines the default permission for writable directories and files + */ +if(!defined('PRADO_CHMOD')) + define('PRADO_CHMOD',0777); + +/** + * PradoBase class. + * + * PradoBase implements a few fundamental static methods. + * + * To use the static methods, Use Prado as the class name rather than PradoBase. + * PradoBase is meant to serve as the base class of Prado. The latter might be + * rewritten for customization. + * + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.0 + */ +class PradoBase +{ + /** + * File extension for Prado class files. + */ + const CLASS_FILE_EXT='.php'; + /** + * @var array list of path aliases + */ + private static $_aliases=array('System'=>PRADO_DIR); + /** + * @var array list of namespaces currently in use + */ + private static $_usings=array(); + /** + * @var TApplication the application instance + */ + private static $_application=null; + /** + * @var TLogger logger instance + */ + private static $_logger=null; + + /** + * @return string the version of Prado framework + */ + public static function getVersion() + { + return '3.1.4a'; + } + + /** + * Initializes error handlers. + * This method set error and exception handlers to be functions + * defined in this class. + */ + public static function initErrorHandlers() + { + /** + * Sets error handler to be Prado::phpErrorHandler + */ + set_error_handler(array('PradoBase','phpErrorHandler'),error_reporting()); + /** + * Sets exception handler to be Prado::exceptionHandler + */ + set_exception_handler(array('PradoBase','exceptionHandler')); + } + + /** + * Class autoload loader. + * This method is provided to be invoked within an __autoload() magic method. + * @param string class name + */ + public static function autoload($className) + { + include_once($className.self::CLASS_FILE_EXT); + if(!class_exists($className,false) && !interface_exists($className,false)) + self::fatalError("Class file for '$className' cannot be found."); + } + + /** + * @param integer the type of "powered logo". Valid values include 0 and 1. + * @return string a string that can be displayed on your Web page showing powered-by-PRADO information + */ + public static function poweredByPrado($logoType=0) + { + $logoName=$logoType==1?'powered2':'powered'; + if(self::$_application!==null) + { + $am=self::$_application->getAssetManager(); + $url=$am->publishFilePath(self::getPathOfNamespace('System.'.$logoName,'.gif')); + } + else + $url='http://www.pradosoft.com/images/'.$logoName.'.gif'; + return 'Powered by PRADO'; + } + + public static function metaGenerator() + { + return 'PRADO - http://www.pradosoft.com/'; + } + + /** + * PHP error handler. + * This method should be registered as PHP error handler using + * {@link set_error_handler}. The method throws an exception that + * contains the error information. + * @param integer the level of the error raised + * @param string the error message + * @param string the filename that the error was raised in + * @param integer the line number the error was raised at + */ + public static function phpErrorHandler($errno,$errstr,$errfile,$errline) + { + if(error_reporting()!=0) + throw new TPhpErrorException($errno,$errstr,$errfile,$errline); + } + + /** + * Default exception handler. + * This method should be registered as default exception handler using + * {@link set_exception_handler}. The method tries to use the errorhandler + * module of the Prado application to handle the exception. + * If the application or the module does not exist, it simply echoes the + * exception. + * @param Exception exception that is not caught + */ + public static function exceptionHandler($exception) + { + if(self::$_application!==null && ($errorHandler=self::$_application->getErrorHandler())!==null) + { + $errorHandler->handleError(null,$exception); + } + else + { + echo $exception; + } + exit(1); + } + + /** + * Stores the application instance in the class static member. + * This method helps implement a singleton pattern for TApplication. + * Repeated invocation of this method or the application constructor + * will cause the throw of an exception. + * This method should only be used by framework developers. + * @param TApplication the application instance + * @throws TInvalidOperationException if this method is invoked twice or more. + */ + public static function setApplication($application) + { + if(self::$_application!==null) + throw new TInvalidOperationException('prado_application_singleton_required'); + self::$_application=$application; + } + + /** + * @return TApplication the application singleton, null if the singleton has not be created yet. + */ + public static function getApplication() + { + return self::$_application; + } + + /** + * @return string the path of the framework + */ + public static function getFrameworkPath() + { + return PRADO_DIR; + } + + /** + * Serializes a data. + * The original PHP serialize function has a bug that may not serialize + * properly an object. + * @param mixed data to be serialized + * @return string the serialized data + */ + public static function serialize($data) + { + $arr[0]=$data; + return serialize($arr); + } + + /** + * Unserializes a data. + * The original PHP unserialize function has a bug that may not unserialize + * properly an object. + * @param string data to be unserialized + * @return mixed unserialized data, null if unserialize failed + */ + public static function unserialize($str) + { + $arr=unserialize($str); + return isset($arr[0])?$arr[0]:null; + } + + /** + * Creates a component with the specified type. + * A component type can be either the component class name + * or a namespace referring to the path of the component class file. + * For example, 'TButton', 'System.Web.UI.WebControls.TButton' are both + * valid component type. + * This method can also pass parameters to component constructors. + * All parameters passed to this method except the first one (the component type) + * will be supplied as component constructor parameters. + * @param string component type + * @return TComponent component instance of the specified type + * @throws TInvalidDataValueException if the component type is unknown + */ + public static function createComponent($type) + { + self::using($type); + if(($pos=strrpos($type,'.'))!==false) + $type=substr($type,$pos+1); + if(($n=func_num_args())>1) + { + $args=func_get_args(); + $s='$args[1]'; + for($i=2;$i<$n;++$i) + $s.=",\$args[$i]"; + eval("\$component=new $type($s);"); + return $component; + } + else + return new $type; + } + + /** + * Uses a namespace. + * A namespace ending with an asterisk '*' refers to a directory, otherwise it represents a PHP file. + * If the namespace corresponds to a directory, the directory will be appended + * to the include path. If the namespace corresponds to a file, it will be included (include_once). + * @param string namespace to be used + * @param boolean whether to check the existence of the class after the class file is included + * @throws TInvalidDataValueException if the namespace is invalid + */ + public static function using($namespace,$checkClassExistence=true) + { + if(isset(self::$_usings[$namespace]) || class_exists($namespace,false)) + return; + if(($pos=strrpos($namespace,'.'))===false) // a class name + { + try + { + include_once($namespace.self::CLASS_FILE_EXT); + } + catch(Exception $e) + { + if($checkClassExistence && !class_exists($namespace,false)) + throw new TInvalidOperationException('prado_component_unknown',$namespace,$e->getMessage()); + else + throw $e; + } + } + else if(($path=self::getPathOfNamespace($namespace,self::CLASS_FILE_EXT))!==null) + { + $className=substr($namespace,$pos+1); + if($className==='*') // a directory + { + self::$_usings[$namespace]=$path; + set_include_path(get_include_path().PATH_SEPARATOR.$path); + } + else // a file + { + self::$_usings[$namespace]=$path; + if(!$checkClassExistence || !class_exists($className,false)) + { + try + { + include_once($path); + } + catch(Exception $e) + { + if($checkClassExistence && !class_exists($className,false)) + throw new TInvalidOperationException('prado_component_unknown',$className,$e->getMessage()); + else + throw $e; + } + } + } + } + else + throw new TInvalidDataValueException('prado_using_invalid',$namespace); + } + + /** + * Translates a namespace into a file path. + * The first segment of the namespace is considered as a path alias + * which is replaced with the actual path. The rest segments are + * subdirectory names appended to the aliased path. + * If the namespace ends with an asterisk '*', it represents a directory; + * Otherwise it represents a file whose extension name is specified by the second parameter (defaults to empty). + * Note, this method does not ensure the existence of the resulting file path. + * @param string namespace + * @param string extension to be appended if the namespace refers to a file + * @return string file path corresponding to the namespace, null if namespace is invalid + */ + public static function getPathOfNamespace($namespace,$ext='') + { + if(isset(self::$_usings[$namespace])) + return self::$_usings[$namespace]; + else if(isset(self::$_aliases[$namespace])) + return self::$_aliases[$namespace]; + else + { + $segs=explode('.',$namespace); + $alias=array_shift($segs); + if(($file=array_pop($segs))!==null && ($root=self::getPathOfAlias($alias))!==null) + return rtrim($root.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR ,$segs),'/\\').(($file==='*')?'':DIRECTORY_SEPARATOR.$file.$ext); + else + return null; + } + } + + /** + * @param string alias to the path + * @return string the path corresponding to the alias, null if alias not defined. + */ + public static function getPathOfAlias($alias) + { + return isset(self::$_aliases[$alias])?self::$_aliases[$alias]:null; + } + + protected static function getPathAliases() + { + return self::$_aliases; + } + + /** + * @param string alias to the path + * @param string the path corresponding to the alias + * @throws TInvalidOperationException if the alias is already defined + * @throws TInvalidDataValueException if the path is not a valid file path + */ + public static function setPathOfAlias($alias,$path) + { + if(isset(self::$_aliases[$alias])) + throw new TInvalidOperationException('prado_alias_redefined',$alias); + else if(($rp=realpath($path))!==false && is_dir($rp)) + { + if(strpos($alias,'.')===false) + self::$_aliases[$alias]=$rp; + else + throw new TInvalidDataValueException('prado_aliasname_invalid',$alias); + } + else + throw new TInvalidDataValueException('prado_alias_invalid',$alias,$path); + } + + /** + * Fatal error handler. + * This method displays an error message together with the current call stack. + * The application will exit after calling this method. + * @param string error message + */ + public static function fatalError($msg) + { + echo '

Fatal Error

'; + echo '

'.$msg.'

'; + if(!function_exists('debug_backtrace')) + return; + echo '

Debug Backtrace

'; + echo '
';
+		$index=-1;
+		foreach(debug_backtrace() as $t)
+		{
+			$index++;
+			if($index==0)  // hide the backtrace of this function
+				continue;
+			echo '#'.$index.' ';
+			if(isset($t['file']))
+				echo basename($t['file']) . ':' . $t['line'];
+			else
+			   echo '';
+			echo ' -- ';
+			if(isset($t['class']))
+				echo $t['class'] . $t['type'];
+			echo $t['function'] . '(';
+			if(isset($t['args']) && sizeof($t['args']) > 0)
+			{
+				$count=0;
+				foreach($t['args'] as $item)
+				{
+					if(is_string($item))
+					{
+						$str=htmlentities(str_replace("\r\n", "", $item), ENT_QUOTES);
+						if (strlen($item) > 70)
+							echo "'". substr($str, 0, 70) . "...'";
+						else
+							echo "'" . $str . "'";
+					}
+					else if (is_int($item) || is_float($item))
+						echo $item;
+					else if (is_object($item))
+						echo get_class($item);
+					else if (is_array($item))
+						echo 'array(' . count($item) . ')';
+					else if (is_bool($item))
+						echo $item ? 'true' : 'false';
+					else if ($item === null)
+						echo 'NULL';
+					else if (is_resource($item))
+						echo get_resource_type($item);
+					$count++;
+					if (count($t['args']) > $count)
+						echo ', ';
+				}
+			}
+			echo ")\n";
+		}
+		echo '
'; + exit(1); + } + + /** + * Returns a list of user preferred languages. + * The languages are returned as an array. Each array element + * represents a single language preference. The languages are ordered + * according to user preferences. The first language is the most preferred. + * @return array list of user preferred languages. + */ + public static function getUserLanguages() + { + static $languages=null; + if($languages===null) + { + if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) + $languages[0]='en'; + else + { + $languages=array(); + foreach(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']) as $language) + { + $array=split(';q=',trim($language)); + $languages[trim($array[0])]=isset($array[1])?(float)$array[1]:1.0; + } + arsort($languages); + $languages=array_keys($languages); + if(empty($languages)) + $languages[0]='en'; + } + } + return $languages; + } + + /** + * Returns the most preferred language by the client user. + * @return string the most preferred language by the client user, defaults to English. + */ + public static function getPreferredLanguage() + { + static $language=null; + if($language===null) + { + $langs=Prado::getUserLanguages(); + $lang=explode('-',$langs[0]); + if(empty($lang[0]) || !ctype_alpha($lang[0])) + $language='en'; + else + $language=$lang[0]; + } + return $language; + } + + /** + * Writes a log message. + * This method wraps {@link log()} by checking the application mode. + * When the application is in Debug mode, debug backtrace information is appended + * to the message and the message is logged at DEBUG level. + * When the application is in Performance mode, this method does nothing. + * Otherwise, the message is logged at INFO level. + * @param string message to be logged + * @param string category of the message + * @see log, getLogger + */ + public static function trace($msg,$category='Uncategorized') + { + if(self::$_application && self::$_application->getMode()===TApplicationMode::Performance) + return; + if(!self::$_application || self::$_application->getMode()===TApplicationMode::Debug) + { + $trace=debug_backtrace(); + if(isset($trace[0]['file']) && isset($trace[0]['line'])) + $msg.=" (line {$trace[0]['line']}, {$trace[0]['file']})"; + $level=TLogger::DEBUG; + } + else + $level=TLogger::INFO; + self::log($msg,$level,$category); + } + + /** + * Logs a message. + * Messages logged by this method may be retrieved via {@link TLogger::getLogs} + * and may be recorded in different media, such as file, email, database, using + * {@link TLogRouter}. + * @param string message to be logged + * @param integer level of the message. Valid values include + * TLogger::DEBUG, TLogger::INFO, TLogger::NOTICE, TLogger::WARNING, + * TLogger::ERROR, TLogger::ALERT, TLogger::FATAL. + * @param string category of the message + */ + public static function log($msg,$level=TLogger::INFO,$category='Uncategorized') + { + if(self::$_logger===null) + self::$_logger=new TLogger; + self::$_logger->log($msg,$level,$category); + } + + /** + * @return TLogger message logger + */ + public static function getLogger() + { + if(self::$_logger===null) + self::$_logger=new TLogger; + return self::$_logger; + } + + /** + * Converts a variable into a string representation. + * This method achieves the similar functionality as var_dump and print_r + * but is more robust when handling complex objects such as PRADO controls. + * @param mixed variable to be dumped + * @param integer maximum depth that the dumper should go into the variable. Defaults to 10. + * @param boolean whether to syntax highlight the output. Defaults to false. + * @return string the string representation of the variable + */ + public static function varDump($var,$depth=10,$highlight=false) + { + Prado::using('System.Util.TVarDumper'); + return TVarDumper::dump($var,$depth,$highlight); + } + + /** + * Localize a text to the locale/culture specified in the globalization handler. + * @param string text to be localized. + * @param array a set of parameters to substitute. + * @param string a different catalogue to find the localize text. + * @param string the input AND output charset. + * @return string localized text. + * @see TTranslate::formatter() + * @see TTranslate::init() + */ + public static function localize($text, $parameters=array(), $catalogue=null, $charset=null) + { + Prado::using('System.I18N.Translation'); + $app = Prado::getApplication()->getGlobalization(false); + + $params = array(); + foreach($parameters as $key => $value) + $params['{'.$key.'}'] = $value; + + //no translation handler provided + if($app===null || ($config = $app->getTranslationConfiguration())===null) + return strtr($text, $params); + + if ($catalogue===null) + $catalogue=isset($config['catalogue'])?$config['catalogue']:'messages'; + + Translation::init($catalogue); + + //globalization charset + $appCharset = $app===null ? '' : $app->getCharset(); + + //default charset + $defaultCharset = ($app===null) ? 'UTF-8' : $app->getDefaultCharset(); + + //fall back + if(empty($charset)) $charset = $appCharset; + if(empty($charset)) $charset = $defaultCharset; + + return Translation::formatter($catalogue)->format($text,$params,$catalogue,$charset); + } +} + +/** + * TReflectionClass class. + * This class was originally written to cope with the incompatibility between different PHP versions. + * It is equivalent to ReflectionClass for PHP version >= 5.1.0 + * @author Qiang Xue + * @version $Id$ + * @package System + * @since 3.0 + */ +class TReflectionClass extends ReflectionClass +{ +} + +/** + * Includes the classes essential for PradoBase class + */ +PradoBase::using('System.TComponent'); +PradoBase::using('System.Exceptions.TException'); +PradoBase::using('System.Util.TLogger'); + +?> diff --git a/index.html b/index.html index 834d1ed9..aade2261 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@

PRADO Framework for PHP 5

-

Version 3.1.3, November 1, 2008
+

Version 3.1.4, To be released
Copyright© 2004-2008 by Prado Software
All Rights Reserved.

-- cgit v1.2.3