summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY4
-rw-r--r--UPGRADE358
-rw-r--r--framework/PradoBase.php1238
-rw-r--r--index.html2
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:
- <translation type="Database" source="db1" autosave="true" cache="false" />
- 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 <span> 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 <div> instead of <span>
-- 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 <span> 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
- <com:TRequiredFieldValidator ClientSide.OnSuccess="xxx" />
- 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:
+ <translation type="Database" source="db1" autosave="true" cache="false" />
+ 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 <span> 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 <div> instead of <span>
+- 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 <span> 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
+ <com:TRequiredFieldValidator ClientSide.OnSuccess="xxx" />
+ 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 @@
-<?php
-/**
- * PradoBase class file.
- *
- * This is the file that establishes the PRADO component model
- * and error handling mechanism.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 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 <qiang.xue@gmail.com>
- * @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 '<a title="Powered by PRADO" href="http://www.pradosoft.com/" target="_blank"><img src="'.$url.'" style="border-width:0px;" alt="Powered by PRADO" /></a>';
- }
-
- 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 '<h1>Fatal Error</h1>';
- echo '<p>'.$msg.'</p>';
- if(!function_exists('debug_backtrace'))
- return;
- echo '<h2>Debug Backtrace</h2>';
- echo '<pre>';
- $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 '<PHP inner-code>';
- 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 '</pre>';
- 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 <qiang.xue@gmail.com>
- * @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');
-
-?>
+<?php
+/**
+ * PradoBase class file.
+ *
+ * This is the file that establishes the PRADO component model
+ * and error handling mechanism.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 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 <qiang.xue@gmail.com>
+ * @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 '<a title="Powered by PRADO" href="http://www.pradosoft.com/" target="_blank"><img src="'.$url.'" style="border-width:0px;" alt="Powered by PRADO" /></a>';
+ }
+
+ 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 '<h1>Fatal Error</h1>';
+ echo '<p>'.$msg.'</p>';
+ if(!function_exists('debug_backtrace'))
+ return;
+ echo '<h2>Debug Backtrace</h2>';
+ echo '<pre>';
+ $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 '<PHP inner-code>';
+ 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 '</pre>';
+ 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 <qiang.xue@gmail.com>
+ * @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 @@
<body>
<h1>PRADO Framework for PHP 5 </h1>
-<p>Version 3.1.3, November 1, 2008<br>
+<p>Version 3.1.4, To be released<br>
Copyright&copy; 2004-2008 by <a href="http://www.pradosoft.com/">Prado Software</a><br>
All Rights Reserved.
</p>