CWidgetFactory property inheritance

As things stand at the moment, setting a global property for CJuiWidget will not have an effect on CJuiAccordion or any other inherited class. For example, you might have this kind of setup in your config file:




'widgetFactory'=>array(

	'widgets' => array(

		'CJuiWidget' => array(

			'themeUrl' => '/themes',

		),

	),

),



I would expect this to be applied to all widgets extending CJuiWidget, but it does not. Here’s a solution I use:




class EWidgetFactory extends CWidgetFactory

{

	/**

	 * If true, properties set for parent class will be applied to children

	 * @var bool

	 */

	public $useInheritance = false;

	

	/**

	 * Creates a new widget based on the given class name and initial properties.

	 * If self::$useInheritance is set to true, widget will inherit global properties from its parents.

	 * If global property is an array holding a key 'eval', its value will be eval'd, eg:

	 * $this->widgets['CJuiWidget']['theme'] = array('eval' => 'return Yii::app()->getTheme() ? Yii::app()->getTheme()->name : null;');

	 * In the previous example, 'theme' property of CJuiWidget will be set to whatever current Yii theme is.  

	 * @param CBaseController $owner the owner of the new widget

	 * @param string $className the class name of the widget. This can also be a path alias (e.g. system.web.widgets.COutputCache)

	 * @param array $properties the initial property values (name=>value) of the widget.

	 * @return CWidget the newly created widget whose properties have been initialized with the given values.

	 */

	public function createWidget($owner,$className,$properties=array())

	{

		$className=Yii::import($className,true);

		$widget=new $className($owner);

		

		$globalProperties = $this->getGlobalProperties($className);

		$properties = CMap::mergeArray($globalProperties, $properties);

		

		return parent::createWidget($owner, $className, $properties);

	}

	

	/**

	 * Returns an array of properties for the widget of the supplied name.

	 * If self::$useInheritance is set, merges those properties with the

	 * properties of its parent classes, overwriting the latter.

	 * Handles properties of the special type (array('eval'=>'...')) by evaluating the provided php code.

	 * @param string $widgetName

	 * @return array

	 */

	protected function getGlobalProperties($widgetName)

	{

		$parentProps = array();

		$props = isset($this->widgets[$widgetName]) ? $this->widgets[$widgetName] : array();

		foreach ($props as &$prop)

		{

			if (is_array($prop) and isset($prop['eval']))

				$prop = eval($prop['eval']);

		}

		if ($this->useInheritance and ($parent = get_parent_class($widgetName)))

			$parentProps = $this->getGlobalProperties($parent);

		

		return CMap::mergeArray($parentProps, $props);

	}

}



Apart from taking care of class inheritance, this class also allows using eval’d code, which I think you could also consider as a feature.

Any thoughts are welcome.