1: <?php
2: /**
3: * CViewAction class file.
4: *
5: * @author Qiang Xue <qiang.xue@gmail.com>
6: * @link http://www.yiiframework.com/
7: * @copyright 2008-2013 Yii Software LLC
8: * @license http://www.yiiframework.com/license/
9: */
10:
11: /**
12: * CViewAction represents an action that displays a view according to a user-specified parameter.
13: *
14: * By default, the view being displayed is specified via the <code>view</code> GET parameter.
15: * The name of the GET parameter can be customized via {@link viewParam}.
16: * If the user doesn't provide the GET parameter, the default view specified by {@link defaultView}
17: * will be displayed.
18: *
19: * Users specify a view in the format of <code>path.to.view</code>, which translates to the view name
20: * <code>BasePath/path/to/view</code> where <code>BasePath</code> is given by {@link basePath}.
21: *
22: * Note, the user specified view can only contain word characters, dots and dashes and
23: * the first letter must be a word letter.
24: *
25: * @property string $requestedView The name of the view requested by the user.
26: * This is in the format of 'path.to.view'.
27: *
28: * @author Qiang Xue <qiang.xue@gmail.com>
29: * @package system.web.actions
30: * @since 1.0
31: */
32: class CViewAction extends CAction
33: {
34: /**
35: * @var string the name of the GET parameter that contains the requested view name. Defaults to 'view'.
36: */
37: public $viewParam='view';
38: /**
39: * @var string the name of the default view when {@link viewParam} GET parameter is not provided by user. Defaults to 'index'.
40: * This should be in the format of 'path.to.view', similar to that given in
41: * the GET parameter.
42: * @see basePath
43: */
44: public $defaultView='index';
45: /**
46: * @var string the name of the view to be rendered. This property will be set
47: * once the user requested view is resolved.
48: */
49: public $view;
50: /**
51: * @var string the base path for the views. Defaults to 'pages'.
52: * The base path will be prefixed to any user-specified page view.
53: * For example, if a user requests for <code>tutorial.chap1</code>, the corresponding view name will
54: * be <code>pages/tutorial/chap1</code>, assuming the base path is <code>pages</code>.
55: * The actual view file is determined by {@link CController::getViewFile}.
56: * @see CController::getViewFile
57: */
58: public $basePath='pages';
59: /**
60: * @var mixed the name of the layout to be applied to the views.
61: * This will be assigned to {@link CController::layout} before the view is rendered.
62: * Defaults to null, meaning the controller's layout will be used.
63: * If false, no layout will be applied.
64: */
65: public $layout;
66: /**
67: * @var boolean whether the view should be rendered as PHP script or static text. Defaults to false.
68: */
69: public $renderAsText=false;
70:
71: private $_viewPath;
72:
73:
74: /**
75: * Returns the name of the view requested by the user.
76: * If the user doesn't specify any view, the {@link defaultView} will be returned.
77: * @return string the name of the view requested by the user.
78: * This is in the format of 'path.to.view'.
79: */
80: public function getRequestedView()
81: {
82: if($this->_viewPath===null)
83: {
84: if(!empty($_GET[$this->viewParam]) && is_string($_GET[$this->viewParam]))
85: $this->_viewPath=$_GET[$this->viewParam];
86: else
87: $this->_viewPath=$this->defaultView;
88: }
89: return $this->_viewPath;
90: }
91:
92: /**
93: * Resolves the user-specified view into a valid view name.
94: * @param string $viewPath user-specified view in the format of 'path.to.view'.
95: * @return string fully resolved view in the format of 'path/to/view'.
96: * @throws CHttpException if the user-specified view is invalid
97: */
98: protected function resolveView($viewPath)
99: {
100: // start with a word char and have word chars, dots and dashes only
101: if(preg_match('/^\w[\w\.\-]*$/',$viewPath))
102: {
103: $view=strtr($viewPath,'.','/');
104: if(!empty($this->basePath))
105: $view=$this->basePath.'/'.$view;
106: if($this->getController()->getViewFile($view)!==false)
107: {
108: $this->view=$view;
109: return;
110: }
111: }
112: throw new CHttpException(404,Yii::t('yii','The requested view "{name}" was not found.',
113: array('{name}'=>$viewPath)));
114: }
115:
116: /**
117: * Runs the action.
118: * This method displays the view requested by the user.
119: * @throws CHttpException if the view is invalid
120: */
121: public function run()
122: {
123: $this->resolveView($this->getRequestedView());
124: $controller=$this->getController();
125: if($this->layout!==null)
126: {
127: $layout=$controller->layout;
128: $controller->layout=$this->layout;
129: }
130:
131: $this->onBeforeRender($event=new CEvent($this));
132: if(!$event->handled)
133: {
134: if($this->renderAsText)
135: {
136: $text=file_get_contents($controller->getViewFile($this->view));
137: $controller->renderText($text);
138: }
139: else
140: $controller->render($this->view);
141: $this->onAfterRender(new CEvent($this));
142: }
143:
144: if($this->layout!==null)
145: $controller->layout=$layout;
146: }
147:
148: /**
149: * Raised right before the action invokes the render method.
150: * Event handlers can set the {@link CEvent::handled} property
151: * to be true to stop further view rendering.
152: * @param CEvent $event event parameter
153: */
154: public function onBeforeRender($event)
155: {
156: $this->raiseEvent('onBeforeRender',$event);
157: }
158:
159: /**
160: * Raised right after the action invokes the render method.
161: * @param CEvent $event event parameter
162: */
163: public function onAfterRender($event)
164: {
165: $this->raiseEvent('onAfterRender',$event);
166: }
167: }