~horux-dev/horux-webcli/thfo

« back to all changes in this revision

Viewing changes to yii/framework/web/CBaseController.php

  • Committer: Thierry Forchelet
  • Date: 2011-02-25 13:30:15 UTC
  • Revision ID: thierry.forchelet@letux.ch-20110225133015-zxyj9w7sqv8ly971
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * CBaseController class file.
 
4
 *
 
5
 * @author Qiang Xue <qiang.xue@gmail.com>
 
6
 * @link http://www.yiiframework.com/
 
7
 * @copyright Copyright &copy; 2008-2011 Yii Software LLC
 
8
 * @license http://www.yiiframework.com/license/
 
9
 */
 
10
 
 
11
 
 
12
/**
 
13
 * CBaseController is the base class for {@link CController} and {@link CWidget}.
 
14
 *
 
15
 * It provides the common functionalities shared by controllers who need to render views.
 
16
 *
 
17
 * CBaseController also implements the support for the following features:
 
18
 * <ul>
 
19
 * <li>{@link CClipWidget Clips} : a clip is a piece of captured output that can be inserted elsewhere.</li>
 
20
 * <li>{@link CWidget Widgets} : a widget is a self-contained sub-controller with its own view and model.</li>
 
21
 * <li>{@link COutputCache Fragment cache} : fragment cache selectively caches a portion of the output.</li>
 
22
 * </ul>
 
23
 *
 
24
 * To use a widget in a view, use the following in the view:
 
25
 * <pre>
 
26
 * $this->widget('path.to.widgetClass',array('property1'=>'value1',...));
 
27
 * </pre>
 
28
 * or
 
29
 * <pre>
 
30
 * $this->beginWidget('path.to.widgetClass',array('property1'=>'value1',...));
 
31
 * // ... display other contents here
 
32
 * $this->endWidget();
 
33
 * </pre>
 
34
 *
 
35
 * To create a clip, use the following:
 
36
 * <pre>
 
37
 * $this->beginClip('clipID');
 
38
 * // ... display the clip contents
 
39
 * $this->endClip();
 
40
 * </pre>
 
41
 * Then, in a different view or place, the captured clip can be inserted as:
 
42
 * <pre>
 
43
 * echo $this->clips['clipID'];
 
44
 * </pre>
 
45
 *
 
46
 * To use fragment cache, do as follows,
 
47
 * <pre>
 
48
 * if($this->beginCache('cacheID',array('property1'=>'value1',...))
 
49
 * {
 
50
 *     // ... display the content to be cached here
 
51
 *    $this->endCache();
 
52
 * }
 
53
 * </pre>
 
54
 *
 
55
 * @author Qiang Xue <qiang.xue@gmail.com>
 
56
 * @version $Id: CBaseController.php 2799 2011-01-01 19:31:13Z qiang.xue $
 
57
 * @package system.web
 
58
 * @since 1.0
 
59
 */
 
60
abstract class CBaseController extends CComponent
 
61
{
 
62
        private $_widgetStack=array();
 
63
 
 
64
        /**
 
65
         * Returns the view script file according to the specified view name.
 
66
         * This method must be implemented by child classes.
 
67
         * @param string $viewName view name
 
68
         * @return string the file path for the named view. False if the view cannot be found.
 
69
         */
 
70
        abstract public function getViewFile($viewName);
 
71
 
 
72
 
 
73
        /**
 
74
         * Renders a view file.
 
75
         *
 
76
         * @param string $viewFile view file path
 
77
         * @param array $data data to be extracted and made available to the view
 
78
         * @param boolean $return whether the rendering result should be returned instead of being echoed
 
79
         * @return string the rendering result. Null if the rendering result is not required.
 
80
         * @throws CException if the view file does not exist
 
81
         */
 
82
        public function renderFile($viewFile,$data=null,$return=false)
 
83
        {
 
84
                $widgetCount=count($this->_widgetStack);
 
85
                if(($renderer=Yii::app()->getViewRenderer())!==null && $renderer->fileExtension==='.'.CFileHelper::getExtension($viewFile))
 
86
                        $content=$renderer->renderFile($this,$viewFile,$data,$return);
 
87
                else
 
88
                        $content=$this->renderInternal($viewFile,$data,$return);
 
89
                if(count($this->_widgetStack)===$widgetCount)
 
90
                        return $content;
 
91
                else
 
92
                {
 
93
                        $widget=end($this->_widgetStack);
 
94
                        throw new CException(Yii::t('yii','{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.',
 
95
                                array('{controller}'=>get_class($this), '{view}'=>$viewFile, '{widget}'=>get_class($widget))));
 
96
                }
 
97
        }
 
98
 
 
99
        /**
 
100
         * Renders a view file.
 
101
         * This method includes the view file as a PHP script
 
102
         * and captures the display result if required.
 
103
         * @param string $_viewFile_ view file
 
104
         * @param array $_data_ data to be extracted and made available to the view file
 
105
         * @param boolean $_return_ whether the rendering result should be returned as a string
 
106
         * @return string the rendering result. Null if the rendering result is not required.
 
107
         */
 
108
        public function renderInternal($_viewFile_,$_data_=null,$_return_=false)
 
109
        {
 
110
                // we use special variable names here to avoid conflict when extracting data
 
111
                if(is_array($_data_))
 
112
                        extract($_data_,EXTR_PREFIX_SAME,'data');
 
113
                else
 
114
                        $data=$_data_;
 
115
                if($_return_)
 
116
                {
 
117
                        ob_start();
 
118
                        ob_implicit_flush(false);
 
119
                        require($_viewFile_);
 
120
                        return ob_get_clean();
 
121
                }
 
122
                else
 
123
                        require($_viewFile_);
 
124
        }
 
125
 
 
126
        /**
 
127
         * Creates a widget and initializes it.
 
128
         * This method first creates the specified widget instance.
 
129
         * It then configures the widget's properties with the given initial values.
 
130
         * At the end it calls {@link CWidget::init} to initialize the widget.
 
131
         * Starting from version 1.1, if a {@link CWidgetFactory widget factory} is enabled,
 
132
         * this method will use the factory to create the widget, instead.
 
133
         * @param string $className class name (can be in path alias format)
 
134
         * @param array $properties initial property values
 
135
         * @return CWidget the fully initialized widget instance.
 
136
         */
 
137
        public function createWidget($className,$properties=array())
 
138
        {
 
139
                $widget=Yii::app()->getWidgetFactory()->createWidget($this,$className,$properties);
 
140
                $widget->init();
 
141
                return $widget;
 
142
        }
 
143
 
 
144
        /**
 
145
         * Creates a widget and executes it.
 
146
         * @param string $className the widget class name or class in dot syntax (e.g. application.widgets.MyWidget)
 
147
         * @param array $properties list of initial property values for the widget (Property Name => Property Value)
 
148
         * @param boolean $captureOutput whether to capture the output of the widget. If true, the method will capture
 
149
         * and return the output generated by the widget. If false, the output will be directly sent for display
 
150
         * and the widget object will be returned. This parameter is available since version 1.1.2.
 
151
         * @return mixed the widget instance when $captureOutput is false, or the widget output when $captureOutput is true.
 
152
         */
 
153
        public function widget($className,$properties=array(),$captureOutput=false)
 
154
        {
 
155
                if($captureOutput)
 
156
                {
 
157
                        ob_start();
 
158
                        ob_implicit_flush(false);
 
159
                        $widget=$this->createWidget($className,$properties);
 
160
                        $widget->run();
 
161
                        return ob_get_clean();
 
162
                }
 
163
                else
 
164
                {
 
165
                        $widget=$this->createWidget($className,$properties);
 
166
                        $widget->run();
 
167
                        return $widget;
 
168
                }
 
169
        }
 
170
 
 
171
        /**
 
172
         * Creates a widget and executes it.
 
173
         * This method is similar to {@link widget()} except that it is expecting
 
174
         * a {@link endWidget()} call to end the execution.
 
175
         * @param string $className the widget class name or class in dot syntax (e.g. application.widgets.MyWidget)
 
176
         * @param array $properties list of initial property values for the widget (Property Name => Property Value)
 
177
         * @return CWidget the widget created to run
 
178
         * @see endWidget
 
179
         */
 
180
        public function beginWidget($className,$properties=array())
 
181
        {
 
182
                $widget=$this->createWidget($className,$properties);
 
183
                $this->_widgetStack[]=$widget;
 
184
                return $widget;
 
185
        }
 
186
 
 
187
        /**
 
188
         * Ends the execution of the named widget.
 
189
         * This method is used together with {@link beginWidget()}.
 
190
         * @param string $id optional tag identifying the method call for debugging purpose.
 
191
         * @return CWidget the widget just ended running
 
192
         * @throws CException if an extra endWidget call is made
 
193
         * @see beginWidget
 
194
         */
 
195
        public function endWidget($id='')
 
196
        {
 
197
                if(($widget=array_pop($this->_widgetStack))!==null)
 
198
                {
 
199
                        $widget->run();
 
200
                        return $widget;
 
201
                }
 
202
                else
 
203
                        throw new CException(Yii::t('yii','{controller} has an extra endWidget({id}) call in its view.',
 
204
                                array('{controller}'=>get_class($this),'{id}'=>$id)));
 
205
        }
 
206
 
 
207
        /**
 
208
         * Begins recording a clip.
 
209
         * This method is a shortcut to beginning {@link CClipWidget}.
 
210
         * @param string $id the clip ID.
 
211
         * @param array $properties initial property values for {@link CClipWidget}.
 
212
         */
 
213
        public function beginClip($id,$properties=array())
 
214
        {
 
215
                $properties['id']=$id;
 
216
                $this->beginWidget('CClipWidget',$properties);
 
217
        }
 
218
 
 
219
        /**
 
220
         * Ends recording a clip.
 
221
         * This method is an alias to {@link endWidget}.
 
222
         */
 
223
        public function endClip()
 
224
        {
 
225
                $this->endWidget('CClipWidget');
 
226
        }
 
227
 
 
228
        /**
 
229
         * Begins fragment caching.
 
230
         * This method will display cached content if it is availabe.
 
231
         * If not, it will start caching and would expect a {@link endCache()}
 
232
         * call to end the cache and save the content into cache.
 
233
         * A typical usage of fragment caching is as follows,
 
234
         * <pre>
 
235
         * if($this->beginCache($id))
 
236
         * {
 
237
         *     // ...generate content here
 
238
         *     $this->endCache();
 
239
         * }
 
240
         * </pre>
 
241
         * @param string $id a unique ID identifying the fragment to be cached.
 
242
         * @param array $properties initial property values for {@link COutputCache}.
 
243
         * @return boolean whether we need to generate content for caching. False if cached version is available.
 
244
         * @see endCache
 
245
         */
 
246
        public function beginCache($id,$properties=array())
 
247
        {
 
248
                $properties['id']=$id;
 
249
                $cache=$this->beginWidget('COutputCache',$properties);
 
250
                if($cache->getIsContentCached())
 
251
                {
 
252
                        $this->endCache();
 
253
                        return false;
 
254
                }
 
255
                else
 
256
                        return true;
 
257
        }
 
258
 
 
259
        /**
 
260
         * Ends fragment caching.
 
261
         * This is an alias to {@link endWidget}.
 
262
         * @see beginCache
 
263
         */
 
264
        public function endCache()
 
265
        {
 
266
                $this->endWidget('COutputCache');
 
267
        }
 
268
 
 
269
        /**
 
270
         * Begins the rendering of content that is to be decorated by the specified view.
 
271
         * @param mixed $view the name of the view that will be used to decorate the content. The actual view script
 
272
         * is resolved via {@link getViewFile}. If this parameter is null (default),
 
273
         * the default layout will be used as the decorative view.
 
274
         * Note that if the current controller does not belong to
 
275
         * any module, the default layout refers to the application's {@link CWebApplication::layout default layout};
 
276
         * If the controller belongs to a module, the default layout refers to the module's
 
277
         * {@link CWebModule::layout default layout}.
 
278
         * @param array $data the variables (name=>value) to be extracted and made available in the decorative view.
 
279
         * This parameter has been available since version 1.0.4
 
280
         * @see beginContent
 
281
         * @see CContentDecorator
 
282
         */
 
283
        public function beginContent($view=null,$data=array())
 
284
        {
 
285
                $this->beginWidget('CContentDecorator',array('view'=>$view, 'data'=>$data));
 
286
        }
 
287
 
 
288
        /**
 
289
         * Ends the rendering of content.
 
290
         * @see beginContent
 
291
         */
 
292
        public function endContent()
 
293
        {
 
294
                $this->endWidget('CContentDecorator');
 
295
        }
 
296
}