Commit 83e353dd by Paul Klimov

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

parent 8c98d995
......@@ -25,7 +25,7 @@ use Yii;
* @author Qiang Xue <qiang.xue@gmail.com>
* @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;
}
/**
......
......@@ -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,31 +195,65 @@ 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 {
// context required
if ($context === null) {
$context = $this->context;
}
if ($context instanceof ViewContext) {
$file = $context->findViewFile($view);
} 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.
*
......
<?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;
* @author Qiang Xue <qiang.xue@gmail.com>
* @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, '/');
}
}
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