* @link http://www.yiiframework.com/ * @copyright 2008-2013 Yii Software LLC * @license http://www.yiiframework.com/license/ */ /** * CViewAction represents an action that displays a view according to a user-specified parameter. * * By default, the view being displayed is specified via the view GET parameter. * The name of the GET parameter can be customized via {@link viewParam}. * If the user doesn't provide the GET parameter, the default view specified by {@link defaultView} * will be displayed. * * Users specify a view in the format of path.to.view, which translates to the view name * BasePath/path/to/view where BasePath is given by {@link basePath}. * * Note, the user specified view can only contain word characters, dots and dashes and * the first letter must be a word letter. * * @property string $requestedView The name of the view requested by the user. * This is in the format of 'path.to.view'. * * @author Qiang Xue * @package system.web.actions * @since 1.0 */ class CViewAction extends CAction { /** * @var string the name of the GET parameter that contains the requested view name. Defaults to 'view'. */ public $viewParam='view'; /** * @var string the name of the default view when {@link viewParam} GET parameter is not provided by user. Defaults to 'index'. * This should be in the format of 'path.to.view', similar to that given in * the GET parameter. * @see basePath */ public $defaultView='index'; /** * @var string the name of the view to be rendered. This property will be set * once the user requested view is resolved. */ public $view; /** * @var string the base path for the views. Defaults to 'pages'. * The base path will be prefixed to any user-specified page view. * For example, if a user requests for tutorial.chap1, the corresponding view name will * be pages/tutorial/chap1, assuming the base path is pages. * The actual view file is determined by {@link CController::getViewFile}. * @see CController::getViewFile */ public $basePath='pages'; /** * @var mixed the name of the layout to be applied to the views. * This will be assigned to {@link CController::layout} before the view is rendered. * Defaults to null, meaning the controller's layout will be used. * If false, no layout will be applied. */ public $layout; /** * @var boolean whether the view should be rendered as PHP script or static text. Defaults to false. */ public $renderAsText=false; private $_viewPath; /** * Returns the name of the view requested by the user. * If the user doesn't specify any view, the {@link defaultView} will be returned. * @return string the name of the view requested by the user. * This is in the format of 'path.to.view'. */ public function getRequestedView() { if($this->_viewPath===null) { if(!empty($_GET[$this->viewParam]) && is_string($_GET[$this->viewParam])) $this->_viewPath=$_GET[$this->viewParam]; else $this->_viewPath=$this->defaultView; } return $this->_viewPath; } /** * Resolves the user-specified view into a valid view name. * @param string $viewPath user-specified view in the format of 'path.to.view'. * @return string fully resolved view in the format of 'path/to/view'. * @throws CHttpException if the user-specified view is invalid */ protected function resolveView($viewPath) { // start with a word char and have word chars, dots and dashes only if(preg_match('/^\w[\w\.\-]*$/',$viewPath)) { $view=strtr($viewPath,'.','/'); if(!empty($this->basePath)) $view=$this->basePath.'/'.$view; if($this->getController()->getViewFile($view)!==false) { $this->view=$view; return; } } throw new CHttpException(404,Yii::t('yii','The requested view "{name}" was not found.', array('{name}'=>$viewPath))); } /** * Runs the action. * This method displays the view requested by the user. * @throws CHttpException if the view is invalid */ public function run() { $this->resolveView($this->getRequestedView()); $controller=$this->getController(); if($this->layout!==null) { $layout=$controller->layout; $controller->layout=$this->layout; } $this->onBeforeRender($event=new CEvent($this)); if(!$event->handled) { if($this->renderAsText) { $text=file_get_contents($controller->getViewFile($this->view)); $controller->renderText($text); } else $controller->render($this->view); $this->onAfterRender(new CEvent($this)); } if($this->layout!==null) $controller->layout=$layout; } /** * Raised right before the action invokes the render method. * Event handlers can set the {@link CEvent::handled} property * to be true to stop further view rendering. * @param CEvent $event event parameter */ public function onBeforeRender($event) { $this->raiseEvent('onBeforeRender',$event); } /** * Raised right after the action invokes the render method. * @param CEvent $event event parameter */ public function onAfterRender($event) { $this->raiseEvent('onAfterRender',$event); } }