Commit 83e353dd by Paul Klimov

'ViewContext' interface extracted, files render workflow refactored to use this interface.

parent 8c98d995
...@@ -25,7 +25,7 @@ use Yii; ...@@ -25,7 +25,7 @@ use Yii;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class Controller extends Component class Controller extends Component implements ViewContext
{ {
/** /**
* @event ActionEvent an event raised right before executing a controller action. * @event ActionEvent an event raised right before executing a controller action.
...@@ -305,8 +305,7 @@ class Controller extends Component ...@@ -305,8 +305,7 @@ class Controller extends Component
*/ */
public function render($view, $params = []) public function render($view, $params = [])
{ {
$viewFile = $this->findViewFile($view); $output = $this->getView()->render($view, $params, $this);
$output = $this->getView()->renderFile($viewFile, $params, $this);
$layoutFile = $this->findLayoutFile(); $layoutFile = $this->findLayoutFile();
if ($layoutFile !== false) { if ($layoutFile !== false) {
return $this->getView()->renderFile($layoutFile, ['content' => $output], $this); return $this->getView()->renderFile($layoutFile, ['content' => $output], $this);
...@@ -325,8 +324,7 @@ class Controller extends Component ...@@ -325,8 +324,7 @@ class Controller extends Component
*/ */
public function renderPartial($view, $params = []) public function renderPartial($view, $params = [])
{ {
$viewFile = $this->findViewFile($view); return $this->getView()->render($view, $params, $this);
return $this->getView()->renderFile($viewFile, $params, $this);
} }
/** /**
...@@ -382,22 +380,9 @@ class Controller extends Component ...@@ -382,22 +380,9 @@ class Controller extends Component
* on how to specify this parameter. * on how to specify this parameter.
* @return string the view file path. Note that the file may not exist. * @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) { return $this->getViewPath() . DIRECTORY_SEPARATOR . $view;
// 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;
} }
/** /**
......
...@@ -89,8 +89,7 @@ class View extends Component ...@@ -89,8 +89,7 @@ class View extends Component
/** /**
* @var object the context under which the [[renderFile()]] method is being invoked. * @var ViewContext the context under which the [[renderFile()]] method is being invoked.
* This can be a controller, a widget, or any other object.
*/ */
public $context; public $context;
/** /**
...@@ -196,31 +195,65 @@ class View extends Component ...@@ -196,31 +195,65 @@ class View extends Component
/** /**
* Renders a view. * 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; * - path alias (e.g. "@app/views/site/index");
* - If [[context]] is a widget, the [[Widget::render()]] method will be called; * - absolute path within application (e.g. "//site/index"): the view name starts with double slashes.
* - Otherwise, an InvalidCallException exception will be thrown. * 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()]] * @param string $view the view name. Please refer to [[Controller::findViewFile()]]
* and [[Widget::findViewFile()]] on how to specify this parameter. * 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 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 * @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. * @throws InvalidParamException if the view cannot be resolved or the view file does not exist.
* @see renderFile * @see renderFile
*/ */
public function render($view, $params = []) public function render($view, $params = [], $context = null)
{ {
if ($this->context instanceof Controller) { $viewFile = $this->findViewFile($view, $context);
return $this->context->renderPartial($view, $params); return $this->renderFile($viewFile, $params, $context);
} elseif ($this->context instanceof Widget) { }
return $this->context->render($view, $params);
/**
* 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 {
// context required
if ($context === null) {
$context = $this->context;
}
if ($context instanceof ViewContext) {
$file = $context->findViewFile($view);
} else { } else {
throw new InvalidCallException('View::render() is not supported for the current context.'); throw new InvalidCallException('Current context is not supported.');
} }
} }
return pathinfo($file, PATHINFO_EXTENSION) === '' ? $file . '.php' : $file;
}
/** /**
* Renders a view file. * Renders a view file.
* *
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
/**
* ViewContext represents possible context for the view rendering.
* It determines the way the non-global view files are searched.
* This interface introduces method [[findViewFile]], which will be used
* at [[View::render()]] to determine the file by view name, which does
* not match default format.
*
* @see View
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @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
...@@ -20,7 +20,7 @@ use Yii; ...@@ -20,7 +20,7 @@ use Yii;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class Widget extends Component class Widget extends Component implements ViewContext
{ {
/** /**
* @var integer a counter used to generate [[id]] for widgets. * @var integer a counter used to generate [[id]] for widgets.
...@@ -167,8 +167,7 @@ class Widget extends Component ...@@ -167,8 +167,7 @@ class Widget extends Component
*/ */
public function render($view, $params = []) public function render($view, $params = [])
{ {
$viewFile = $this->findViewFile($view); return $this->getView()->render($view, $params, $this);
return $this->getView()->renderFile($viewFile, $params, $this);
} }
/** /**
...@@ -197,25 +196,12 @@ class Widget extends Component ...@@ -197,25 +196,12 @@ class Widget extends Component
/** /**
* Finds the view file based on the given view name. * 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()]] * File will be searched under [[viewPath]] directory.
* on how to specify this parameter. * @param string $view the view name.
* @return string the view file path. Note that the file may not exist. * @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) { return $this->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
// 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;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment