From 8b157421c027e455a3b52c28f08d328236a7d05f Mon Sep 17 00:00:00 2001 From: xue <> Date: Sat, 19 Nov 2005 15:03:14 +0000 Subject: --- framework/Exceptions/TErrorHandler.php | 102 +++++++++++++++++++++++++++++++-- framework/Exceptions/error503-en.html | 27 +++++++++ framework/Exceptions/error503-zh.html | 27 +++++++++ framework/Exceptions/error503.html | 27 +++++++++ framework/Exceptions/messages.txt | 3 + framework/TApplication.php | 41 ++++++++++++- framework/Web/TAssetManager.php | 4 +- 7 files changed, 222 insertions(+), 9 deletions(-) create mode 100644 framework/Exceptions/error503-en.html create mode 100644 framework/Exceptions/error503-zh.html create mode 100644 framework/Exceptions/error503.html (limited to 'framework') diff --git a/framework/Exceptions/TErrorHandler.php b/framework/Exceptions/TErrorHandler.php index 52ed9935..d053619f 100644 --- a/framework/Exceptions/TErrorHandler.php +++ b/framework/Exceptions/TErrorHandler.php @@ -1,8 +1,63 @@ + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Revision: $ $Date: $ + * @package System.Exceptions + */ +/** + * TErrorHandler class + * + * TErrorHandler handles all PHP user errors and exceptions generated during + * servicing user requests. It displays these errors using different templates + * and if possible, using languages preferred by the client user. + * Note, PHP parsing errors cannot be caught and handled by TErrorHandler. + * + * The templates used to format the error output are stored under System.Exceptions. + * You may choose to use your own templates, should you not like the templates + * provided by Prado. Simply set {@link setErrorTemplatePath ErrorTemplatePath} + * to the path (in namespace format) storing your own templates. + * + * There are two sets of templates, one for errors to be displayed to client users + * (called external errors), one for errors to be displayed to system developers + * (called internal errors). The template file name for the former is + * error[StatusCode][-LanguageCode].html, and for the latter it is + * exception[-LanguageCode].html, where StatusCode refers to response status + * code (e.g. 404, 500) specified when {@link THttpException} is thrown, + * and LanguageCode is the client user preferred language code (e.g. en, zh, de). + * The templates error.html and exception.html are default ones + * that are used if no other appropriate templates are available. + * Note, these templates are not Prado control templates. They are simply + * templates with keywords (e.g. %%ErrorMessage%%, %%Version%%) + * to be replaced with corresponding information. + * + * By default, TErrorHandler is registered with {@link TApplication} as the + * error handler module. It can be accessed via {@link TApplication::getErrorHandler()}. + * You seldom need to deal with the error handler directly. It is mainly used + * by the application object to handle errors. + * + * TErrorHandler may be configured in application configuration file as follows + * + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Exceptions + * @since 3.0 + */ class TErrorHandler extends TComponent implements IModule { + /** + * error template file basename + */ const ERROR_FILE_NAME='error'; + /** + * exception template file basename + */ const EXCEPTION_FILE_NAME='exception'; /** @@ -52,6 +107,12 @@ class TErrorHandler extends TComponent implements IModule return $this->_templatePath; } + /** + * Sets the path storing all error and exception template files. + * The path must be in namespace format, such as System.Exceptions (which is the default). + * @param string template path in namespace format + * @throws TConfigurationException if the template path is invalid + */ public function setErrorTemplatePath($value) { if(($templatePath=Prado::getPathOfNamespace($this->_templatePath))!==null && is_dir($templatePath)) @@ -60,15 +121,25 @@ class TErrorHandler extends TComponent implements IModule throw new TConfigurationException('errorhandler_errortemplatepath_invalid',$value); } + /** + * Handles PHP user errors and exceptions. + * This is the event handler responding to the Error event + * raised in {@link TApplication}. + * The method mainly uses appropriate template to display the error/exception. + * It terminates the application immediately after the error is displayed. + * @param mixed sender of the event + * @param mixed event parameter (if the event is raised by TApplication, it refers to the exception instance) + */ public function handleError($sender,$param) { static $handling=false; // We need to restore error and exception handlers, - // otherwise because errors occured in error handler - // will not be handled properly. + // because within error and exception handlers, new errors and exceptions + // cannot be handled properly by PHP restore_error_handler(); restore_exception_handler(); - if($handling) // ensure that we do not enter infinite loop of error handling + // ensure that we do not enter infinite loop of error handling + if($handling) $this->handleRecursiveError($param); else { @@ -85,6 +156,13 @@ class TErrorHandler extends TComponent implements IModule exit(1); } + /** + * Displays error to the client user. + * THttpException and errors happened when the application is in Debug + * mode will be displayed to the client user. + * @param integer response status code + * @param Exception exception instance + */ protected function handleExternalError($statusCode,$exception) { if(!($exception instanceof THttpException)) @@ -122,6 +200,13 @@ class TErrorHandler extends TComponent implements IModule echo str_replace($fields,$values,$content); } + /** + * Handles error occurs during error handling (called recursive error). + * THttpException and errors happened when the application is in Debug + * mode will be displayed to the client user. + * Error is displayed without using existing template to prevent further errors. + * @param Exception exception instance + */ protected function handleRecursiveError($exception) { if(Prado::getApplication()->getMode()==='Debug') @@ -138,6 +223,13 @@ class TErrorHandler extends TComponent implements IModule } } + /** + * Displays exception information. + * Exceptions are displayed with rich context information, including + * the call stack and the context source code. + * This method is only invoked when application is in Debug mode. + * @param Exception exception instance + */ protected function displayException($exception) { $lines=file($exception->getFile()); @@ -174,9 +266,9 @@ class TErrorHandler extends TComponent implements IModule strftime('%Y-%m-%d %H:%m',time()) ); $lang=Prado::getPreferredLanguage(); - $exceptionFile=dirname(__FILE__).'/'.self::EXCEPTION_FILE_NAME.'-'.$lang.'.html'; + $exceptionFile=$this->_templatePath.'/'.self::EXCEPTION_FILE_NAME.'-'.$lang.'.html'; if(!is_file($exceptionFile)) - $exceptionFile=dirname(__FILE__).'/'.self::EXCEPTION_FILE_NAME.'.html'; + $exceptionFile=$this->_templatePath.'/'.self::EXCEPTION_FILE_NAME.'.html'; if(($content=@file_get_contents($exceptionFile))===false) die("Unable to open exception template file '$exceptionFile'."); echo str_replace($fields,$values,$content); diff --git a/framework/Exceptions/error503-en.html b/framework/Exceptions/error503-en.html new file mode 100644 index 00000000..60527c45 --- /dev/null +++ b/framework/Exceptions/error503-en.html @@ -0,0 +1,27 @@ + + +Service Unavailable + + + + +

Service Unavailable

+

+Our system is currently under maintenance. Please come back later. +

+

+Thank you. +

+
+%%Version%%
+%%Time%% +
+ + \ No newline at end of file diff --git a/framework/Exceptions/error503-zh.html b/framework/Exceptions/error503-zh.html new file mode 100644 index 00000000..b6b5915c --- /dev/null +++ b/framework/Exceptions/error503-zh.html @@ -0,0 +1,27 @@ + + +系统无法提供服务 + + + + +

系统无法提供服务

+

+系统维护中,请稍后再来访问。 +

+

+谢谢。 +

+
+%%Version%%
+%%Time%% +
+ + \ No newline at end of file diff --git a/framework/Exceptions/error503.html b/framework/Exceptions/error503.html new file mode 100644 index 00000000..60527c45 --- /dev/null +++ b/framework/Exceptions/error503.html @@ -0,0 +1,27 @@ + + +Service Unavailable + + + + +

Service Unavailable

+

+Our system is currently under maintenance. Please come back later. +

+

+Thank you. +

+
+%%Version%%
+%%Time%% +
+ + \ No newline at end of file diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 9ed1160b..17e1e627 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -11,6 +11,7 @@ application_configfile_inexistent = Application configuration file '%s' does no application_module_existing = Application module '%s' cannot be registered twice. application_service_invalid = Service '%s' must implement IService interface. application_service_unknown = Requested service '%s' is not defined. +application_service_unavailable = Service Unavailable. appconfig_aliaspath_invalid = Application configuration uses an invalid file path "%s". appconfig_aliasid_required = Application configuration element must have an "id" attribute. @@ -55,6 +56,8 @@ memcache_connection_failed = TMemCache failed to connect to memcache server % memcache_host_unchangeable = TMemCache.Host cannot be modified after the module is initialized. memcache_port_unchangeable = TMemCache.Port cannot be modified after the module is initialized. +errorhandler_errortemplatepath_invalid = TErrorHandler.ErrorTemplatePath '%s' is invalid. Make sure it is in namespace form and points to a valid directory containing error template files. + pageservice_page_unknown = Page '%s' Not Found diff --git a/framework/TApplication.php b/framework/TApplication.php index 7c9de44a..665ed076 100644 --- a/framework/TApplication.php +++ b/framework/TApplication.php @@ -41,6 +41,9 @@ require_once(PRADO_DIR.'/Web/Services/TPageService.php'); * TApplication coordinates modules and services, and serves as a configuration * context for all Prado components. * + * TApplication uses a configuration file to specify the settings of + * the application, the modules, the services, the parameters, and so on. + * * TApplication adopts a modular structure. A TApplication instance is a composition * of multiple modules. A module is an instance of class implementing * {@link IModule} interface. Each module accomplishes certain functionalities @@ -50,12 +53,44 @@ require_once(PRADO_DIR.'/Web/Services/TPageService.php'); * Modules cooperate with each other to serve a user request by following * a sequence of lifecycles predefined in TApplication. * + * TApplication has four modes that can be changed by setting {@link setMode Mode} + * property (in the application configuration file). + * - Off mode will prevent the application from serving user requests. + * - Debug mode is mainly used during application development. It ensures + * the cache is always up-to-date if caching is enabled. It also allows + * exceptions are displayed with rich context information if they occur. + * - Normal mode is mainly used during production stage. Exception information + * will only be recorded in system error logs. The cache is ensured to be + * up-to-date if it is enabled. + * - Performance mode is similar to Normal mode except that it + * does not ensure the cache is up-to-date. + * * TApplication dispatches each user request to a particular service which * finishes the actual work for the request with the aid from the application * modules. * - * TApplication uses a configuration file to specify the settings of - * the application, the modules, the services, the parameters, and so on. + * TApplication maintains a lifecycle with the following stages: + * - [construct] : construction of the application instance + * - [initApplication] : load application configuration and instantiate modules and the requested service + * - BeginRequest : this event happens right after application initialization + * - Authentication : this event happens when authentication is needed for the current request + * - PostAuthentication : this event happens right after the authentication is done for the current request + * - Authorization : this event happens when authorization is needed for the current request + * - PostAuthorization : this event happens right after the authorization is done for the current request + * - LoadState : this event happens when application state needs to be loaded + * - PostLoadState : this event happens right after the application state is loaded + * - PreRunService : this event happens right before the requested service is to run + * - RunService : this event happens when the requested service runs + * - PostRunService : this event happens right after the requested service finishes running + * - SaveState : this event happens when application needs to save its state + * - PostSaveState : this event happens right after the application saves its state + * - EndRequest : this is the last stage an application runs + * - [destruct] : destruction of the application instance + * Modules and services can attach their methods to one or several of the above + * events and do appropriate processing when the events are raised. By this way, + * the application is able to coordinate the activities of modules and services + * in the above order. To terminate an application before the whole lifecycle + * completes, call {@link completeRequest}. * * Examples: * - Create and run a Prado application: @@ -203,6 +238,8 @@ class TApplication extends TComponent $this->_requestCompleted=false; while($this->_step<$n) { + if($this->_mode==='Off') + throw new THttpException(503,'application_service_unavailable'); $method='on'.self::$_steps[$this->_step]; $this->$method($this); if($this->_requestCompleted && $this->_step<$n-1) diff --git a/framework/Web/TAssetManager.php b/framework/Web/TAssetManager.php index fa9e649e..4dfcdf5b 100644 --- a/framework/Web/TAssetManager.php +++ b/framework/Web/TAssetManager.php @@ -19,8 +19,8 @@ * TAssetManager will copy the file to be published into a web-accessible * directory. The default base directory for storing the file is "assets", which * should be under the application directory. This can be changed by setting - * the BasePath property together with the BaseUrl property that refers to - * the URL for accessing the base path. + * the {@link setBasePath BasePath} property together with the + * {@link setBaseUrl BaseUrl} property that refers to the URL for accessing the base path. * * By default, TAssetManager will not publish a file or directory if it already * exists in the publishing directory and has an older modification time. -- cgit v1.2.3