|
|
|
@ -10,6 +10,7 @@
|
|
|
|
|
namespace yii\base; |
|
|
|
|
|
|
|
|
|
use yii\base\InvalidCallException; |
|
|
|
|
use yii\util\StringHelper; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Application is the base class for all application classes. |
|
|
|
@ -206,13 +207,13 @@ class Application extends Module
|
|
|
|
|
* @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 BadRequestException if the route cannot be resolved into a controller |
|
|
|
|
* @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 BadRequestException(\Yii::t('yii', 'Unable to resolve the request.')); |
|
|
|
|
throw new InvalidRequestException(\Yii::t('yii', 'Unable to resolve the request.')); |
|
|
|
|
} |
|
|
|
|
/** @var $controller Controller */ |
|
|
|
|
list($controller, $action) = $result; |
|
|
|
@ -441,4 +442,126 @@ 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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** @var $controller Controller */ |
|
|
|
|
if (isset($module->controllerMap[$id])) { |
|
|
|
|
$controller = \Yii::createObject($module->controllerMap[$id], $id, $module); |
|
|
|
|
} else { |
|
|
|
|
$controller = $this->createController($id, $module); |
|
|
|
|
if ($controller === null) { |
|
|
|
|
throw new InvalidRequestException("Unable to resolve the request: $route"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (isset($controller)) { |
|
|
|
|
$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 |
|
|
|
|
* @throws InvalidConfigException if [[Controller::defaultAction]] is empty. |
|
|
|
|
*/ |
|
|
|
|
public function createAction($id, $controller) |
|
|
|
|
{ |
|
|
|
|
if ($id === '') { |
|
|
|
|
$id = $controller->defaultAction; |
|
|
|
|
if ($id == '') { |
|
|
|
|
throw new InvalidConfigException(get_class($controller) . '::defaultAction cannot be empty.'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|