CWidget.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. /**
  3. * CWidget 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. * CWidget is the base class for widgets.
  12. *
  13. * A widget is a self-contained component that may generate presentation
  14. * based on model data. It can be viewed as a micro-controller that embeds
  15. * into the controller-managed views.
  16. *
  17. * Compared with {@link CController controller}, a widget has neither actions nor filters.
  18. *
  19. * Usage is described at {@link CBaseController} and {@link CBaseController::widget}.
  20. *
  21. * @property CBaseController $owner Owner/creator of this widget. It could be either a widget or a controller.
  22. * @property string $id Id of the widget.
  23. * @property CController $controller The controller that this widget belongs to.
  24. * @property string $viewPath The directory containing the view files for this widget.
  25. *
  26. * @author Qiang Xue <qiang.xue@gmail.com>
  27. * @package system.web.widgets
  28. * @since 1.0
  29. */
  30. class CWidget extends CBaseController
  31. {
  32. /**
  33. * @var string the prefix to the IDs of the {@link actions}.
  34. * When a widget is declared an action provider in {@link CController::actions},
  35. * a prefix can be specified to differentiate its action IDs from others.
  36. * The same prefix should then also be used to configure this property
  37. * when the widget is used in a view of the controller.
  38. */
  39. public $actionPrefix;
  40. /**
  41. * @var mixed the name of the skin to be used by this widget. Defaults to 'default'.
  42. * If this is set as false, no skin will be applied to this widget.
  43. * @see CWidgetFactory
  44. * @since 1.1
  45. */
  46. public $skin='default';
  47. /**
  48. * @var array view paths for different types of widgets
  49. */
  50. private static $_viewPaths;
  51. /**
  52. * @var integer the counter for generating implicit IDs.
  53. */
  54. private static $_counter=0;
  55. /**
  56. * @var string id of the widget.
  57. */
  58. private $_id;
  59. /**
  60. * @var CBaseController owner/creator of this widget. It could be either a widget or a controller.
  61. */
  62. private $_owner;
  63. /**
  64. * Returns a list of actions that are used by this widget.
  65. * The structure of this method's return value is similar to
  66. * that returned by {@link CController::actions}.
  67. *
  68. * When a widget uses several actions, you can declare these actions using
  69. * this method. The widget will then become an action provider, and the actions
  70. * can be easily imported into a controller.
  71. *
  72. * Note, when creating URLs referring to the actions listed in this method,
  73. * make sure the action IDs are prefixed with {@link actionPrefix}.
  74. *
  75. * @return array
  76. *
  77. * @see actionPrefix
  78. * @see CController::actions
  79. */
  80. public static function actions()
  81. {
  82. return array();
  83. }
  84. /**
  85. * Constructor.
  86. * @param CBaseController $owner owner/creator of this widget. It could be either a widget or a controller.
  87. */
  88. public function __construct($owner=null)
  89. {
  90. $this->_owner=$owner===null?Yii::app()->getController():$owner;
  91. }
  92. /**
  93. * Returns the owner/creator of this widget.
  94. * @return CBaseController owner/creator of this widget. It could be either a widget or a controller.
  95. */
  96. public function getOwner()
  97. {
  98. return $this->_owner;
  99. }
  100. /**
  101. * Returns the ID of the widget or generates a new one if requested.
  102. * @param boolean $autoGenerate whether to generate an ID if it is not set previously
  103. * @return string id of the widget.
  104. */
  105. public function getId($autoGenerate=true)
  106. {
  107. if($this->_id!==null)
  108. return $this->_id;
  109. elseif($autoGenerate)
  110. return $this->_id='yw'.self::$_counter++;
  111. }
  112. /**
  113. * Sets the ID of the widget.
  114. * @param string $value id of the widget.
  115. */
  116. public function setId($value)
  117. {
  118. $this->_id=$value;
  119. }
  120. /**
  121. * Returns the controller that this widget belongs to.
  122. * @return CController the controller that this widget belongs to.
  123. */
  124. public function getController()
  125. {
  126. if($this->_owner instanceof CController)
  127. return $this->_owner;
  128. else
  129. return Yii::app()->getController();
  130. }
  131. /**
  132. * Initializes the widget.
  133. * This method is called by {@link CBaseController::createWidget}
  134. * and {@link CBaseController::beginWidget} after the widget's
  135. * properties have been initialized.
  136. */
  137. public function init()
  138. {
  139. }
  140. /**
  141. * Executes the widget.
  142. * This method is called by {@link CBaseController::endWidget}.
  143. */
  144. public function run()
  145. {
  146. }
  147. /**
  148. * Returns the directory containing the view files for this widget.
  149. * The default implementation returns the 'views' subdirectory of the directory containing the widget class file.
  150. * If $checkTheme is set true, the directory "ThemeID/views/ClassName" will be returned when it exists.
  151. * @param boolean $checkTheme whether to check if the theme contains a view path for the widget.
  152. * @return string the directory containing the view files for this widget.
  153. */
  154. public function getViewPath($checkTheme=false)
  155. {
  156. $className=get_class($this);
  157. $scope=$checkTheme?'theme':'local';
  158. if(isset(self::$_viewPaths[$className][$scope]))
  159. return self::$_viewPaths[$className][$scope];
  160. else
  161. {
  162. if($checkTheme && ($theme=Yii::app()->getTheme())!==null)
  163. {
  164. $path=$theme->getViewPath().DIRECTORY_SEPARATOR;
  165. if(strpos($className,'\\')!==false) // namespaced class
  166. $path.=str_replace('\\','_',ltrim($className,'\\'));
  167. else
  168. $path.=$className;
  169. if(is_dir($path))
  170. return self::$_viewPaths[$className]['theme']=$path;
  171. }
  172. $class=new ReflectionClass($className);
  173. return self::$_viewPaths[$className]['local']=dirname($class->getFileName()).DIRECTORY_SEPARATOR.'views';
  174. }
  175. }
  176. /**
  177. * Looks for the view script file according to the view name.
  178. * This method will look for the view under the widget's {@link getViewPath viewPath}.
  179. * The view script file is named as "ViewName.php". A localized view file
  180. * may be returned if internationalization is needed. See {@link CApplication::findLocalizedFile}
  181. * for more details.
  182. * The view name can also refer to a path alias if it contains dot characters.
  183. * @param string $viewName name of the view (without file extension)
  184. * @return string the view file path. False if the view file does not exist
  185. * @see CApplication::findLocalizedFile
  186. */
  187. public function getViewFile($viewName)
  188. {
  189. if(($renderer=Yii::app()->getViewRenderer())!==null)
  190. $extension=$renderer->fileExtension;
  191. else
  192. $extension='.php';
  193. if(strpos($viewName,'.')) // a path alias
  194. $viewFile=Yii::getPathOfAlias($viewName);
  195. else
  196. {
  197. $viewFile=$this->getViewPath(true).DIRECTORY_SEPARATOR.$viewName;
  198. if(is_file($viewFile.$extension))
  199. return Yii::app()->findLocalizedFile($viewFile.$extension);
  200. elseif($extension!=='.php' && is_file($viewFile.'.php'))
  201. return Yii::app()->findLocalizedFile($viewFile.'.php');
  202. $viewFile=$this->getViewPath(false).DIRECTORY_SEPARATOR.$viewName;
  203. }
  204. if(is_file($viewFile.$extension))
  205. return Yii::app()->findLocalizedFile($viewFile.$extension);
  206. elseif($extension!=='.php' && is_file($viewFile.'.php'))
  207. return Yii::app()->findLocalizedFile($viewFile.'.php');
  208. else
  209. return false;
  210. }
  211. /**
  212. * Renders a view.
  213. *
  214. * The named view refers to a PHP script (resolved via {@link getViewFile})
  215. * that is included by this method. If $data is an associative array,
  216. * it will be extracted as PHP variables and made available to the script.
  217. *
  218. * @param string $view name of the view to be rendered. See {@link getViewFile} for details
  219. * about how the view script is resolved.
  220. * @param array $data data to be extracted into PHP variables and made available to the view script
  221. * @param boolean $return whether the rendering result should be returned instead of being displayed to end users
  222. * @return string the rendering result. Null if the rendering result is not required.
  223. * @throws CException if the view does not exist
  224. * @see getViewFile
  225. */
  226. public function render($view,$data=null,$return=false)
  227. {
  228. if(($viewFile=$this->getViewFile($view))!==false)
  229. return $this->renderFile($viewFile,$data,$return);
  230. else
  231. throw new CException(Yii::t('yii','{widget} cannot find the view "{view}".',
  232. array('{widget}'=>get_class($this), '{view}'=>$view)));
  233. }
  234. }