Yii Framework Forum: CWidgetFactory property inheritance - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

CWidgetFactory property inheritance Setting property for a widget should have an effect on all children Rate Topic: ***** 1 Votes

#1 User is offline   pavlepredic 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 39
  • Joined: 30-August 11

Posted 23 March 2012 - 09:48 AM

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.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users