* @link http://www.yiiframework.com/ * @copyright 2008-2013 Yii Software LLC * @license http://www.yiiframework.com/license/ */ /** * CWidget is the base class for widgets. * * A widget is a self-contained component that may generate presentation * based on model data. It can be viewed as a micro-controller that embeds * into the controller-managed views. * * Compared with {@link CController controller}, a widget has neither actions nor filters. * * Usage is described at {@link CBaseController} and {@link CBaseController::widget}. * * @property CBaseController $owner Owner/creator of this widget. It could be either a widget or a controller. * @property string $id Id of the widget. * @property CController $controller The controller that this widget belongs to. * @property string $viewPath The directory containing the view files for this widget. * * @author Qiang Xue * @package system.web.widgets * @since 1.0 */ class CWidget extends CBaseController { /** * @var string the prefix to the IDs of the {@link actions}. * When a widget is declared an action provider in {@link CController::actions}, * a prefix can be specified to differentiate its action IDs from others. * The same prefix should then also be used to configure this property * when the widget is used in a view of the controller. */ public $actionPrefix; /** * @var mixed the name of the skin to be used by this widget. Defaults to 'default'. * If this is set as false, no skin will be applied to this widget. * @see CWidgetFactory * @since 1.1 */ public $skin='default'; /** * @var array view paths for different types of widgets */ private static $_viewPaths; /** * @var integer the counter for generating implicit IDs. */ private static $_counter=0; /** * @var string id of the widget. */ private $_id; /** * @var CBaseController owner/creator of this widget. It could be either a widget or a controller. */ private $_owner; /** * Returns a list of actions that are used by this widget. * The structure of this method's return value is similar to * that returned by {@link CController::actions}. * * When a widget uses several actions, you can declare these actions using * this method. The widget will then become an action provider, and the actions * can be easily imported into a controller. * * Note, when creating URLs referring to the actions listed in this method, * make sure the action IDs are prefixed with {@link actionPrefix}. * * @return array * * @see actionPrefix * @see CController::actions */ public static function actions() { return array(); } /** * Constructor. * @param CBaseController $owner owner/creator of this widget. It could be either a widget or a controller. */ public function __construct($owner=null) { $this->_owner=$owner===null?Yii::app()->getController():$owner; } /** * Returns the owner/creator of this widget. * @return CBaseController owner/creator of this widget. It could be either a widget or a controller. */ public function getOwner() { return $this->_owner; } /** * Returns the ID of the widget or generates a new one if requested. * @param boolean $autoGenerate whether to generate an ID if it is not set previously * @return string id of the widget. */ public function getId($autoGenerate=true) { if($this->_id!==null) return $this->_id; elseif($autoGenerate) return $this->_id='yw'.self::$_counter++; } /** * Sets the ID of the widget. * @param string $value id of the widget. */ public function setId($value) { $this->_id=$value; } /** * Returns the controller that this widget belongs to. * @return CController the controller that this widget belongs to. */ public function getController() { if($this->_owner instanceof CController) return $this->_owner; else return Yii::app()->getController(); } /** * Initializes the widget. * This method is called by {@link CBaseController::createWidget} * and {@link CBaseController::beginWidget} after the widget's * properties have been initialized. */ public function init() { } /** * Executes the widget. * This method is called by {@link CBaseController::endWidget}. */ public function run() { } /** * Returns the directory containing the view files for this widget. * The default implementation returns the 'views' subdirectory of the directory containing the widget class file. * If $checkTheme is set true, the directory "ThemeID/views/ClassName" will be returned when it exists. * @param boolean $checkTheme whether to check if the theme contains a view path for the widget. * @return string the directory containing the view files for this widget. */ public function getViewPath($checkTheme=false) { $className=get_class($this); $scope=$checkTheme?'theme':'local'; if(isset(self::$_viewPaths[$className][$scope])) return self::$_viewPaths[$className][$scope]; else { if($checkTheme && ($theme=Yii::app()->getTheme())!==null) { $path=$theme->getViewPath().DIRECTORY_SEPARATOR; if(strpos($className,'\\')!==false) // namespaced class $path.=str_replace('\\','_',ltrim($className,'\\')); else $path.=$className; if(is_dir($path)) return self::$_viewPaths[$className]['theme']=$path; } $class=new ReflectionClass($className); return self::$_viewPaths[$className]['local']=dirname($class->getFileName()).DIRECTORY_SEPARATOR.'views'; } } /** * Looks for the view script file according to the view name. * This method will look for the view under the widget's {@link getViewPath viewPath}. * The view script file is named as "ViewName.php". A localized view file * may be returned if internationalization is needed. See {@link CApplication::findLocalizedFile} * for more details. * The view name can also refer to a path alias if it contains dot characters. * @param string $viewName name of the view (without file extension) * @return string the view file path. False if the view file does not exist * @see CApplication::findLocalizedFile */ public function getViewFile($viewName) { if(($renderer=Yii::app()->getViewRenderer())!==null) $extension=$renderer->fileExtension; else $extension='.php'; if(strpos($viewName,'.')) // a path alias $viewFile=Yii::getPathOfAlias($viewName); else { $viewFile=$this->getViewPath(true).DIRECTORY_SEPARATOR.$viewName; if(is_file($viewFile.$extension)) return Yii::app()->findLocalizedFile($viewFile.$extension); elseif($extension!=='.php' && is_file($viewFile.'.php')) return Yii::app()->findLocalizedFile($viewFile.'.php'); $viewFile=$this->getViewPath(false).DIRECTORY_SEPARATOR.$viewName; } if(is_file($viewFile.$extension)) return Yii::app()->findLocalizedFile($viewFile.$extension); elseif($extension!=='.php' && is_file($viewFile.'.php')) return Yii::app()->findLocalizedFile($viewFile.'.php'); else return false; } /** * Renders a view. * * The named view refers to a PHP script (resolved via {@link getViewFile}) * that is included by this method. If $data is an associative array, * it will be extracted as PHP variables and made available to the script. * * @param string $view name of the view to be rendered. See {@link getViewFile} for details * about how the view script is resolved. * @param array $data data to be extracted into PHP variables and made available to the view script * @param boolean $return whether the rendering result should be returned instead of being displayed to end users * @return string the rendering result. Null if the rendering result is not required. * @throws CException if the view does not exist * @see getViewFile */ public function render($view,$data=null,$return=false) { if(($viewFile=$this->getViewFile($view))!==false) return $this->renderFile($viewFile,$data,$return); else throw new CException(Yii::t('yii','{widget} cannot find the view "{view}".', array('{widget}'=>get_class($this), '{view}'=>$view))); } }