Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 5 additions & 20 deletions framework/yii/base/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Controller extends Component
class Controller extends Component implements ViewContextInterface
{
/**
* @event ActionEvent an event raised right before executing a controller action.
Expand Down Expand Up @@ -305,8 +305,7 @@ public function getRoute()
*/
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);
Expand All @@ -325,8 +324,7 @@ public function render($view, $params = [])
*/
public function renderPartial($view, $params = [])
{
$viewFile = $this->findViewFile($view);
return $this->getView()->renderFile($viewFile, $params, $this);
return $this->getView()->render($view, $params, $this);
}

/**
Expand Down Expand Up @@ -382,22 +380,9 @@ public function getViewPath()
* 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;
}

/**
Expand Down
59 changes: 46 additions & 13 deletions framework/yii/base/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 ViewContextInterface the context under which the [[renderFile()]] method is being invoked.
*/
public $context;
/**
Expand Down Expand Up @@ -196,29 +195,63 @@ public function init()
/**
* 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 ViewContextInterface) {
$file = $context->findViewFile($view);
} else {
throw new InvalidCallException('Current context is not supported.');
}
}

return pathinfo($file, PATHINFO_EXTENSION) === '' ? $file . '.php' : $file;
}

/**
Expand Down
30 changes: 30 additions & 0 deletions framework/yii/base/ViewContextInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/

namespace yii\base;

/**
* ViewContextInterface 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 ViewContextInterface
{
/**
* 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);
}
26 changes: 6 additions & 20 deletions framework/yii/base/Widget.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Widget extends Component
class Widget extends Component implements ViewContextInterface
{
/**
* @var integer a counter used to generate [[id]] for widgets.
Expand Down Expand Up @@ -167,8 +167,7 @@ public function run()
*/
public function render($view, $params = [])
{
$viewFile = $this->findViewFile($view);
return $this->getView()->renderFile($viewFile, $params, $this);
return $this->getView()->render($view, $params, $this);
}

/**
Expand Down Expand Up @@ -197,25 +196,12 @@ public function getViewPath()

/**
* 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, '/');
}
}