From 83e353dd41b6c48dade0168d9853b496a3897728 Mon Sep 17 00:00:00 2001 From: Paul Klimov Date: Thu, 24 Oct 2013 16:55:48 +0300 Subject: [PATCH] 'ViewContext' interface extracted, files render workflow refactored to use this interface. --- framework/yii/base/Controller.php | 25 ++++------------ framework/yii/base/View.php | 59 +++++++++++++++++++++++++++++--------- framework/yii/base/ViewContext.php | 30 +++++++++++++++++++ framework/yii/base/Widget.php | 26 ++++------------- 4 files changed, 87 insertions(+), 53 deletions(-) create mode 100644 framework/yii/base/ViewContext.php diff --git a/framework/yii/base/Controller.php b/framework/yii/base/Controller.php index 9a168da..79c1f5e 100644 --- a/framework/yii/base/Controller.php +++ b/framework/yii/base/Controller.php @@ -25,7 +25,7 @@ use Yii; * @author Qiang Xue * @since 2.0 */ -class Controller extends Component +class Controller extends Component implements ViewContext { /** * @event ActionEvent an event raised right before executing a controller action. @@ -305,8 +305,7 @@ class Controller extends Component */ public function render($view, $params = []) { - $viewFile = $this->findViewFile($view); - $output = $this->getView()->renderFile($viewFile, $params, $this); + $output = $this->getView()->render($view, $params, $this); $layoutFile = $this->findLayoutFile(); if ($layoutFile !== false) { return $this->getView()->renderFile($layoutFile, ['content' => $output], $this); @@ -325,8 +324,7 @@ class Controller extends Component */ public function renderPartial($view, $params = []) { - $viewFile = $this->findViewFile($view); - return $this->getView()->renderFile($viewFile, $params, $this); + return $this->getView()->render($view, $params, $this); } /** @@ -382,22 +380,9 @@ class Controller extends Component * on how to specify this parameter. * @return string the view file path. Note that the file may not exist. */ - protected function findViewFile($view) + public function findViewFile($view) { - if (strncmp($view, '@', 1) === 0) { - // e.g. "@app/views/main" - $file = Yii::getAlias($view); - } elseif (strncmp($view, '//', 2) === 0) { - // e.g. "//layouts/main" - $file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); - } elseif (strncmp($view, '/', 1) === 0) { - // e.g. "/site/index" - $file = $this->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); - } else { - $file = $this->getViewPath() . DIRECTORY_SEPARATOR . $view; - } - - return pathinfo($file, PATHINFO_EXTENSION) === '' ? $file . '.php' : $file; + return $this->getViewPath() . DIRECTORY_SEPARATOR . $view; } /** diff --git a/framework/yii/base/View.php b/framework/yii/base/View.php index 68b1094..1cb9a59 100644 --- a/framework/yii/base/View.php +++ b/framework/yii/base/View.php @@ -89,8 +89,7 @@ class View extends Component /** - * @var object the context under which the [[renderFile()]] method is being invoked. - * This can be a controller, a widget, or any other object. + * @var ViewContext the context under which the [[renderFile()]] method is being invoked. */ public $context; /** @@ -196,29 +195,63 @@ class View extends Component /** * Renders a view. * - * This method delegates the call to the [[context]] object: + * The view to be rendered can be specified in one of the following formats: * - * - If [[context]] is a controller, the [[Controller::renderPartial()]] method will be called; - * - If [[context]] is a widget, the [[Widget::render()]] method will be called; - * - Otherwise, an InvalidCallException exception will be thrown. + * - path alias (e.g. "@app/views/site/index"); + * - absolute path within application (e.g. "//site/index"): the view name starts with double slashes. + * The actual view file will be looked for under the [[Application::viewPath|view path]] of the application. + * - absolute path within current module (e.g. "/site/index"): the view name starts with a single slash. + * The actual view file will be looked for under the [[Module::viewPath|view path]] of [[module]]. + * - resolving any other format will be performed via [[ViewContext::findViewFile()]]. * * @param string $view the view name. Please refer to [[Controller::findViewFile()]] * and [[Widget::findViewFile()]] on how to specify this parameter. * @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file. + * @param object $context the context that the view should use for rendering the view. If null, + * existing [[context]] will be used. * @return string the rendering result - * @throws InvalidCallException if [[context]] is neither a controller nor a widget. * @throws InvalidParamException if the view cannot be resolved or the view file does not exist. * @see renderFile */ - public function render($view, $params = []) + public function render($view, $params = [], $context = null) { - if ($this->context instanceof Controller) { - return $this->context->renderPartial($view, $params); - } elseif ($this->context instanceof Widget) { - return $this->context->render($view, $params); + $viewFile = $this->findViewFile($view, $context); + return $this->renderFile($viewFile, $params, $context); + } + + /** + * Finds the view file based on the given view name. + * @param string $view the view name or the path alias of the view file. Please refer to [[render()]] + * on how to specify this parameter. + * @param object $context the context that the view should be used to search the view file. If null, + * existing [[context]] will be used. + * @throws InvalidCallException if [[context]] is required and invalid. + * @return string the view file path. Note that the file may not exist. + */ + protected function findViewFile($view, $context = null) + { + if (strncmp($view, '@', 1) === 0) { + // e.g. "@app/views/main" + $file = Yii::getAlias($view); + } elseif (strncmp($view, '//', 2) === 0) { + // e.g. "//layouts/main" + $file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); + } elseif (strncmp($view, '/', 1) === 0 && Yii::$app->controller !== null) { + // e.g. "/site/index" + $file = Yii::$app->controller->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); } else { - throw new InvalidCallException('View::render() is not supported for the current context.'); + // context required + if ($context === null) { + $context = $this->context; + } + if ($context instanceof ViewContext) { + $file = $context->findViewFile($view); + } else { + throw new InvalidCallException('Current context is not supported.'); + } } + + return pathinfo($file, PATHINFO_EXTENSION) === '' ? $file . '.php' : $file; } /** diff --git a/framework/yii/base/ViewContext.php b/framework/yii/base/ViewContext.php new file mode 100644 index 0000000..4072ffc --- /dev/null +++ b/framework/yii/base/ViewContext.php @@ -0,0 +1,30 @@ + + * @since 2.0 + */ +interface ViewContext +{ + /** + * Finds the view file based on the given view name. + * @param string $view the view name. + * @return string the view file path. Note that the file may not exist. + */ + public function findViewFile($view); +} \ No newline at end of file diff --git a/framework/yii/base/Widget.php b/framework/yii/base/Widget.php index 14c4cba..69da6a9 100644 --- a/framework/yii/base/Widget.php +++ b/framework/yii/base/Widget.php @@ -20,7 +20,7 @@ use Yii; * @author Qiang Xue * @since 2.0 */ -class Widget extends Component +class Widget extends Component implements ViewContext { /** * @var integer a counter used to generate [[id]] for widgets. @@ -167,8 +167,7 @@ class Widget extends Component */ public function render($view, $params = []) { - $viewFile = $this->findViewFile($view); - return $this->getView()->renderFile($viewFile, $params, $this); + return $this->getView()->render($view, $params, $this); } /** @@ -197,25 +196,12 @@ class Widget extends Component /** * Finds the view file based on the given view name. - * @param string $view the view name or the path alias of the view file. Please refer to [[render()]] - * on how to specify this parameter. + * File will be searched under [[viewPath]] directory. + * @param string $view the view name. * @return string the view file path. Note that the file may not exist. */ - protected function findViewFile($view) + public function findViewFile($view) { - if (strncmp($view, '@', 1) === 0) { - // e.g. "@app/views/main" - $file = Yii::getAlias($view); - } elseif (strncmp($view, '//', 2) === 0) { - // e.g. "//layouts/main" - $file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); - } elseif (strncmp($view, '/', 1) === 0 && Yii::$app->controller !== null) { - // e.g. "/site/index" - $file = Yii::$app->controller->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); - } else { - $file = $this->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); - } - - return pathinfo($file, PATHINFO_EXTENSION) === '' ? $file . '.php' : $file; + return $this->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); } }