From ceac41b25041280b24a7e11956bac08acc8edad6 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 25 Jan 2013 18:56:56 -0500 Subject: [PATCH] MVC WIP --- framework/base/Application.php | 40 ++++++++----------- framework/base/Module.php | 91 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 26 deletions(-) diff --git a/framework/base/Application.php b/framework/base/Application.php index 2e92aab..d2f463f 100644 --- a/framework/base/Application.php +++ b/framework/base/Application.php @@ -9,6 +9,7 @@ namespace yii\base; +use Yii; use yii\base\InvalidCallException; use yii\util\StringHelper; @@ -128,7 +129,7 @@ class Application extends Module */ public function __construct($id, $basePath, $config = array()) { - \Yii::$application = $this; + Yii::$application = $this; $this->id = $id; $this->setBasePath($basePath); $this->registerDefaultAliases(); @@ -213,7 +214,7 @@ class Application extends Module { $result = $this->createController($route); if ($result === false) { - throw new InvalidRequestException(\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; @@ -243,7 +244,7 @@ class Application extends Module */ public function setRuntimePath($path) { - $p = \Yii::getAlias($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 { @@ -402,9 +403,9 @@ class Application extends Module */ public function registerDefaultAliases() { - \Yii::$aliases['@application'] = $this->getBasePath(); - \Yii::$aliases['@entry'] = dirname($_SERVER['SCRIPT_FILENAME']); - \Yii::$aliases['@www'] = ''; + Yii::$aliases['@application'] = $this->getBasePath(); + Yii::$aliases['@entry'] = dirname($_SERVER['SCRIPT_FILENAME']); + Yii::$aliases['@www'] = ''; } /** @@ -480,17 +481,15 @@ class Application extends Module 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"); + $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.'); + } } - } - if (isset($controller)) { $action = $this->createAction($route, $controller); if ($action !== null) { return $action->runWithParams($params); @@ -516,7 +515,7 @@ class Application extends Module public function createController($id, $module) { if (isset($module->controllerMap[$id])) { - return \Yii::createObject($module->controllerMap[$id], $id, $module); + 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'; @@ -541,18 +540,11 @@ class Application extends Module * @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); + 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)) { diff --git a/framework/base/Module.php b/framework/base/Module.php index 6337a9b..0539cdc 100644 --- a/framework/base/Module.php +++ b/framework/base/Module.php @@ -9,6 +9,8 @@ namespace yii\base; +use Yii; +use yii\util\StringHelper; use yii\util\FileHelper; /** @@ -167,12 +169,15 @@ abstract class Module extends Component /** * Returns an ID that uniquely identifies this module among all modules within the current application. + * Note that if the module is an application, an empty string will be returned. * @return string the unique ID of the module. */ public function getUniqueId() { - if ($this->module && !$this->module instanceof Application) { - return $this->module->getUniqueId() . "/{$this->id}"; + if ($this instanceof Application) { + return ''; + } elseif ($this->module) { + return $this->module->getUniqueId() . '/' . $this->id; } else { return $this->id; } @@ -533,4 +538,86 @@ abstract class Module extends Component $this->getComponent($id); } } + + /** + * 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 + * @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()) + { + $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); + } else { + $id = $route; + $route = ''; + } + + $module = $this->getModule($id); + if ($module !== null) { + return $module->runAction($route, $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.'); + } + } + + $action = $controller->createAction($route); + if ($action !== null) { + return $action->runWithParams($params); + } + } + + throw new InvalidRequestException('Unable to resolve the request: ' . ltrim($this->getUniqueId() . '/' . $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 + * @return Controller the newly created controller instance + */ + public function createController($id) + { + if (isset($this->controllerMap[$id])) { + return Yii::createObject($this->controllerMap[$id], $id, $this); + } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id)) { + $className = StringHelper::id2camel($id) . 'Controller'; + $classFile = $this->controllerPath . DIRECTORY_SEPARATOR . $className . '.php'; + if (is_file($classFile)) { + $className = $this->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, $this); + } + } + } + return null; + } }