Commit cc0be8ad by Qiang Xue

support anonymous behaviors.

parent c9097ed0
...@@ -14,7 +14,8 @@ namespace yii\base; ...@@ -14,7 +14,8 @@ namespace yii\base;
* *
* A behavior can be used to enhance the functionality of an existing component without modifying its code. * A behavior can be used to enhance the functionality of an existing component without modifying its code.
* In particular, it can "inject" its own methods and properties into the component * In particular, it can "inject" its own methods and properties into the component
* and make them directly accessible via the component. * and make them directly accessible via the component. It can also respond to the events triggered in the component
* and thus intercept the normal code execution.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
......
...@@ -53,8 +53,8 @@ class Component extends \yii\base\Object ...@@ -53,8 +53,8 @@ class Component extends \yii\base\Object
} else { } else {
// behavior property // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $i => $behavior) {
if ($behavior->canGetProperty($name)) { if (is_string($i) && $behavior->canGetProperty($name)) {
return $behavior->$name; return $behavior->$name;
} }
} }
...@@ -96,8 +96,8 @@ class Component extends \yii\base\Object ...@@ -96,8 +96,8 @@ class Component extends \yii\base\Object
} else { } else {
// behavior property // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $i => $behavior) {
if ($behavior->canSetProperty($name)) { if (is_string($i) && $behavior->canSetProperty($name)) {
$behavior->$name = $value; $behavior->$name = $value;
return; return;
} }
...@@ -131,8 +131,8 @@ class Component extends \yii\base\Object ...@@ -131,8 +131,8 @@ class Component extends \yii\base\Object
} else { } else {
// behavior property // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $i => $behavior) {
if ($behavior->canGetProperty($name)) { if (is_string($i) && $behavior->canGetProperty($name)) {
return $behavior->$name !== null; return $behavior->$name !== null;
} }
} }
...@@ -162,8 +162,8 @@ class Component extends \yii\base\Object ...@@ -162,8 +162,8 @@ class Component extends \yii\base\Object
} else { } else {
// behavior property // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $i => $behavior) {
if ($behavior->canSetProperty($name)) { if (is_string($i) && $behavior->canSetProperty($name)) {
$behavior->$name = null; $behavior->$name = null;
return; return;
} }
...@@ -198,8 +198,8 @@ class Component extends \yii\base\Object ...@@ -198,8 +198,8 @@ class Component extends \yii\base\Object
} }
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $object) { foreach ($this->_b as $i => $object) {
if (method_exists($object, $name)) { if (is_string($i) && method_exists($object, $name)) {
return call_user_func_array(array($object, $name), $params); return call_user_func_array(array($object, $name), $params);
} }
} }
...@@ -224,7 +224,10 @@ class Component extends \yii\base\Object ...@@ -224,7 +224,10 @@ class Component extends \yii\base\Object
* ) * )
* ~~~ * ~~~
* *
* Note that a behavior class must extend from [[Behavior]]. * Note that a behavior class must extend from [[Behavior]]. Behavior names can be strings
* or integers. If the former, they uniquely identify the behaviors. If the latter, the corresponding
* behaviors are anonymous and their properties and methods will NOT be made available via the component
* (however, the behaviors can still respond to the component's events).
* *
* Behaviors declared in this method will be attached to the component automatically (on demand). * Behaviors declared in this method will be attached to the component automatically (on demand).
* *
...@@ -348,13 +351,23 @@ class Component extends \yii\base\Object ...@@ -348,13 +351,23 @@ class Component extends \yii\base\Object
/** /**
* Returns the named behavior object. * Returns the named behavior object.
* @param string $behavior the behavior name * @param string $name the behavior name
* @return Behavior the behavior object, or null if the behavior does not exist * @return Behavior the behavior object, or null if the behavior does not exist
*/ */
public function getBehavior($behavior) public function getBehavior($name)
{ {
$this->ensureBehaviors(); $this->ensureBehaviors();
return isset($this->_b[$behavior]) ? $this->_b[$behavior] : null; return isset($this->_b[$name]) ? $this->_b[$name] : null;
}
/**
* Returns all behaviors attached to this component.
* @return Behavior[] list of behaviors attached to this component
*/
public function getBehaviors()
{
$this->ensureBehaviors();
return $this->_b;
} }
/** /**
...@@ -362,7 +375,9 @@ class Component extends \yii\base\Object ...@@ -362,7 +375,9 @@ class Component extends \yii\base\Object
* This method will create the behavior object based on the given * This method will create the behavior object based on the given
* configuration. After that, the behavior object will be attached to * configuration. After that, the behavior object will be attached to
* this component by calling the [[Behavior::attach]] method. * this component by calling the [[Behavior::attach]] method.
* @param string $name the behavior's name. It should uniquely identify this behavior. * @param integer|string $name the name of the behavior. This can be a string or an integer (or empty string).
* If the former, it uniquely identifies this behavior. If the latter, the behavior becomes
* anonymous and its methods and properties will NOT be made available in this component.
* @param string|array|Behavior $behavior the behavior configuration. This can be one of the following: * @param string|array|Behavior $behavior the behavior configuration. This can be one of the following:
* *
* - a [[Behavior]] object * - a [[Behavior]] object
...@@ -381,8 +396,7 @@ class Component extends \yii\base\Object ...@@ -381,8 +396,7 @@ class Component extends \yii\base\Object
/** /**
* Attaches a list of behaviors to the component. * Attaches a list of behaviors to the component.
* Each behavior is indexed by its name and should be a [[Behavior]] object, * Each behavior is indexed by its name and should be a [[Behavior]] object,
* a string specifying the behavior class, or an * a string specifying the behavior class, or an configuration array for creating the behavior.
* configuration array for creating the behavior.
* @param array $behaviors list of behaviors to be attached to the component * @param array $behaviors list of behaviors to be attached to the component
* @see attachBehavior * @see attachBehavior
*/ */
...@@ -441,7 +455,8 @@ class Component extends \yii\base\Object ...@@ -441,7 +455,8 @@ class Component extends \yii\base\Object
/** /**
* Attaches a behavior to this component. * Attaches a behavior to this component.
* @param string $name the name of the behavior. * @param integer|string $name the name of the behavior. If it is an integer or an empty string,
* the behavior is anonymous and its methods and properties will NOT be made available to the owner component.
* @param string|array|Behavior $behavior the behavior to be attached * @param string|array|Behavior $behavior the behavior to be attached
* @return Behavior the attached behavior. * @return Behavior the attached behavior.
*/ */
...@@ -450,13 +465,16 @@ class Component extends \yii\base\Object ...@@ -450,13 +465,16 @@ class Component extends \yii\base\Object
if (!($behavior instanceof Behavior)) { if (!($behavior instanceof Behavior)) {
$behavior = \Yii::createObject($behavior); $behavior = \Yii::createObject($behavior);
} }
if (is_int($name)) { if (is_int($name) || $name == '') {
$name = '_b ' . $name; // anonymous behavior // anonymous behavior
} $behavior->attach($this);
if (isset($this->_b[$name])) { return $this->_b[] = $behavior;
$this->_b[$name]->detach($this); } else {
if (isset($this->_b[$name])) {
$this->_b[$name]->detach($this);
}
$behavior->attach($this);
return $this->_b[$name] = $behavior;
} }
$behavior->attach($this);
return $this->_b[$name] = $behavior;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment