Commit a5ee5b84 by Qiang Xue

view WIP

parent 2ecf1d92
...@@ -304,9 +304,13 @@ class Controller extends Component ...@@ -304,9 +304,13 @@ class Controller extends Component
*/ */
public function render($view, $params = array()) public function render($view, $params = array())
{ {
$viewFile = $this->findViewFile($view); $output = Yii::$app->getView()->render($view, $params, $this);
$layoutFile = $this->findLayoutFile(); $layoutFile = $this->findLayoutFile();
return Yii::$app->getView()->render($this, $viewFile, $params, $layoutFile); if ($layoutFile !== false) {
return Yii::$app->getView()->renderFile($layoutFile, array('content' => $output), $this);
} else {
return $output;
}
} }
/** /**
...@@ -319,7 +323,7 @@ class Controller extends Component ...@@ -319,7 +323,7 @@ class Controller extends Component
*/ */
public function renderPartial($view, $params = array()) public function renderPartial($view, $params = array())
{ {
return $this->renderFile($this->findViewFile($view), $params); return Yii::$app->getView()->render($view, $params, $this);
} }
/** /**
...@@ -331,7 +335,7 @@ class Controller extends Component ...@@ -331,7 +335,7 @@ class Controller extends Component
*/ */
public function renderFile($file, $params = array()) public function renderFile($file, $params = array())
{ {
return Yii::$app->getView()->render($this, $file, $params); return Yii::$app->getView()->renderFile($file, $params, $this);
} }
/** /**
...@@ -346,46 +350,6 @@ class Controller extends Component ...@@ -346,46 +350,6 @@ class Controller extends Component
} }
/** /**
* Finds the view file based on the given view name.
*
* A view name can be specified in one of the following formats:
*
* - 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 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 the currently
* active module.
* - relative path (e.g. "index"): the actual view file will be looked for under [[viewPath]].
*
* If the view name does not contain a file extension, it will use the default one `.php`.
*
* @param string $view the view name or the path alias of the view file.
* @return string the view file path. Note that the file may not exist.
* @throws InvalidParamException if the view file is an invalid path alias
*/
protected function findViewFile($view)
{
if (strncmp($view, '@', 1) === 0) {
// e.g. "@app/views/common"
$file = Yii::getAlias($view);
} elseif (strncmp($view, '/', 1) !== 0) {
// e.g. "index"
$file = $this->getViewPath() . DIRECTORY_SEPARATOR . $view;
} elseif (strncmp($view, '//', 2) !== 0) {
// e.g. "/site/index"
$file = $this->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} else {
// e.g. "//layouts/main"
$file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
}
if (FileHelper::getExtension($file) === '') {
$file .= '.php';
}
return $file;
}
/**
* Finds the applicable layout file. * Finds the applicable layout file.
* *
* This method locates an applicable layout file via two steps. * This method locates an applicable layout file via two steps.
......
...@@ -39,6 +39,12 @@ class View extends Component ...@@ -39,6 +39,12 @@ class View extends Component
* If not set, it means theming is not enabled. * If not set, it means theming is not enabled.
*/ */
public $theme; public $theme;
/**
* @var array a list of named output clips. You can call [[beginClip()]] and [[endClip()]]
* to capture small fragments of a view. They can be later accessed at somewhere else
* through this property.
*/
public $clips;
/** /**
* @var Widget[] the widgets that are currently not ended * @var Widget[] the widgets that are currently not ended
...@@ -61,35 +67,29 @@ class View extends Component ...@@ -61,35 +67,29 @@ class View extends Component
} }
/** /**
* Renders a view file under a context with an optional layout. * Renders a view.
* *
* This method is similar to [[renderFile()]] except that it will update [[context]] * This method will call [[findViewFile()]] to convert the view name into the corresponding view
* with the provided $context parameter. It will also apply layout to the rendering result * file path, and it will then call [[renderFile()]] to render the view.
* of the view file if $layoutFile is given.
* *
* Theming and localization will be performed for the view file and the layout file, if possible. * @param string $view the view name. Please refer to [[findViewFile()]] on how to specify this parameter.
*
* @param object $context the context object for rendering the file. This could be a controller, a widget,
* or any other object that serves as the rendering context of the view file. In the view file,
* it can be accessed through the [[context]] property.
* @param string $viewFile the view file. This can be a file path or a path alias.
* @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 string|boolean $layoutFile the layout file. This can be a file path or a path alias. * @param object $context the context that the view should use for rendering the view. If null,
* If it is false, it means no layout should be applied. * existing [[context]] will be used.
* @return string the rendering result * @return string the rendering result
* @throws InvalidParamException if the view file or the layout file does not exist. * @throws InvalidParamException if the view cannot be resolved or the view file does not exist.
* @see renderFile
* @see findViewFile
*/ */
public function render($view, $params = array()) public function render($view, $params = array(), $context = null)
{ {
$viewFile = $this->findViewFile($this->context, $view); $viewFile = $this->findViewFile($context, $view);
return $this->renderFile($viewFile, $params); return $this->renderFile($viewFile, $params, $context);
} }
/** /**
* Renders a view file. * Renders a view file.
* *
* This method renders the specified view file under the existing [[context]].
*
* If [[theme]] is enabled (not null), it will try to render the themed version of the view file as long * If [[theme]] is enabled (not null), it will try to render the themed version of the view file as long
* as it is available. * as it is available.
* *
...@@ -99,12 +99,14 @@ class View extends Component ...@@ -99,12 +99,14 @@ class View extends Component
* Otherwise, it will simply include the view file as a normal PHP file, capture its output and * Otherwise, it will simply include the view file as a normal PHP file, capture its output and
* return it as a string. * return it as a string.
* *
* @param string $viewFile the view file. This can be a file path or a path alias. * @param string $viewFile the view file. This can be either a file path or a path alias.
* @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 InvalidParamException if the view file does not exist * @throws InvalidParamException if the view file does not exist
*/ */
public function renderFile($viewFile, $params = array()) public function renderFile($viewFile, $params = array(), $context = null)
{ {
$viewFile = Yii::getAlias($viewFile); $viewFile = Yii::getAlias($viewFile);
if (is_file($viewFile)) { if (is_file($viewFile)) {
...@@ -116,11 +118,18 @@ class View extends Component ...@@ -116,11 +118,18 @@ class View extends Component
throw new InvalidParamException("The view file does not exist: $viewFile"); throw new InvalidParamException("The view file does not exist: $viewFile");
} }
$oldContext = $this->context;
$this->context = $context;
if ($this->renderer !== null) { if ($this->renderer !== null) {
return $this->renderer->render($this, $viewFile, $params); $output = $this->renderer->render($this, $viewFile, $params);
} else { } else {
return $this->renderPhpFile($viewFile, $params); $output = $this->renderPhpFile($viewFile, $params);
} }
$this->context = $oldContext;
return $output;
} }
/** /**
...@@ -156,36 +165,36 @@ class View extends Component ...@@ -156,36 +165,36 @@ class View extends Component
* - absolute path within module (e.g. "/site/index"): the view name starts with a single slash. * - absolute path within 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 the currently * The actual view file will be looked for under the [[Module::viewPath|view path]] of the currently
* active module. * active module.
* - relative path (e.g. "index"): the actual view file will be looked for under [[viewPath]]. * - relative path (e.g. "index"): the actual view file will be looked for under [[Controller::viewPath|viewPath]]
* of the context object, assuming the context is either a [[Controller]] or a [[Widget]].
* *
* If the view name does not contain a file extension, it will use the default one `.php`. * If the view name does not contain a file extension, it will use the default one `.php`.
* *
* @param object $context the view context object
* @param string $view the view name or the path alias of the view file. * @param string $view the view name or the path alias of the view file.
* @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.
* @throws InvalidParamException if the view file is an invalid path alias * @throws InvalidParamException if the view file is an invalid path alias or the context cannot be
* used to determine the actual view file corresponding to the specified view.
*/ */
protected function findViewFile($context, $view) protected function findViewFile($context, $view)
{ {
if (FileHelper::getExtension($view) === '') { if (strncmp($view, '@', 1) === 0) {
$view .= '.php'; // e.g. "@app/views/main"
} $file = Yii::getAlias($view);
} elseif (strncmp($view, '//', 2) === 0) {
if (strncmp($view, '//', 2) === 0) {
// e.g. "//layouts/main" // e.g. "//layouts/main"
$file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); $file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} elseif (strncmp($view, '/', 1) === 0) { } elseif (strncmp($view, '/', 1) === 0) {
// e.g. "/site/index" // e.g. "/site/index"
$file = Yii::$app->controller->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/'); $file = Yii::$app->controller->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} elseif (strncmp($view, '@', 1) !== 0) { } elseif ($context instanceof Controller || $context instanceof Widget) {
// e.g. "index" or "view/item" /** @var $context Controller|Widget */
if (method_exists($context, 'getViewPath')) {
$file = $context->getViewPath() . DIRECTORY_SEPARATOR . $view; $file = $context->getViewPath() . DIRECTORY_SEPARATOR . $view;
} else { } else {
$file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . $view; throw new InvalidParamException("Unable to resolve the view file for '$view'.");
}
} }
return $file; return FileHelper::getExtension($file) === '' ? $file . '.php' : $file;
} }
/** /**
...@@ -260,26 +269,31 @@ class View extends Component ...@@ -260,26 +269,31 @@ class View extends Component
} }
} }
// /**
// /** * Begins recording a clip.
// * Begins recording a clip. * This method is a shortcut to beginning [[yii\widgets\Clip]]
// * This method is a shortcut to beginning [[yii\widgets\Clip]] * @param string $id the clip ID.
// * @param string $id the clip ID. * @param boolean $renderInPlace whether to render the clip content in place.
// * @param array $properties initial property values for [[yii\widgets\Clip]] * Defaults to false, meaning the captured clip will not be displayed.
// */ * @return \yii\widgets\Clip the Clip widget instance
// public function beginClip($id, $properties = array()) */
// { public function beginClip($id, $renderInPlace = false)
// $properties['id'] = $id; {
// $this->beginWidget('yii\widgets\Clip', $properties); return $this->beginWidget('yii\widgets\Clip', array(
// } 'id' => $id,
// 'renderInPlace' => $renderInPlace,
// /** 'view' => $this,
// * Ends recording a clip. ));
// */ }
// public function endClip()
// { /**
// $this->endWidget(); * Ends recording a clip.
// } */
public function endClip()
{
$this->endWidget();
}
// //
// /** // /**
// * Begins fragment caching. // * Begins fragment caching.
...@@ -322,33 +336,33 @@ class View extends Component ...@@ -322,33 +336,33 @@ class View extends Component
// $this->endWidget(); // $this->endWidget();
// } // }
// //
// /** /**
// * Begins the rendering of content that is to be decorated by the specified view. * Begins the rendering of content that is to be decorated by the specified view.
// * @param mixed $view the name of the view that will be used to decorate the content. The actual view script * @param mixed $view the name of the view that will be used to decorate the content. The actual view script
// * is resolved via {@link getViewFile}. If this parameter is null (default), * is resolved via {@link getViewFile}. If this parameter is null (default),
// * the default layout will be used as the decorative view. * the default layout will be used as the decorative view.
// * Note that if the current controller does not belong to * Note that if the current controller does not belong to
// * any module, the default layout refers to the application's {@link CWebApplication::layout default layout}; * any module, the default layout refers to the application's {@link CWebApplication::layout default layout};
// * If the controller belongs to a module, the default layout refers to the module's * If the controller belongs to a module, the default layout refers to the module's
// * {@link CWebModule::layout default layout}. * {@link CWebModule::layout default layout}.
// * @param array $params the variables (name=>value) to be extracted and made available in the decorative view. * @param array $params the variables (name=>value) to be extracted and made available in the decorative view.
// * @see endContent * @see endContent
// * @see yii\widgets\ContentDecorator * @see yii\widgets\ContentDecorator
// */ */
// public function beginContent($view, $params = array()) public function beginContent($view, $params = array())
// { {
// $this->beginWidget('yii\widgets\ContentDecorator', array( $this->beginWidget('yii\widgets\ContentDecorator', array(
// 'view' => $view, 'view' => $view,
// 'params' => $params, 'params' => $params,
// )); ));
// } }
//
// /** /**
// * Ends the rendering of content. * Ends the rendering of content.
// * @see beginContent * @see beginContent
// */ */
// public function endContent() public function endContent()
// { {
// $this->endWidget(); $this->endWidget();
// } }
} }
\ No newline at end of file
...@@ -80,8 +80,7 @@ class Widget extends Component ...@@ -80,8 +80,7 @@ class Widget extends Component
*/ */
public function render($view, $params = array()) public function render($view, $params = array())
{ {
$file = $this->findViewFile($view); return Yii::$app->getView()->render($view, $params, $this);
return Yii::$app->getView()->render($this, $file, $params);
} }
/** /**
...@@ -93,7 +92,7 @@ class Widget extends Component ...@@ -93,7 +92,7 @@ class Widget extends Component
*/ */
public function renderFile($file, $params = array()) public function renderFile($file, $params = array())
{ {
return Yii::$app->getView()->render($this, $file, $params); return Yii::$app->getView()->renderFile($file, $params, $this);
} }
/** /**
...@@ -107,44 +106,4 @@ class Widget extends Component ...@@ -107,44 +106,4 @@ class Widget extends Component
$class = new \ReflectionClass($className); $class = new \ReflectionClass($className);
return dirname($class->getFileName()) . DIRECTORY_SEPARATOR . 'views'; return dirname($class->getFileName()) . DIRECTORY_SEPARATOR . 'views';
} }
/**
* Finds the view file based on the given view name.
*
* The view name can be specified in one of the following formats:
*
* - 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 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 the currently
* active module.
* - relative path (e.g. "index"): the actual view file will be looked for under [[viewPath]].
*
* If the view name does not contain a file extension, it will use the default one `.php`.
*
* @param string $view the view name or the path alias of the view file.
* @return string the view file path. Note that the file may not exist.
* @throws InvalidParamException if the view file is an invalid path alias
*/
public function findViewFile($view)
{
if (strncmp($view, '@', 1) === 0) {
// e.g. "@app/views/common"
$file = Yii::getAlias($view);
} elseif (strncmp($view, '/', 1) !== 0) {
// e.g. "index"
$file = $this->getViewPath() . DIRECTORY_SEPARATOR . $view;
} elseif (strncmp($view, '//', 2) !== 0 && Yii::$app->controller !== null) {
// e.g. "/site/index"
$file = Yii::$app->controller->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
} else {
// e.g. "//layouts/main"
$file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, '/');
}
if (FileHelper::getExtension($file) === '') {
$file .= '.php';
}
return $file;
}
} }
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\widgets;
use Yii;
use yii\base\Widget;
use yii\base\View;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Clip extends Widget
{
/**
* @var string the ID of this clip.
*/
public $id;
/**
* @var View the view object for keeping the clip. If not set, the view registered with the application
* will be used.
*/
public $view;
/**
* @var boolean whether to render the clip content in place. Defaults to false,
* meaning the captured clip will not be displayed.
*/
public $renderInPlace = false;
/**
* Starts recording a clip.
*/
public function init()
{
ob_start();
ob_implicit_flush(false);
}
/**
* Ends recording a clip.
* This method stops output buffering and saves the rendering result as a named clip in the controller.
*/
public function run()
{
$clip = ob_get_clean();
if ($this->renderClip) {
echo $clip;
}
$view = $this->view !== null ? $this->view : Yii::$app->getView();
$view->clips[$this->id] = $clip;
}
}
\ No newline at end of file
<?php
/**
* CContentDecorator class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CContentDecorator decorates the content it encloses with the specified view.
*
* CContentDecorator is mostly used to implement nested layouts, i.e., a layout
* is embedded within another layout. {@link CBaseController} defines a pair of
* convenient methods to use CContentDecorator:
* <pre>
* $this->beginContent('path/to/view');
* // ... content to be decorated
* $this->endContent();
* </pre>
*
* The property {@link view} specifies the name of the view that is used to
* decorate the content. In the view, the content being decorated may be
* accessed with variable <code>$content</code>.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.web.widgets
* @since 1.0
*/
class CContentDecorator extends COutputProcessor
{
/**
* @var mixed the name of the view that will be used to decorate the captured content.
* If this property is null (default value), the default layout will be used as
* the decorative view. Note that if the current controller does not belong to
* any module, the default layout refers to the application's {@link CWebApplication::layout default layout};
* If the controller belongs to a module, the default layout refers to the module's
* {@link CWebModule::layout default layout}.
*/
public $view;
/**
* @var array the variables (name=>value) to be extracted and made available in the decorative view.
*/
public $data=array();
/**
* Processes the captured output.
* This method decorates the output with the specified {@link view}.
* @param string $output the captured output to be processed
*/
public function processOutput($output)
{
$output=$this->decorate($output);
parent::processOutput($output);
}
/**
* Decorates the content by rendering a view and embedding the content in it.
* The content being embedded can be accessed in the view using variable <code>$content</code>
* The decorated content will be displayed directly.
* @param string $content the content to be decorated
* @return string the decorated content
*/
protected function decorate($content)
{
$owner=$this->getOwner();
if($this->view===null)
$viewFile=Yii::app()->getController()->getLayoutFile(null);
else
$viewFile=$owner->getViewFile($this->view);
if($viewFile!==false)
{
$data=$this->data;
$data['content']=$content;
return $owner->renderFile($viewFile,$data,true);
}
else
return $content;
}
}
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