diff --git a/framework/YiiBase.php b/framework/YiiBase.php
index 9d3698b..1230053 100644
--- a/framework/YiiBase.php
+++ b/framework/YiiBase.php
@@ -121,8 +121,8 @@ class YiiBase
*
* To import a class or a directory, one can use either path alias or class name (can be namespaced):
*
- * - `@app/components/GoogleMap`: importing the `GoogleMap` class with a path alias;
- * - `@app/components/*`: importing the whole `components` directory with a path alias;
+ * - `@application/components/GoogleMap`: importing the `GoogleMap` class with a path alias;
+ * - `@application/components/*`: importing the whole `components` directory with a path alias;
* - `GoogleMap`: importing the `GoogleMap` class with a class name. [[autoload()]] will be used
* when this class is used for the first time.
*
@@ -322,12 +322,12 @@ class YiiBase
* the class. For example,
*
* - `\app\components\GoogleMap`: fully-qualified namespaced class.
- * - `@app/components/GoogleMap`: an alias
+ * - `@application/components/GoogleMap`: an alias
*
* Below are some usage examples:
*
* ~~~
- * $object = \Yii::createObject('@app/components/GoogleMap');
+ * $object = \Yii::createObject('@application/components/GoogleMap');
* $object = \Yii::createObject(array(
* 'class' => '\app\components\GoogleMap',
* 'apiKey' => 'xyz',
diff --git a/framework/base/Application.php b/framework/base/Application.php
index c618faa..6203d11 100644
--- a/framework/base/Application.php
+++ b/framework/base/Application.php
@@ -10,8 +10,8 @@
namespace yii\base;
use Yii;
+use yii\util\FileHelper;
use yii\base\InvalidCallException;
-use yii\util\StringHelper;
/**
* Application is the base class for all application classes.
@@ -37,7 +37,7 @@ use yii\util\StringHelper;
* Yii framework messages. This application component is dynamically loaded when needed.
*
*
- * Application will undergo the following lifecycles when processing a user request:
+ * Application will undergo the following life cycles when processing a user request:
*
* - load application configuration;
* - set up class autoloader and error handling;
@@ -50,28 +50,6 @@ use yii\util\StringHelper;
* Starting from lifecycle 3, if a PHP error or an uncaught exception occurs,
* the application will switch to its error handling logic and jump to step 6 afterwards.
*
- * @property string $basePath Returns the root path of the application.
- * @property CCache $cache Returns the cache component.
- * @property CPhpMessageSource $coreMessages Returns the core message translations.
- * @property CDateFormatter $dateFormatter Returns the locale-dependent date formatter.
- * @property \yii\db\Connection $db Returns the database connection component.
- * @property CErrorHandler $errorHandler Returns the error handler component.
- * @property string $extensionPath Returns the root directory that holds all third-party extensions.
- * @property string $id Returns the unique identifier for the application.
- * @property string $language Returns the language that the user is using and the application should be targeted to.
- * @property CLocale $locale Returns the locale instance.
- * @property string $localeDataPath Returns the directory that contains the locale data.
- * @property CMessageSource $messages Returns the application message translations component.
- * @property CNumberFormatter $numberFormatter The locale-dependent number formatter.
- * @property CHttpRequest $request Returns the request component.
- * @property string $runtimePath Returns the directory that stores runtime files.
- * @property CSecurityManager $securityManager Returns the security manager component.
- * @property CStatePersister $statePersister Returns the state persister component.
- * @property string $timeZone Returns the time zone used by this application.
- * @property UrlManager $urlManager Returns the URL manager component.
- * @property string $baseUrl Returns the relative URL for the application
- * @property string $homeUrl the homepage URL
- *
* @author Qiang Xue
* @since 2.0
*/
@@ -134,7 +112,7 @@ class Application extends Module
$this->setBasePath($basePath);
$this->registerDefaultAliases();
$this->registerCoreComponents();
- parent::__construct($id, $this, $config);
+ Component::__construct($config);
}
/**
@@ -204,27 +182,6 @@ class Application extends Module
}
/**
- * Runs a controller with the given route and parameters.
- * @param string $route the route (e.g. `post/create`)
- * @param array $params the parameters to be passed to the controller action
- * @return integer the exit status (0 means normal, non-zero values mean abnormal)
- * @throws InvalidRequestException if the route cannot be resolved into a controller
- */
- public function runController($route, $params = array())
- {
- $result = $this->createController($route);
- if ($result === false) {
- throw new InvalidRequestException(Yii::t('yii', 'Unable to resolve the request.'));
- }
-
- $priorController = $this->controller;
- $this->controller = $controllerObject;
- $status = $controllerObject->run($action, $params);
- $this->controller = $priorController;
- return $status;
- }
-
- /**
* Returns the directory that stores runtime files.
* @return string the directory that stores runtime files. Defaults to 'protected/runtime'.
*/
@@ -239,15 +196,15 @@ class Application extends Module
/**
* Sets the directory that stores runtime files.
* @param string $path the directory that stores runtime files.
- * @throws InvalidCallException if the directory does not exist or is not writable
+ * @throws InvalidConfigException if the directory does not exist or is not writable
*/
public function setRuntimePath($path)
{
- $p = Yii::getAlias($path);
- if ($p === false || !is_dir($p) || !is_writable($path)) {
- throw new InvalidCallException("Application runtime path \"$path\" is invalid. Please make sure it is a directory writable by the Web server process.");
- } else {
+ $p = FileHelper::ensureDirectory($path);
+ if (is_writable($p)) {
$this->_runtimePath = $p;
+ } else {
+ throw new InvalidConfigException("Runtime path must be writable by the Web server process: $path");
}
}
@@ -296,34 +253,61 @@ class Application extends Module
date_default_timezone_set($value);
}
- /**
- * Returns the locale instance.
- * @param string $localeID the locale ID (e.g. en_US). If null, the {@link getLanguage application language ID} will be used.
- * @return CLocale the locale instance
- */
- public function getLocale($localeID = null)
- {
- return CLocale::getInstance($localeID === null ? $this->getLanguage() : $localeID);
- }
-
- /**
- * @return CNumberFormatter the locale-dependent number formatter.
- * The current {@link getLocale application locale} will be used.
- */
- public function getNumberFormatter()
- {
- return $this->getLocale()->getNumberFormatter();
- }
-
- /**
- * Returns the locale-dependent date formatter.
- * @return CDateFormatter the locale-dependent date formatter.
- * The current {@link getLocale application locale} will be used.
- */
- public function getDateFormatter()
- {
- return $this->getLocale()->getDateFormatter();
- }
+// /**
+// * Returns the security manager component.
+// * @return SecurityManager the security manager application component.
+// */
+// public function getSecurityManager()
+// {
+// return $this->getComponent('securityManager');
+// }
+//
+// /**
+// * Returns the locale instance.
+// * @param string $localeID the locale ID (e.g. en_US). If null, the {@link getLanguage application language ID} will be used.
+// * @return CLocale the locale instance
+// */
+// public function getLocale($localeID = null)
+// {
+// return CLocale::getInstance($localeID === null ? $this->getLanguage() : $localeID);
+// }
+//
+// /**
+// * @return CNumberFormatter the locale-dependent number formatter.
+// * The current {@link getLocale application locale} will be used.
+// */
+// public function getNumberFormatter()
+// {
+// return $this->getLocale()->getNumberFormatter();
+// }
+//
+// /**
+// * Returns the locale-dependent date formatter.
+// * @return CDateFormatter the locale-dependent date formatter.
+// * The current {@link getLocale application locale} will be used.
+// */
+// public function getDateFormatter()
+// {
+// return $this->getLocale()->getDateFormatter();
+// }
+//
+// /**
+// * Returns the core message translations component.
+// * @return \yii\i18n\MessageSource the core message translations
+// */
+// public function getCoreMessages()
+// {
+// return $this->getComponent('coreMessages');
+// }
+//
+// /**
+// * Returns the application message translations component.
+// * @return \yii\i18n\MessageSource the application message translations
+// */
+// public function getMessages()
+// {
+// return $this->getComponent('messages');
+// }
/**
* Returns the database connection component.
@@ -353,15 +337,6 @@ class Application extends Module
}
/**
- * Returns the security manager component.
- * @return SecurityManager the security manager application component.
- */
- public function getSecurityManager()
- {
- return $this->getComponent('securityManager');
- }
-
- /**
* Returns the cache component.
* @return \yii\caching\Cache the cache application component. Null if the component is not enabled.
*/
@@ -371,24 +346,6 @@ class Application extends Module
}
/**
- * Returns the core message translations component.
- * @return \yii\i18n\MessageSource the core message translations
- */
- public function getCoreMessages()
- {
- return $this->getComponent('coreMessages');
- }
-
- /**
- * Returns the application message translations component.
- * @return \yii\i18n\MessageSource the application message translations
- */
- public function getMessages()
- {
- return $this->getComponent('messages');
- }
-
- /**
* Returns the request component.
* @return Request the request component
*/
@@ -417,15 +374,6 @@ class Application extends Module
'errorHandler' => array(
'class' => 'yii\base\ErrorHandler',
),
- 'request' => array(
- 'class' => 'yii\base\Request',
- ),
- 'response' => array(
- 'class' => 'yii\base\Response',
- ),
- 'format' => array(
- 'class' => 'yii\base\Formatter',
- ),
'coreMessages' => array(
'class' => 'yii\i18n\PhpMessageSource',
'language' => 'en_us',
@@ -442,117 +390,4 @@ class Application extends Module
),
));
}
-
- /**
- * Performs a controller action specified by a route.
- * This method parses the specified route and creates the corresponding controller and action
- * instances under the context of the specified module. It then runs the created action
- * with the given parameters.
- * @param string $route the route that specifies the action.
- * @param array $params the parameters to be passed to the action
- * @param Module $module the module which serves as the context of the route
- * @return integer the action
- * @throws InvalidConfigException if the module's defaultRoute is empty or the controller's defaultAction is empty
- * @throws InvalidRequestException if the requested route cannot be resolved into an action successfully
- */
- public function runAction($route, $params = array(), $module = null)
- {
- if ($module === null) {
- $module = $this;
- }
- $route = trim($route, '/');
- if ($route === '') {
- $route = trim($module->defaultRoute, '/');
- if ($route == '') {
- throw new InvalidConfigException(get_class($module) . '::defaultRoute cannot be empty.');
- }
- }
- if (($pos = strpos($route, '/')) !== false) {
- $id = substr($route, 0, $pos);
- $route = substr($route, $pos + 1);
- } else {
- $id = $route;
- $route = '';
- }
-
- $childModule = $module->getModule($id);
- if ($childModule !== null) {
- return $this->runAction($route, $params, $childModule);
- }
-
- $controller = $this->createController($id, $module);
- if ($controller !== null) {
- if ($route === '') {
- $route = $controller->defaultAction;
- if ($route == '') {
- throw new InvalidConfigException(get_class($controller) . '::defaultAction cannot be empty.');
- }
- }
-
- $action = $this->createAction($route, $controller);
- if ($action !== null) {
- return $action->runWithParams($params);
- }
- }
-
- throw new InvalidRequestException("Unable to resolve the request: $route");
- }
-
-
- /**
- * Creates a controller instance based on the controller ID.
- *
- * The controller is created within the given module. The method first attempts to
- * create the controller based on the [[controllerMap]] of the module. If not available,
- * it will look for the controller class under the [[controllerPath]] and create an
- * instance of it.
- *
- * @param string $id the controller ID
- * @param Module $module the module that owns the controller
- * @return Controller the newly created controller instance
- */
- public function createController($id, $module)
- {
- if (isset($module->controllerMap[$id])) {
- return Yii::createObject($module->controllerMap[$id], $id, $module);
- } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) {
- $className = StringHelper::id2camel($id) . 'Controller';
- $classFile = $module->controllerPath . DIRECTORY_SEPARATOR . $className . '.php';
- if (is_file($classFile)) {
- $className = $module->controllerNamespace . '\\' . $className;
- if (!class_exists($className, false)) {
- require($classFile);
- }
- if (class_exists($className, false) && is_subclass_of($className, '\yii\base\Controller')) {
- return new $className($id, $module);
- }
- }
- }
- return null;
- }
-
- /**
- * Creates an action based on the given action ID.
- * The action is created within the given controller. The method first attempts to
- * create the action based on [[Controller::actions()]]. If not available,
- * it will look for the inline action method within the controller.
- * @param string $id the action ID
- * @param Controller $controller the controller that owns the action
- * @return Action the newly created action instance
- */
- public function createAction($id, $controller)
- {
- if (isset($controller->actionMap[$id])) {
- return Yii::createObject($controller->actionMap[$id], $id, $controller);
- } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) {
- $methodName = 'action' . StringHelper::id2camel($id);
- if (method_exists($controller, $methodName)) {
- $method = new \ReflectionMethod($controller, $methodName);
- if ($method->getName() === $methodName) {
- return new InlineAction($id, $controller);
- }
- }
- }
- return null;
- }
}
diff --git a/framework/base/Controller.php b/framework/base/Controller.php
index d62cc35..79ad574 100644
--- a/framework/base/Controller.php
+++ b/framework/base/Controller.php
@@ -9,6 +9,9 @@
namespace yii\base;
+use Yii;
+use yii\util\StringHelper;
+
/**
* Controller is the base class for classes containing controller logic.
*
@@ -27,6 +30,10 @@ namespace yii\base;
*/
class Controller extends Component
{
+ const EVENT_AUTHORIZE = 'authorize';
+ const EVENT_BEFORE_ACTION = 'beforeAction';
+ const EVENT_AFTER_ACTION = 'afterAction';
+
/**
* @var string the ID of this controller
*/
@@ -91,65 +98,138 @@ class Controller extends Component
}
/**
- * Runs the controller with the specified action and parameters.
- * @param Action|string $action the action to be executed. This can be either an action object
- * or the ID of the action.
+ * Runs an action with the specified action ID and parameters.
+ * If the action ID is empty, the method will use [[defaultAction]].
+ * @param string $id the ID of the action to be executed.
* @param array $params the parameters (name-value pairs) to be passed to the action.
- * If null, the result of [[getActionParams()]] will be used as action parameters.
- * @return integer the exit status of the action. 0 means normal, other values mean abnormal.
- * @see missingAction
+ * @return integer the status of the action execution. 0 means normal, other values mean abnormal.
+ * @throws InvalidRouteException if the requested action ID cannot be resolved into an action successfully.
* @see createAction
*/
- public function run($action, $params = null)
+ public function runAction($id, $params = array())
{
- if (is_string($action)) {
- if (($a = $this->createAction($action)) !== null) {
- $action = $a;
- } else {
- $this->missingAction($action);
- return 1;
- }
+ if ($id === '') {
+ $id = $this->defaultAction;
}
- $priorAction = $this->action;
- $this->action = $action;
+ $action = $this->createAction($id);
+ if ($action !== null) {
+ $oldAction = $this->action;
+ $this->action = $action;
- if ($this->authorize($action) && $this->beforeAction($action)) {
- if ($params === null) {
- $params = $this->getActionParams();
+ if ($this->authorize($action) && $this->beforeAction($action)) {
+ $status = $action->runWithParams($params);
+ $this->afterAction($action);
+ } else {
+ $status = 1;
}
- $status = $action->runWithParams($params);
- $this->afterAction($action);
+
+ $this->action = $oldAction;
+
+ return $status;
} else {
- $status = 1;
+ throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $id);
}
+ }
- $this->action = $priorAction;
+ /**
+ * Runs a request specified in terms of a route.
+ * The route can be either an ID of an action within this controller or a complete route consisting
+ * of module IDs, controller ID and action ID. If the route starts with a slash '/', the parsing of
+ * the route will start from the application; otherwise, it will start from the parent module of this controller.
+ * @param string $route the route to be handled, e.g., 'view', 'comment/view', '/admin/comment/view'.
+ * @param array $params the parameters to be passed to the action.
+ * @return integer the status code returned by the action execution. 0 means normal, and other values mean abnormal.
+ * @see runAction
+ * @see forward
+ */
+ public function run($route, $params = array())
+ {
+ $pos = strpos($route, '/');
+ if ($pos === false) {
+ return $this->runAction($route, $params);
+ } elseif ($pos > 0) {
+ return $this->module->runAction($route, $params);
+ } else {
+ return \Yii::$application->runAction($route, $params);
+ }
+ }
- return $status;
+ /**
+ * Forwards the current execution flow to handle a new request specified by a route.
+ * The only difference between this method and [[run()]] is that after calling this method,
+ * the application will exit.
+ * @param string $route the route to be handled, e.g., 'view', 'comment/view', '/admin/comment/view'.
+ * @param array $params the parameters to be passed to the action.
+ * @return integer the status code returned by the action execution. 0 means normal, and other values mean abnormal.
+ * @see run
+ */
+ public function forward($route, $params = array())
+ {
+ $status = $this->run($route, $params);
+ exit($status);
}
/**
- * Creates the action instance based on the action ID.
- * The action can be either an inline action or an object.
- * The latter is created by looking up the action map specified in [[actions]].
- * @param string $actionID ID of the action. If empty, it will take the value of [[defaultAction]].
- * @return Action the action instance, null if the action does not exist.
- * @see actions
+ * Creates an action based on the given action ID.
+ * The method first checks if the action ID has been declared in [[actions()]]. If so,
+ * it will use the configuration declared there to create the action object.
+ * If not, it will look for a controller method whose name is in the format of `actionXyz`
+ * where `Xyz` stands for the action ID. If found, an [[InlineAction]] representing that
+ * method will be created and returned.
+ * @param string $id the action ID
+ * @return Action the newly created action instance. Null if the ID doesn't resolve into any action.
*/
- public function createAction($actionID)
+ public function createAction($id)
{
- if ($actionID === '') {
- $actionID = $this->defaultAction;
- }
- $actions = $this->actions();
- if (isset($actions[$actionID])) {
- return \Yii::createObject($actions[$actionID], $actionID, $this);
- } elseif (method_exists($this, 'action' . $actionID)) {
- return new InlineAction($actionID, $this);
- } else {
- return null;
+ $actionMap = $this->actions();
+ if (isset($actionMap[$id])) {
+ return Yii::createObject($actionMap[$id], $id, $this);
+ } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) {
+ $methodName = 'action' . StringHelper::id2camel($id);
+ if (method_exists($this, $methodName)) {
+ $method = new \ReflectionMethod($this, $methodName);
+ if ($method->getName() === $methodName) {
+ return new InlineAction($id, $this);
+ }
+ }
}
+ return null;
+ }
+
+ /**
+ * This method is invoked when checking the access for the action to be executed.
+ * @param Action $action the action to be executed.
+ * @return boolean whether the action is allowed to be executed.
+ */
+ public function authorize($action)
+ {
+ $event = new ActionEvent($action);
+ $this->trigger(self::EVENT_AUTHORIZE, $event);
+ return $event->isValid;
+ }
+
+ /**
+ * This method is invoked right before an action is to be executed (after all possible filters.)
+ * You may override this method to do last-minute preparation for the action.
+ * @param Action $action the action to be executed.
+ * @return boolean whether the action should continue to be executed.
+ */
+ public function beforeAction($action)
+ {
+ $event = new ActionEvent($action);
+ $this->trigger(self::EVENT_BEFORE_ACTION, $event);
+ return $event->isValid;
+ }
+
+ /**
+ * This method is invoked right after an action is executed.
+ * You may override this method to do some postprocessing for the action.
+ * @param Action $action the action just executed.
+ */
+ public function afterAction($action)
+ {
+ $this->trigger(self::EVENT_AFTER_ACTION, new ActionEvent($action));
}
/**
@@ -217,67 +297,6 @@ class Controller extends Component
return $this->action !== null ? $this->getUniqueId() . '/' . $this->action->id : $this->getUniqueId();
}
- /**
- * Processes the request using another controller action.
- * @param string $route the route of the new controller action. This can be an action ID, or a complete route
- * with module ID (optional in the current module), controller ID and action ID. If the former,
- * the action is assumed to be located within the current controller.
- * @param array $params the parameters to be passed to the action.
- * If null, the result of [[getActionParams()]] will be used as action parameters.
- * Note that the parameters must be name-value pairs with the names corresponding to
- * the parameter names as declared by the action.
- * @param boolean $exit whether to end the application after this call. Defaults to true.
- */
- public function forward($route, $params = array(), $exit = true)
- {
- if (strpos($route, '/') === false) {
- $status = $this->run($route, $params);
- } else {
- if ($route[0] !== '/' && !$this->module instanceof Application) {
- $route = '/' . $this->module->getUniqueId() . '/' . $route;
- }
- $status = \Yii::$application->runController($route, $params);
- }
- if ($exit) {
- \Yii::$application->end($status);
- }
- }
-
- /**
- * This method is invoked when checking the access for the action to be executed.
- * @param Action $action the action to be executed.
- * @return boolean whether the action is allowed to be executed.
- */
- public function authorize($action)
- {
- $event = new ActionEvent($action);
- $this->trigger(__METHOD__, $event);
- return $event->isValid;
- }
-
- /**
- * This method is invoked right before an action is to be executed (after all possible filters.)
- * You may override this method to do last-minute preparation for the action.
- * @param Action $action the action to be executed.
- * @return boolean whether the action should continue to be executed.
- */
- public function beforeAction($action)
- {
- $event = new ActionEvent($action);
- $this->trigger(__METHOD__, $event);
- return $event->isValid;
- }
-
- /**
- * This method is invoked right after an action is executed.
- * You may override this method to do some postprocessing for the action.
- * @param Action $action the action just executed.
- */
- public function afterAction($action)
- {
- $this->trigger(__METHOD__, new ActionEvent($action));
- }
-
public function render($view, $params = array())
{
return $this->createView()->render($view, $params);
diff --git a/framework/base/InvalidRouteException.php b/framework/base/InvalidRouteException.php
new file mode 100644
index 0000000..8e82b40
--- /dev/null
+++ b/framework/base/InvalidRouteException.php
@@ -0,0 +1,21 @@
+
+ * @since 2.0
+ */
+class InvalidRouteException extends \Exception
+{
+}
+
diff --git a/framework/base/Module.php b/framework/base/Module.php
index 0539cdc..23bd577 100644
--- a/framework/base/Module.php
+++ b/framework/base/Module.php
@@ -16,13 +16,19 @@ use yii\util\FileHelper;
/**
* Module is the base class for module and application classes.
*
- * Module mainly manages application components and sub-modules that belongs to a module.
+ * A module represents a sub-application which contains MVC elements by itself, such as
+ * models, views, controllers, etc.
+ *
+ * A module may consist of [[modules|sub-modules]].
+ *
+ * [[components|Components]] may be registered with the module so that they are globally
+ * accessible within the module.
*
* @property string $uniqueId An ID that uniquely identifies this module among all modules within
* the current application.
* @property string $basePath The root directory of the module. Defaults to the directory containing the module class.
* @property array $modules The configuration of the currently installed modules (module ID => configuration).
- * @property array $components The application components (indexed by their IDs).
+ * @property array $components The components (indexed by their IDs) registered within this module.
* @property array $import List of aliases to be imported. This property is write-only.
* @property array $aliases List of aliases to be defined. This property is write-only.
*
@@ -36,7 +42,7 @@ abstract class Module extends Component
*/
public $params = array();
/**
- * @var array the IDs of the application components that should be preloaded when this module is created.
+ * @var array the IDs of the components that should be preloaded when this module is created.
*/
public $preload = array();
/**
@@ -88,27 +94,27 @@ abstract class Module extends Component
/**
* @var string the root directory of the module.
*/
- protected $_basePath;
+ private $_basePath;
/**
* @var string the root directory that contains view files for this module
*/
- protected $_viewPath;
+ private $_viewPath;
/**
* @var string the root directory that contains layout view files for this module.
*/
- protected $_layoutPath;
+ private $_layoutPath;
/**
* @var string the directory containing controller classes in the module.
*/
- protected $_controllerPath;
+ private $_controllerPath;
/**
* @var array child modules of this module
*/
- protected $_modules = array();
+ private $_modules = array();
/**
- * @var array application components of this module
+ * @var array components registered under this module
*/
- protected $_components = array();
+ private $_components = array();
/**
* Constructor.
@@ -125,9 +131,9 @@ abstract class Module extends Component
/**
* Getter magic method.
- * This method is overridden to support accessing application components
+ * This method is overridden to support accessing components
* like reading module properties.
- * @param string $name application component or property name
+ * @param string $name component or property name
* @return mixed the named property value
*/
public function __get($name)
@@ -142,7 +148,7 @@ abstract class Module extends Component
/**
* Checks if a property value is null.
* This method overrides the parent implementation by checking
- * if the named application component is loaded.
+ * if the named component is loaded.
* @param string $name the property name or the event name
* @return boolean whether the property value is null
*/
@@ -163,7 +169,7 @@ abstract class Module extends Component
*/
public function init()
{
- \Yii::setAlias('@' . $this->id, $this->getBasePath());
+ Yii::setAlias('@' . $this->id, $this->getBasePath());
$this->preloadComponents();
}
@@ -282,19 +288,19 @@ abstract class Module extends Component
/**
* Imports the specified path aliases.
* This method is provided so that you can import a set of path aliases when configuring a module.
- * The path aliases will be imported by calling [[\Yii::import()]].
+ * The path aliases will be imported by calling [[Yii::import()]].
* @param array $aliases list of path aliases to be imported
*/
public function setImport($aliases)
{
foreach ($aliases as $alias) {
- \Yii::import($alias);
+ Yii::import($alias);
}
}
/**
* Defines path aliases.
- * This method calls [[\Yii::setAlias()]] to register the path aliases.
+ * This method calls [[Yii::setAlias()]] to register the path aliases.
* This method is provided so that you can define path aliases when configuring a module.
* @param array $aliases list of path aliases to be defined. The array keys are alias names
* (must start with '@') and the array values are the corresponding paths or aliases.
@@ -302,7 +308,7 @@ abstract class Module extends Component
*
* ~~~
* array(
- * '@models' => '@app/models', // an existing alias
+ * '@models' => '@application/models', // an existing alias
* '@backend' => __DIR__ . '/../backend', // a directory
* )
* ~~~
@@ -310,7 +316,7 @@ abstract class Module extends Component
public function setAliases($aliases)
{
foreach ($aliases as $name => $alias) {
- \Yii::setAlias($name, $alias);
+ Yii::setAlias($name, $alias);
}
}
@@ -339,8 +345,8 @@ abstract class Module extends Component
if ($this->_modules[$id] instanceof Module) {
return $this->_modules[$id];
} elseif ($load) {
- \Yii::trace("Loading \"$id\" module", __CLASS__);
- return $this->_modules[$id] = \Yii::createObject($this->_modules[$id], $id, $this);
+ Yii::trace("Loading module: $id", __CLASS__);
+ return $this->_modules[$id] = Yii::createObject($this->_modules[$id], $id, $this);
}
}
return null;
@@ -393,7 +399,7 @@ abstract class Module extends Component
*
* Each sub-module should be specified as a name-value pair, where
* name refers to the ID of the module and value the module or a configuration
- * array that can be used to create the module. In the latter case, [[\Yii::createObject()]]
+ * array that can be used to create the module. In the latter case, [[Yii::createObject()]]
* will be used to create the module.
*
* If a new sub-module has the same ID as an existing one, the existing one will be overwritten silently.
@@ -423,8 +429,8 @@ abstract class Module extends Component
/**
* Checks whether the named component exists.
- * @param string $id application component ID
- * @return boolean whether the named application component exists. Both loaded and unloaded components
+ * @param string $id component ID
+ * @return boolean whether the named component exists. Both loaded and unloaded components
* are considered.
*/
public function hasComponent($id)
@@ -433,11 +439,10 @@ abstract class Module extends Component
}
/**
- * Retrieves the named application component.
- * @param string $id application component ID (case-sensitive)
+ * Retrieves the named component.
+ * @param string $id component ID (case-sensitive)
* @param boolean $load whether to load the component if it is not yet loaded.
- * @return Component|null the application component instance, null if the application component
- * does not exist.
+ * @return Component|null the component instance, null if the component does not exist.
* @see hasComponent()
*/
public function getComponent($id, $load = true)
@@ -446,22 +451,22 @@ abstract class Module extends Component
if ($this->_components[$id] instanceof Component) {
return $this->_components[$id];
} elseif ($load) {
- \Yii::trace("Loading \"$id\" application component", __CLASS__);
- return $this->_components[$id] = \Yii::createObject($this->_components[$id]);
+ Yii::trace("Loading component: $id", __CLASS__);
+ return $this->_components[$id] = Yii::createObject($this->_components[$id]);
}
}
return null;
}
/**
- * Registers an application component in this module.
+ * Registers a component with this module.
* @param string $id component ID
- * @param Component|array|null $component the component to be added to the module. This can
+ * @param Component|array|null $component the component to be registered with the module. This can
* be one of the followings:
*
* - a [[Component]] object
* - a configuration array: when [[getComponent()]] is called initially for this component, the array
- * will be used to instantiate the component
+ * will be used to instantiate the component via [[Yii::createObject()]].
* - null: the named component will be removed from the module
*/
public function setComponent($id, $component)
@@ -474,11 +479,11 @@ abstract class Module extends Component
}
/**
- * Returns the application components.
+ * Returns the registered components.
* @param boolean $loadedOnly whether to return the loaded components only. If this is set false,
* then all components specified in the configuration will be returned, whether they are loaded or not.
* Loaded components will be returned as objects, while unloaded components as configuration arrays.
- * @return array the application components (indexed by their IDs)
+ * @return array the components (indexed by their IDs)
*/
public function getComponents($loadedOnly = false)
{
@@ -496,11 +501,11 @@ abstract class Module extends Component
}
/**
- * Registers a set of application components in this module.
+ * Registers a set of components in this module.
*
- * Each application component should be specified as a name-value pair, where
+ * Each component should be specified as a name-value pair, where
* name refers to the ID of the component and value the component or a configuration
- * array that can be used to create the component. In the latter case, [[\Yii::createObject()]]
+ * array that can be used to create the component. In the latter case, [[Yii::createObject()]]
* will be used to create the component.
*
* If a new component has the same ID as an existing one, the existing one will be overwritten silently.
@@ -520,7 +525,7 @@ abstract class Module extends Component
* )
* ~~~
*
- * @param array $components application components (id => component configuration or instance)
+ * @param array $components components (id => component configuration or instance)
*/
public function setComponents($components)
{
@@ -530,7 +535,7 @@ abstract class Module extends Component
}
/**
- * Loads application components that are declared in [[preload]].
+ * Loads components that are declared in [[preload]].
*/
public function preloadComponents()
{
@@ -540,54 +545,47 @@ abstract class Module extends Component
}
/**
- * Performs a controller action specified by a route.
- * This method parses the specified route and creates the corresponding controller and action
- * instances under the context of the specified module. It then runs the created action
- * with the given parameters.
+ * Runs a controller action specified by a route.
+ * This method parses the specified route and creates the corresponding child module(s), controller and action
+ * instances. It then calls [[Controller::runAction()]] to run the action with the given parameters.
+ * If the route is empty, the method will use [[defaultRoute]].
* @param string $route the route that specifies the action.
* @param array $params the parameters to be passed to the action
- * @return integer the action
- * @throws InvalidConfigException if the module's defaultRoute is empty or the controller's defaultAction is empty
- * @throws InvalidRequestException if the requested route cannot be resolved into an action successfully
+ * @return integer the status code returned by the action execution. 0 means normal, and other values mean abnormal.
+ * @throws InvalidRouteException if the requested route cannot be resolved into an action successfully
*/
public function runAction($route, $params = array())
{
$route = trim($route, '/');
if ($route === '') {
$route = trim($this->defaultRoute, '/');
- if ($route == '') {
- throw new InvalidConfigException(get_class($this) . '::defaultRoute cannot be empty.');
- }
}
if (($pos = strpos($route, '/')) !== false) {
$id = substr($route, 0, $pos);
- $route = substr($route, $pos + 1);
+ $route2 = substr($route, $pos + 1);
} else {
$id = $route;
- $route = '';
+ $route2 = '';
}
$module = $this->getModule($id);
if ($module !== null) {
- return $module->runAction($route, $params);
+ return $module->runAction($route2, $params);
}
$controller = $this->createController($id);
if ($controller !== null) {
- if ($route === '') {
- $route = $controller->defaultAction;
- if ($route == '') {
- throw new InvalidConfigException(get_class($controller) . '::defaultAction cannot be empty.');
- }
- }
+ $oldController = Yii::$application->controller;
+ Yii::$application->controller = $controller;
- $action = $controller->createAction($route);
- if ($action !== null) {
- return $action->runWithParams($params);
- }
- }
+ $status = $controller->runAction($route2, $params);
- throw new InvalidRequestException('Unable to resolve the request: ' . ltrim($this->getUniqueId() . '/' . $route, '/'));
+ Yii::$application->controller = $oldController;
+
+ return $status;
+ } else {
+ throw new InvalidRouteException('Unable to resolve the request: ' . $this->getUniqueId() . '/' . $route);
+ }
}
/**
diff --git a/framework/base/View.php b/framework/base/View.php
index db0741a..9657025 100644
--- a/framework/base/View.php
+++ b/framework/base/View.php
@@ -97,7 +97,7 @@ class View extends Component
* To determine which view file should be rendered, the method calls [[findViewFile()]] which
* will search in the directories as specified by [[basePath]].
*
- * View name can be a path alias representing an absolute file path (e.g. `@app/views/layout/index`),
+ * View name can be a path alias representing an absolute file path (e.g. `@application/views/layout/index`),
* or a path relative to [[basePath]]. The file suffix is optional and defaults to `.php` if not given
* in the view name.
*
diff --git a/framework/base/Widget.php b/framework/base/Widget.php
index 3608205..686e58e 100644
--- a/framework/base/Widget.php
+++ b/framework/base/Widget.php
@@ -80,7 +80,7 @@ class Widget extends Component
* To determine which view file should be rendered, the method calls [[findViewFile()]] which
* will search in the directories as specified by [[basePath]].
*
- * View name can be a path alias representing an absolute file path (e.g. `@app/views/layout/index`),
+ * View name can be a path alias representing an absolute file path (e.g. `@application/views/layout/index`),
* or a path relative to [[basePath]]. The file suffix is optional and defaults to `.php` if not given
* in the view name.
*
diff --git a/framework/logging/DbTarget.php b/framework/logging/DbTarget.php
index 004bf21..129e4d4 100644
--- a/framework/logging/DbTarget.php
+++ b/framework/logging/DbTarget.php
@@ -89,16 +89,17 @@ class DbTarget extends Target
}
/**
- * Stores log [[messages]] to DB.
- * @param boolean $final whether this method is called at the end of the current application
+ * Stores log messages to DB.
+ * @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
+ * of each message.
*/
- public function exportMessages($final)
+ public function export($messages)
{
$db = $this->getDb();
$tableName = $db->quoteTableName($this->tableName);
$sql = "INSERT INTO $tableName (level, category, log_time, message) VALUES (:level, :category, :log_time, :message)";
$command = $db->createCommand($sql);
- foreach ($this->messages as $message) {
+ foreach ($messages as $message) {
$command->bindValues(array(
':level' => $message[1],
':category' => $message[2],
diff --git a/framework/logging/EmailTarget.php b/framework/logging/EmailTarget.php
index 73fd3bb..e02e4da 100644
--- a/framework/logging/EmailTarget.php
+++ b/framework/logging/EmailTarget.php
@@ -39,13 +39,14 @@ class EmailTarget extends Target
public $headers = array();
/**
- * Sends log [[messages]] to specified email addresses.
- * @param boolean $final whether this method is called at the end of the current application
+ * Sends log messages to specified email addresses.
+ * @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
+ * of each message.
*/
- public function exportMessages($final)
+ public function export($messages)
{
$body = '';
- foreach ($this->messages as $message) {
+ foreach ($messages as $message) {
$body .= $this->formatMessage($message);
}
$body = wordwrap($body, 70);
diff --git a/framework/logging/FileTarget.php b/framework/logging/FileTarget.php
index f4ddf44..0eb897e 100644
--- a/framework/logging/FileTarget.php
+++ b/framework/logging/FileTarget.php
@@ -65,19 +65,28 @@ class FileTarget extends Target
}
/**
- * Sends log [[messages]] to specified email addresses.
- * @param boolean $final whether this method is called at the end of the current application
+ * Sends log messages to specified email addresses.
+ * @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
+ * of each message.
*/
- public function exportMessages($final)
+ public function export($messages)
{
+ $text = '';
+ foreach ($messages as $message) {
+ $text .= $this->formatMessage($message);
+ }
+ $fp = @fopen($this->logFile, 'a');
+ @flock($fp, LOCK_EX);
if (@filesize($this->logFile) > $this->maxFileSize * 1024) {
$this->rotateFiles();
+ @flock($fp,LOCK_UN);
+ @fclose($fp);
+ @file_put_contents($this->logFile, $text, FILE_APPEND | LOCK_EX);
+ } else {
+ @fwrite($fp, $text);
+ @flock($fp,LOCK_UN);
+ @fclose($fp);
}
- $messages = array();
- foreach ($this->messages as $message) {
- $messages[] = $this->formatMessage($message);
- }
- @file_put_contents($this->logFile, implode('', $messages), FILE_APPEND | LOCK_EX);
}
/**
diff --git a/framework/logging/Logger.php b/framework/logging/Logger.php
index c139193..a8ffb5e 100644
--- a/framework/logging/Logger.php
+++ b/framework/logging/Logger.php
@@ -8,16 +8,13 @@
*/
namespace yii\logging;
-
-use yii\base\Event;
-use yii\base\Exception;
+use yii\base\InvalidConfigException;
/**
* Logger records logged messages in memory.
*
- * When [[flushInterval()]] is reached or when application terminates, it will
- * call [[flush()]] to send logged messages to different log targets, such as
- * file, email, Web.
+ * When the application ends or [[flushInterval]] is reached, Logger will call [[flush()]]
+ * to send logged messages to different log targets, such as file, email, Web.
*
* @author Qiang Xue
* @since 2.0
@@ -25,15 +22,6 @@ use yii\base\Exception;
class Logger extends \yii\base\Component
{
/**
- * @event Event an event that is triggered when [[flush()]] is called.
- */
- const EVENT_FLUSH = 'flush';
- /**
- * @event Event an event that is triggered when [[flush()]] is called at the end of application.
- */
- const EVENT_FINAL_FLUSH = 'finalFlush';
-
- /**
* Error message level. An error message is one that indicates the abnormal termination of the
* application and may require developer's handling.
*/
@@ -82,7 +70,7 @@ class Logger extends \yii\base\Component
*
* ~~~
* array(
- * [0] => message (mixed)
+ * [0] => message (mixed, can be a string or some complex data, such as an exception object)
* [1] => level (integer)
* [2] => category (string)
* [3] => timestamp (float, obtained by microtime(true))
@@ -90,6 +78,10 @@ class Logger extends \yii\base\Component
* ~~~
*/
public $messages = array();
+ /**
+ * @var Router the log target router registered with this logger.
+ */
+ public $router;
/**
* Initializes the logger by registering [[flush()]] as a shutdown function.
@@ -138,7 +130,9 @@ class Logger extends \yii\base\Component
*/
public function flush($final = false)
{
- $this->trigger($final ? self::EVENT_FINAL_FLUSH : self::EVENT_FLUSH);
+ if ($this->router) {
+ $this->router->dispatch($this->messages, $final);
+ }
$this->messages = array();
}
@@ -149,7 +143,7 @@ class Logger extends \yii\base\Component
* of [[YiiBase]] class file.
* @return float the total elapsed time in seconds for current request.
*/
- public function getExecutionTime()
+ public function getElapsedTime()
{
return microtime(true) - YII_BEGIN_TIME;
}
@@ -218,7 +212,7 @@ class Logger extends \yii\base\Component
if (($last = array_pop($stack)) !== null && $last[0] === $token) {
$timings[] = array($token, $category, $timestamp - $last[3]);
} else {
- throw new Exception("Unmatched profiling block: $token");
+ throw new InvalidConfigException("Unmatched profiling block: $token");
}
}
}
@@ -231,5 +225,4 @@ class Logger extends \yii\base\Component
return $timings;
}
-
}
diff --git a/framework/logging/Router.php b/framework/logging/Router.php
index 75fbbc0..2e6a8dd 100644
--- a/framework/logging/Router.php
+++ b/framework/logging/Router.php
@@ -81,26 +81,21 @@ class Router extends Component
$this->targets[$name] = Yii::createObject($target);
}
}
-
- Yii::getLogger()->on(Logger::EVENT_FLUSH, array($this, 'processMessages'));
- Yii::getLogger()->on(Logger::EVENT_FINAL_FLUSH, array($this, 'processMessages'));
+ Yii::getLogger()->router = $this;
}
/**
- * Retrieves and processes log messages from the system logger.
- * This method mainly serves the event handler to the [[Logger::EVENT_FLUSH]] event
- * and the [[Logger::EVENT_FINAL_FLUSH]] event.
- * It will retrieve the available log messages from the [[Yii::getLogger()|system logger]]
- * and invoke the registered [[targets|log targets]] to do the actual processing.
- * @param \yii\base\Event $event event parameter
+ * Dispatches log messages to [[targets]].
+ * This method is called by [[Logger]] when its [[Logger::flush()]] method is called.
+ * It will forward the messages to each log target registered in [[targets]].
+ * @param array $messages the messages to be processed
+ * @param boolean $final whether this is the final call during a request cycle
*/
- public function processMessages($event)
+ public function dispatch($messages, $final = false)
{
- $messages = Yii::getLogger()->messages;
- $final = $event->name === Logger::EVENT_FINAL_FLUSH;
foreach ($this->targets as $target) {
if ($target->enabled) {
- $target->processMessages($messages, $final);
+ $target->collect($messages, $final);
}
}
}
diff --git a/framework/logging/Target.php b/framework/logging/Target.php
index a4e7714..c9e175a 100644
--- a/framework/logging/Target.php
+++ b/framework/logging/Target.php
@@ -50,15 +50,6 @@ abstract class Target extends \yii\base\Component
*/
public $except = array();
/**
- * @var boolean whether to prefix each log message with the current session ID. Defaults to false.
- */
- public $prefixSession = false;
- /**
- * @var boolean whether to prefix each log message with the current user name and ID. Defaults to false.
- * @see \yii\web\User
- */
- public $prefixUser = false;
- /**
* @var boolean whether to log a message containing the current user name and ID. Defaults to false.
* @see \yii\web\User
*/
@@ -77,19 +68,18 @@ abstract class Target extends \yii\base\Component
public $exportInterval = 1000;
/**
* @var array the messages that are retrieved from the logger so far by this log target.
- * @see autoExport
*/
- public $messages = array();
+ private $_messages = array();
private $_levels = 0;
/**
* Exports log messages to a specific destination.
- * Child classes must implement this method. Note that you may need
- * to clean up [[messages]] in this method to avoid re-exporting messages.
- * @param boolean $final whether this method is called at the end of the current application
+ * Child classes must implement this method.
+ * @param array $messages the messages to be exported. See [[Logger::messages]] for the structure
+ * of each message.
*/
- abstract public function exportMessages($final);
+ abstract public function export($messages);
/**
* Processes the given log messages.
@@ -99,45 +89,16 @@ abstract class Target extends \yii\base\Component
* of each message.
* @param boolean $final whether this method is called at the end of the current application
*/
- public function processMessages($messages, $final)
+ public function collect($messages, $final)
{
- $messages = $this->filterMessages($messages);
- $this->messages = array_merge($this->messages, $messages);
-
- $count = count($this->messages);
+ $this->_messages = array($this->_messages, $this->filterMessages($messages));
+ $count = count($this->_messages);
if ($count > 0 && ($final || $this->exportInterval > 0 && $count >= $this->exportInterval)) {
- $this->prepareExport($final);
- $this->exportMessages($final);
- $this->messages = array();
- }
- }
-
- /**
- * Prepares the [[messages]] for exporting.
- * This method will modify each message by prepending extra information
- * if [[prefixSession]] and/or [[prefixUser]] are set true.
- * It will also add an additional message showing context information if
- * [[logUser]] and/or [[logVars]] are set.
- * @param boolean $final whether this method is called at the end of the current application
- */
- protected function prepareExport($final)
- {
- $prefix = array();
- if ($this->prefixSession && ($id = session_id()) !== '') {
- $prefix[] = "[$id]";
- }
- if ($this->prefixUser && ($user = \Yii::$application->getComponent('user', false)) !== null) {
- $prefix[] = '[' . $user->getName() . ']';
- $prefix[] = '[' . $user->getId() . ']';
- }
- if ($prefix !== array()) {
- $prefix = implode(' ', $prefix);
- foreach ($this->messages as $i => $message) {
- $this->messages[$i][0] = $prefix . ' ' . $this->messages[$i][0];
+ if (($context = $this->getContextMessage()) !== '') {
+ $this->_messages[] = array($context, Logger::LEVEL_INFO, 'application', YII_BEGIN_TIME);
}
- }
- if ($final && ($context = $this->getContextMessage()) !== '') {
- $this->messages[] = array($context, Logger::LEVEL_INFO, 'application', YII_BEGIN_TIME);
+ $this->export($this->_messages);
+ $this->_messages = array();
}
}
@@ -164,7 +125,7 @@ abstract class Target extends \yii\base\Component
/**
* @return integer the message levels that this target is interested in. This is a bitmap of
- * level values. Defaults to 0, meaning all available levels.
+ * level values. Defaults to 0, meaning all available levels.
*/
public function getLevels()
{
diff --git a/framework/util/FileHelper.php b/framework/util/FileHelper.php
index b0b0611..d340338 100644
--- a/framework/util/FileHelper.php
+++ b/framework/util/FileHelper.php
@@ -10,6 +10,7 @@
namespace yii\util;
use yii\base\Exception;
+use yii\base\InvalidConfigException;
/**
* Filesystem helper
@@ -37,7 +38,7 @@ class FileHelper
* If the given path does not refer to an existing directory, an exception will be thrown.
* @param string $path the given path. This can also be a path alias.
* @return string the normalized path
- * @throws Exception if the path does not refer to an existing directory.
+ * @throws InvalidConfigException if the path does not refer to an existing directory.
*/
public static function ensureDirectory($path)
{
@@ -45,7 +46,7 @@ class FileHelper
if ($p !== false && ($p = realpath($p)) !== false && is_dir($p)) {
return $p;
} else {
- throw new Exception('Directory does not exist: ' . $path);
+ throw new InvalidConfigException('Directory does not exist: ' . $path);
}
}