Commit 47fe25d4 by Qiang Xue

new event implementation.

parent e281b402
...@@ -19,7 +19,7 @@ namespace yii\base; ...@@ -19,7 +19,7 @@ namespace yii\base;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class Behavior extends Object class Behavior extends \yii\base\Object
{ {
/** /**
* @var Component the owner component * @var Component the owner component
...@@ -38,17 +38,17 @@ class Behavior extends Object ...@@ -38,17 +38,17 @@ class Behavior extends Object
* *
* The callbacks can be any of the followings: * The callbacks can be any of the followings:
* *
* - method in this behavior: `'handleOnClick'`, equivalent to `array($this, 'handleOnClick')` * - method in this behavior: `'handleClick'`, equivalent to `array($this, 'handleClick')`
* - object method: `array($object, 'handleOnClick')` * - object method: `array($object, 'handleClick')`
* - static method: `array('Page', 'handleOnClick')` * - static method: `array('Page', 'handleClick')`
* - anonymous function: `function($event) { ... }` * - anonymous function: `function($event) { ... }`
* *
* The following is an example: * The following is an example:
* *
* ~~~ * ~~~
* array( * array(
* 'onBeforeValidate' => 'myBeforeValidate', * 'beforeValidate' => 'myBeforeValidate',
* 'onAfterValidate' => 'myAfterValidate', * 'afterValidate' => 'myAfterValidate',
* ) * )
* ~~~ * ~~~
* *
...@@ -70,7 +70,7 @@ class Behavior extends Object ...@@ -70,7 +70,7 @@ class Behavior extends Object
{ {
$this->_owner = $owner; $this->_owner = $owner;
foreach ($this->events() as $event => $handler) { foreach ($this->events() as $event => $handler) {
$owner->attachEventHandler($event, is_string($handler) ? array($this, $handler) : $handler); $owner->on($event, is_string($handler) ? array($this, $handler) : $handler);
} }
} }
...@@ -84,7 +84,7 @@ class Behavior extends Object ...@@ -84,7 +84,7 @@ class Behavior extends Object
public function detach($owner) public function detach($owner)
{ {
foreach ($this->events() as $event => $handler) { foreach ($this->events() as $event => $handler) {
$owner->detachEventHandler($event, is_string($handler) ? array($this, $handler) : $handler); $owner->off($event, is_string($handler) ? array($this, $handler) : $handler);
} }
$this->_owner = null; $this->_owner = null;
} }
......
...@@ -12,34 +12,36 @@ namespace yii\base; ...@@ -12,34 +12,36 @@ namespace yii\base;
/** /**
* Component is the base class for all component classes in Yii. * Component is the base class for all component classes in Yii.
* *
* Extending from [[Object]], Component implements the *event* and *behavior* * Component provides the *event* and *behavior* features, in addition to
* features in addition to the *property* feature. * the *property* feature which is implemented in its parent class [[Object]].
* *
* An event is defined by the presence of a method whose name starts with `on`. * Event is a way to "inject" custom code into existing code at certain places.
* The event name is the method name. For example, the following method defines * For example, a button object can trigger a "click" event when the user clicks
* the `onClick` event: * on the button. We can write custom code and attach it to this event so that
* when the event is triggered, our custom code will be executed.
* *
* ~~~ * An event is identified by a name (unique within the class it is defined).
* public function onClick($event) * Event names are *case-sensitive*.
* {
* $this->raiseEvent('onClick', $event);
* }
* ~~~
*
* Event names are case-insensitive.
* *
* An event can be attached with one or multiple PHP callbacks, called *event handlers*. * An event can be attached with one or multiple PHP callbacks, called *event handlers*.
* One can call [[raiseEvent()]] to raise an event. When an event is raised, the attached * One can call [[trigger()]] to raise an event. When an event is raised, the attached
* event handlers will be invoked automatically in the order they are attached to the event. * event handlers will be invoked automatically in the order they are attached to the event.
* *
* To attach an event handler to an event, call [[attachEventHandler]]. Alternatively, * To attach an event handler to an event, call [[on()]]. For example,
* you can use the assignment syntax: `$component->onClick = $callback;`,
* where `$callback` refers to a valid PHP callback which can be one of the followings:
* *
* - global function: `'handleOnClick'` * ~~~
* $button->on('click', function($event) {
* echo "I'm clicked!";
* });
* ~~~
*
* In the above, we attach an anonymous function to the "click" event of the button.
* Valid event handlers include:
*
* - anonymous function: `function($event) { ... }`
* - object method: `array($object, 'handleOnClick')` * - object method: `array($object, 'handleOnClick')`
* - static method: `array('Page', 'handleOnClick')` * - static method: `array('Page', 'handleOnClick')`
* - anonymous function: `function($event) { ... }` * - global function: `'handleOnClick'`
* *
* The signature of an event handler should be like the following: * The signature of an event handler should be like the following:
* ~~~ * ~~~
...@@ -48,14 +50,15 @@ namespace yii\base; ...@@ -48,14 +50,15 @@ namespace yii\base;
* *
* where `$event` is an [[Event]] object which includes parameters associated with the event. * where `$event` is an [[Event]] object which includes parameters associated with the event.
* *
* Because `$component->onClick` is returned as a [[Vector]] with each item in the vector being * One can call [[getEventHandlers()]] to retrieve all event handlers that are attached
* an attached event handler, one can manipulate this [[Vector]] object to attach/detach event * to a specified event. Because this method returns a [[Vector]] object, we can manipulate
* handlers, or adjust their relative orders. For example, * this object to attach/detach event handlers, or adjust their relative orders.
* *
* ~~~ * ~~~
* $component->onClick->insertAt(0, $callback); // attach a handler as the first one * $handlers = $button->getEventHandlers('click');
* $component->onClick[] = $callback; // attach a handler as the last one * $handlers->insertAt(0, $callback); // attach a handler as the first one
* unset($component->onClick[0]); // detach the first handler * $handlers[] = $callback; // attach a handler as the last one
* unset($handlers[0]); // detach the first handler
* ~~~ * ~~~
* *
* *
...@@ -65,6 +68,7 @@ namespace yii\base; ...@@ -65,6 +68,7 @@ namespace yii\base;
* those properties and methods. * those properties and methods.
* *
* To attach a behavior to a component, declare it in [[behaviors()]], or explicitly call [[attachBehavior]]. * To attach a behavior to a component, declare it in [[behaviors()]], or explicitly call [[attachBehavior]].
* Behaviors declared in [[behaviors()]] are automatically attached to the corresponding component.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
...@@ -85,7 +89,6 @@ class Component extends \yii\base\Object ...@@ -85,7 +89,6 @@ class Component extends \yii\base\Object
* This method will check in the following order and act accordingly: * This method will check in the following order and act accordingly:
* *
* - a property defined by a getter: return the getter result * - a property defined by a getter: return the getter result
* - an event: return a vector containing the attached event handlers
* - a behavior: return the behavior object * - a behavior: return the behavior object
* - a property of a behavior: return the behavior property value * - a property of a behavior: return the behavior property value
* *
...@@ -102,12 +105,6 @@ class Component extends \yii\base\Object ...@@ -102,12 +105,6 @@ class Component extends \yii\base\Object
$getter = 'get' . $name; $getter = 'get' . $name;
if (method_exists($this, $getter)) { // read property, e.g. getName() if (method_exists($this, $getter)) { // read property, e.g. getName()
return $this->$getter(); return $this->$getter();
} elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { // event, e.g. onClick()
$name = strtolower($name);
if (!isset($this->_e[$name])) {
$this->_e[$name] = new Vector;
}
return $this->_e[$name];
} else { // behavior property } else { // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $behavior) {
...@@ -131,7 +128,6 @@ class Component extends \yii\base\Object ...@@ -131,7 +128,6 @@ class Component extends \yii\base\Object
* will be implicitly called when executing `$component->property = $value;`. * will be implicitly called when executing `$component->property = $value;`.
* @param string $name the property name or the event name * @param string $name the property name or the event name
* @param mixed $value the property value * @param mixed $value the property value
* @return mixed value that was set
* @throws Exception if the property is not defined or read-only. * @throws Exception if the property is not defined or read-only.
* @see __get * @see __get
*/ */
...@@ -139,18 +135,18 @@ class Component extends \yii\base\Object ...@@ -139,18 +135,18 @@ class Component extends \yii\base\Object
{ {
$setter = 'set' . $name; $setter = 'set' . $name;
if (method_exists($this, $setter)) { // write property if (method_exists($this, $setter)) { // write property
return $this->$setter($value); $this->$setter($value);
} elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { // event return;
$name = strtolower($name); } elseif (strncmp($name, 'on ', 3) === 0) { // on event
if (!isset($this->_e[$name])) { $name = substr($name, 3);
$this->_e[$name] = new Vector; $this->getEventHandlers($name)->add($value);
} return;
return $this->_e[$name]->add($value);
} else { // behavior property } else { // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $behavior) {
if ($behavior->canSetProperty($name)) { if ($behavior->canSetProperty($name)) {
return $behavior->$name = $value; $behavior->$name = $value;
return;
} }
} }
} }
...@@ -166,7 +162,6 @@ class Component extends \yii\base\Object ...@@ -166,7 +162,6 @@ class Component extends \yii\base\Object
* This method will check in the following order and act accordingly: * This method will check in the following order and act accordingly:
* *
* - a property defined by a setter: return whether the property value is null * - a property defined by a setter: return whether the property value is null
* - an event: return whether the event has any handler attached
* - a property of a behavior: return whether the property value is null * - a property of a behavior: return whether the property value is null
* *
* Do not call this method directly as it is a PHP magic method that * Do not call this method directly as it is a PHP magic method that
...@@ -179,9 +174,6 @@ class Component extends \yii\base\Object ...@@ -179,9 +174,6 @@ class Component extends \yii\base\Object
$getter = 'get' . $name; $getter = 'get' . $name;
if (method_exists($this, $getter)) { // property is not null if (method_exists($this, $getter)) { // property is not null
return $this->$getter() !== null; return $this->$getter() !== null;
} elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { // has event handler
$name = strtolower($name);
return isset($this->_e[$name]) && $this->_e[$name]->getCount();
} else { // behavior property } else { // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $behavior) {
...@@ -198,7 +190,6 @@ class Component extends \yii\base\Object ...@@ -198,7 +190,6 @@ class Component extends \yii\base\Object
* This method will check in the following order and act accordingly: * This method will check in the following order and act accordingly:
* *
* - a property defined by a setter: set the property value to be null * - a property defined by a setter: set the property value to be null
* - an event: remove all attached event handlers
* - a property of a behavior: set the property value to be null * - a property of a behavior: set the property value to be null
* *
* Do not call this method directly as it is a PHP magic method that * Do not call this method directly as it is a PHP magic method that
...@@ -212,9 +203,6 @@ class Component extends \yii\base\Object ...@@ -212,9 +203,6 @@ class Component extends \yii\base\Object
if (method_exists($this, $setter)) { // write property if (method_exists($this, $setter)) { // write property
$this->$setter(null); $this->$setter(null);
return; return;
} elseif (method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0) { // event
unset($this->_e[strtolower($name)]);
return;
} else { // behavior property } else { // behavior property
$this->ensureBehaviors(); $this->ensureBehaviors();
foreach ($this->_b as $behavior) { foreach ($this->_b as $behavior) {
...@@ -280,7 +268,7 @@ class Component extends \yii\base\Object ...@@ -280,7 +268,7 @@ class Component extends \yii\base\Object
* *
* Note that a behavior class must extend from [[Behavior]]. * Note that a behavior class must extend from [[Behavior]].
* *
* Behaviors declared in this method will be attached to the component on demand. * Behaviors declared in this method will be attached to the component automatically (on demand).
* *
* @return array the behavior configurations. * @return array the behavior configurations.
*/ */
...@@ -290,18 +278,6 @@ class Component extends \yii\base\Object ...@@ -290,18 +278,6 @@ class Component extends \yii\base\Object
} }
/** /**
* Returns a value indicating whether an event is defined.
* An event is defined if the class has a method whose name starts with `on` (e.g. `onClick`).
* Note that event name is case-insensitive.
* @param string $name the event name
* @return boolean whether an event is defined
*/
public function hasEvent($name)
{
return method_exists($this, $name) && strncasecmp($name, 'on', 2) === 0;
}
/**
* Returns a value indicating whether there is any handler attached to the named event. * Returns a value indicating whether there is any handler attached to the named event.
* @param string $name the event name * @param string $name the event name
* @return boolean whether there is any handler attached to the event. * @return boolean whether there is any handler attached to the event.
...@@ -309,7 +285,6 @@ class Component extends \yii\base\Object ...@@ -309,7 +285,6 @@ class Component extends \yii\base\Object
public function hasEventHandlers($name) public function hasEventHandlers($name)
{ {
$this->ensureBehaviors(); $this->ensureBehaviors();
$name = strtolower($name);
return isset($this->_e[$name]) && $this->_e[$name]->getCount(); return isset($this->_e[$name]) && $this->_e[$name]->getCount();
} }
...@@ -328,15 +303,12 @@ class Component extends \yii\base\Object ...@@ -328,15 +303,12 @@ class Component extends \yii\base\Object
*/ */
public function getEventHandlers($name) public function getEventHandlers($name)
{ {
if ($this->hasEvent($name)) {
$name = strtolower($name);
if (!isset($this->_e[$name])) { if (!isset($this->_e[$name])) {
$this->_e[$name] = new Vector; $this->_e[$name] = new Vector;
} }
$this->ensureBehaviors();
return $this->_e[$name]; return $this->_e[$name];
} }
throw new Exception('Undefined event: ' . $name);
}
/** /**
* Attaches an event handler to an event. * Attaches an event handler to an event.
...@@ -351,10 +323,10 @@ class Component extends \yii\base\Object ...@@ -351,10 +323,10 @@ class Component extends \yii\base\Object
* some examples: * some examples:
* *
* ~~~ * ~~~
* 'handleOnClick' // handleOnClick() is a global function
* array($object, 'handleOnClick') // $object->handleOnClick()
* array('Page', 'handleOnClick') // Page::handleOnClick()
* function($event) { ... } // anonymous function * function($event) { ... } // anonymous function
* array($object, 'handleClick') // $object->handleClick()
* array('Page', 'handleClick') // Page::handleClick()
* 'handleClick' // global function handleClick()
* ~~~ * ~~~
* *
* An event handler must be defined with the following signature, * An event handler must be defined with the following signature,
...@@ -367,68 +339,49 @@ class Component extends \yii\base\Object ...@@ -367,68 +339,49 @@ class Component extends \yii\base\Object
* *
* @param string $name the event name * @param string $name the event name
* @param callback $handler the event handler * @param callback $handler the event handler
* @throws Exception if the event is not defined * @see off
* @see detachEventHandler
*/ */
public function attachEventHandler($name, $handler) public function on($name, $handler)
{ {
$this->getEventHandlers($name)->add($handler); $this->getEventHandlers($name)->add($handler);
} }
/** /**
* Detaches an existing event handler. * Detaches an existing event handler.
* This method is the opposite of [[attachEventHandler]]. * This method is the opposite of [[on]].
* @param string $name event name * @param string $name event name
* @param callback $handler the event handler to be removed * @param callback $handler the event handler to be removed
* @return boolean if the detachment process is successful * @return boolean if a handler is found and detached
* @see attachEventHandler * @see on
*/ */
public function detachEventHandler($name, $handler) public function off($name, $handler)
{ {
return $this->getEventHandlers($name)->remove($handler) !== false; return $this->getEventHandlers($name)->remove($handler) !== false;
} }
/** /**
* Raises an event. * Triggers an event.
* This method represents the happening of an event. It invokes * This method represents the happening of an event. It invokes
* all attached handlers for the event. * all attached handlers for the event.
* @param string $name the event name * @param string $name the event name
* @param Event $event the event parameter * @param Event $event the event parameter
* @throws Exception if the event is undefined or an event handler is invalid. * @throws Exception if the event is undefined or an event handler is invalid.
*/ */
public function raiseEvent($name, $event) public function trigger($name, $event)
{ {
$this->ensureBehaviors(); $this->ensureBehaviors();
$name = strtolower($name); if (isset($this->_e[$name])) {
if ($event instanceof Event) { if ($event instanceof Event) {
$event->name = $name; $event->name = $name;
$event->handled = false; $event->handled = false;
} }
if (isset($this->_e[$name])) {
foreach ($this->_e[$name] as $handler) { foreach ($this->_e[$name] as $handler) {
if (is_string($handler) || $handler instanceof \Closure) {
call_user_func($handler, $event);
} elseif (is_callable($handler, true)) {
// an array: 0 - object, 1 - method name
list($object, $method) = $handler;
if (is_string($object)) { // static method call
call_user_func($handler, $event); call_user_func($handler, $event);
} elseif (method_exists($object, $method)) {
$object->$method($event);
} else {
throw new Exception('Event "' . get_class($this) . '.' . $name . '" is attached with an invalid handler.');
}
} else {
throw new Exception('Event "' . get_class($this) . '.' . $name . '" is attached with an invalid handler.');
}
// stop further handling if the event is handled // stop further handling if the event is handled
if ($event instanceof Event && $event->handled) { if ($event instanceof Event && $event->handled) {
return; return;
} }
} }
} elseif (!$this->hasEvent($name)) {
throw new Exception('Raising unknown event: ' . get_class($this) . '.' . $name);
} }
} }
......
...@@ -24,9 +24,8 @@ class ModelBehavior extends Behavior ...@@ -24,9 +24,8 @@ class ModelBehavior extends Behavior
* Declares event handlers for owner's events. * Declares event handlers for owner's events.
* The default implementation returns the following event handlers: * The default implementation returns the following event handlers:
* *
* - `onAfterInit` event: [[afterInit]] * - `beforeValidate` event
* - `onBeforeValidate` event: [[beforeValidate]] * - `afterValidate` event
* - `onAfterValidate` event: [[afterValidate]]
* *
* You may override these event handler methods to respond to the corresponding owner events. * You may override these event handler methods to respond to the corresponding owner events.
* @return array events (array keys) and the corresponding event handler methods (array values). * @return array events (array keys) and the corresponding event handler methods (array values).
...@@ -34,22 +33,12 @@ class ModelBehavior extends Behavior ...@@ -34,22 +33,12 @@ class ModelBehavior extends Behavior
public function events() public function events()
{ {
return array( return array(
'onAfterInit' => 'afterInit', 'beforeValidate' => 'beforeValidate',
'onBeforeValidate' => 'beforeValidate', 'afterValidate' => 'afterValidate',
'onAfterValidate' => 'afterValidate',
); );
} }
/** /**
* Responds to [[Model::onAfterInit]] event.
* Override this method if you want to handle the corresponding event of the [[owner]].
* @param Event $event event parameter
*/
public function afterInit($event)
{
}
/**
* Responds to [[Model::onBeforeValidate]] event. * Responds to [[Model::onBeforeValidate]] event.
* Override this method if you want to handle the corresponding event of the [[owner]]. * Override this method if you want to handle the corresponding event of the [[owner]].
* You may set the [[ModelEvent::isValid|isValid]] property of the event parameter * You may set the [[ModelEvent::isValid|isValid]] property of the event parameter
......
...@@ -294,7 +294,7 @@ class Object ...@@ -294,7 +294,7 @@ class Object
* ~~~ * ~~~
* *
* @param array $config the object configuration (name-value pairs that will be used to initialize the object) * @param array $config the object configuration (name-value pairs that will be used to initialize the object)
* @return Object the created object * @return \yii\base\Object the created object
* @throws Exception if the configuration is invalid. * @throws Exception if the configuration is invalid.
*/ */
public static function newInstance($config = array()) public static function newInstance($config = array())
...@@ -326,7 +326,7 @@ class Object ...@@ -326,7 +326,7 @@ class Object
$object->$name = $value; $object->$name = $value;
} }
if ($object instanceof \yii\base\Initable) { if ($object instanceof Initable) {
$object->init(); $object->init();
} }
......
...@@ -4,17 +4,20 @@ namespace yiiunit\framework\base; ...@@ -4,17 +4,20 @@ namespace yiiunit\framework\base;
function globalEventHandler($event) function globalEventHandler($event)
{ {
$event->sender->eventHandled=true; $event->sender->eventHandled = true;
} }
function globalEventHandler2($event) function globalEventHandler2($event)
{ {
$event->sender->eventHandled=true; $event->sender->eventHandled = true;
$event->handled=true; $event->handled = true;
} }
class ComponentTest extends \yiiunit\TestCase class ComponentTest extends \yiiunit\TestCase
{ {
/**
* @var NewComponent
*/
protected $component; protected $component;
public function setUp() public function setUp()
...@@ -50,19 +53,19 @@ class ComponentTest extends \yiiunit\TestCase ...@@ -50,19 +53,19 @@ class ComponentTest extends \yiiunit\TestCase
public function testGetProperty() public function testGetProperty()
{ {
$this->assertTrue('default'===$this->component->Text); $this->assertTrue('default' === $this->component->Text);
$this->setExpectedException('yii\base\Exception'); $this->setExpectedException('yii\base\Exception');
$value2=$this->component->Caption; $value2 = $this->component->Caption;
} }
public function testSetProperty() public function testSetProperty()
{ {
$value='new value'; $value = 'new value';
$this->component->Text=$value; $this->component->Text = $value;
$text=$this->component->Text; $text = $this->component->Text;
$this->assertTrue($value===$this->component->Text); $this->assertTrue($value === $this->component->Text);
$this->setExpectedException('yii\base\Exception'); $this->setExpectedException('yii\base\Exception');
$this->component->NewMember=$value; $this->component->NewMember = $value;
} }
public function testIsset() public function testIsset()
...@@ -74,123 +77,89 @@ class ComponentTest extends \yiiunit\TestCase ...@@ -74,123 +77,89 @@ class ComponentTest extends \yiiunit\TestCase
$this->assertFalse(isset($this->component->Text)); $this->assertFalse(isset($this->component->Text));
$this->assertFalse(!empty($this->component->Text)); $this->assertFalse(!empty($this->component->Text));
$this->component->Text=''; $this->component->Text = '';
$this->assertTrue(isset($this->component->Text)); $this->assertTrue(isset($this->component->Text));
$this->assertTrue(empty($this->component->Text)); $this->assertTrue(empty($this->component->Text));
} }
public function testHasEvent() public function testOn()
{ {
$this->assertTrue($this->component->hasEvent('OnMyEvent')); $this->assertEquals(0, $this->component->getEventHandlers('click')->getCount());
$this->assertTrue($this->component->hasEvent('onmyevent')); $this->component->on('click', 'foo');
$this->assertFalse($this->component->hasEvent('onYourEvent')); $this->assertEquals(1, $this->component->getEventHandlers('click')->getCount());
} $this->component->on('click', 'bar');
$this->assertEquals(2, $this->component->getEventHandlers('click')->getCount());
public function testHasEventHandlers()
{
$this->assertFalse($this->component->hasEventHandlers('OnMyEvent'));
$this->component->attachEventHandler('OnMyEvent','foo');
$this->assertTrue($this->component->hasEventHandlers('OnMyEvent'));
}
public function testGetEventHandlers()
{
$list=$this->component->getEventHandlers('OnMyEvent');
$this->assertEquals($list->getCount(),0);
$this->component->attachEventHandler('OnMyEvent','foo');
$this->assertEquals($list->getCount(),1);
$this->setExpectedException('yii\base\Exception');
$list=$this->component->getEventHandlers('YourEvent');
}
public function testAttachEventHandler() $this->component->getEventHandlers('click')->add('test');
{ $this->assertEquals(3, $this->component->getEventHandlers('click')->getCount());
$this->component->attachEventHandler('OnMyEvent','foo');
$this->assertTrue($this->component->getEventHandlers('OnMyEvent')->getCount()===1);
$this->setExpectedException('yii\base\Exception');
$this->component->attachEventHandler('YourEvent','foo');
} }
public function testDettachEventHandler() public function testOff()
{ {
$this->component->attachEventHandler('OnMyEvent','foo'); $this->component->on('click', 'foo');
$this->component->attachEventHandler('OnMyEvent',array($this->component,'myEventHandler')); $this->component->on('click', array($this->component, 'myEventHandler'));
$this->assertEquals($this->component->getEventHandlers('OnMyEvent')->getCount(),2); $this->assertEquals(2, $this->component->getEventHandlers('click')->getCount());
$this->assertTrue($this->component->detachEventHandler('OnMyEvent','foo'));
$this->assertEquals($this->component->getEventHandlers('OnMyEvent')->getCount(),1);
$this->assertFalse($this->component->detachEventHandler('OnMyEvent','foo')); $result = $this->component->off('click', 'foo');
$this->assertEquals($this->component->getEventHandlers('OnMyEvent')->getCount(),1); $this->assertTrue($result);
$this->assertEquals(1, $this->component->getEventHandlers('click')->getCount());
$this->assertTrue($this->component->detachEventHandler('OnMyEvent',array($this->component,'myEventHandler'))); $result = $this->component->off('click', 'foo');
$this->assertEquals($this->component->getEventHandlers('OnMyEvent')->getCount(),0); $this->assertFalse($result);
$this->assertEquals(1, $this->component->getEventHandlers('click')->getCount());
$this->assertFalse($this->component->detachEventHandler('OnMyEvent','foo')); $result = $this->component->off('click', array($this->component, 'myEventHandler'));
$this->assertTrue($result);
$this->assertEquals(0, $this->component->getEventHandlers('click')->getCount());
} }
public function testRaiseEvent() public function testTrigger()
{ {
$this->component->attachEventHandler('OnMyEvent',array($this->component,'myEventHandler')); $this->component->on('click', array($this->component, 'myEventHandler'));
$this->assertFalse($this->component->eventHandled); $this->assertFalse($this->component->eventHandled);
$this->component->raiseEvent('OnMyEvent',new \yii\base\Event($this)); $this->assertNull($this->component->event);
$this->component->raiseEvent();
$this->assertTrue($this->component->eventHandled); $this->assertTrue($this->component->eventHandled);
$this->assertEquals('click', $this->component->event->name);
$this->assertEquals($this->component, $this->component->event->sender);
$this->assertFalse($this->component->event->handled);
$this->setExpectedException('yii\base\Exception'); $eventRaised = false;
$this->component->raiseEvent('OnUnknown',new \yii\base\Event($this)); $this->component->on('click', function($event) use (&$eventRaised) {
$eventRaised = true;
});
$this->component->raiseEvent();
$this->assertTrue($eventRaised);
} }
public function testEventAccessor() public function testHasEventHandlers()
{ {
$component=new NewComponent; $this->assertFalse($this->component->hasEventHandlers('click'));
$this->assertEquals($component->onMyEvent->getCount(),0); $this->component->on('click', 'foo');
$component->onMyEvent='yiiunit\framework\base\globalEventHandler'; $this->assertTrue($this->component->hasEventHandlers('click'));
$component->onMyEvent=array($this->component,'myEventHandler');
$this->assertEquals($component->onMyEvent->getCount(),2);
$this->assertFalse($component->eventHandled);
$this->assertFalse($this->component->eventHandled);
$component->onMyEvent();
$this->assertTrue($component->eventHandled);
$this->assertTrue($this->component->eventHandled);
} }
public function testStopEvent() public function testStopEvent()
{ {
$component=new NewComponent; $component = new NewComponent;
$component->onMyEvent='yiiunit\framework\base\globalEventHandler2'; $component->on('click', 'yiiunit\framework\base\globalEventHandler2');
$component->onMyEvent=array($this->component,'myEventHandler'); $component->on('click', array($this->component, 'myEventHandler'));
$component->onMyEvent(); $component->raiseEvent();
$this->assertTrue($component->eventHandled); $this->assertTrue($component->eventHandled);
$this->assertFalse($this->component->eventHandled); $this->assertFalse($this->component->eventHandled);
} }
public function testInvalidHandler1()
{
$this->component->onMyEvent=array(1,2,3);
$this->setExpectedException('yii\base\Exception');
$this->component->onMyEvent();
}
public function testInvalidHandler2()
{
$this->component->onMyEvent=array($this->component,'nullHandler');
$this->setExpectedException('yii\base\Exception');
$this->component->onMyEvent();
}
public function testDetachBehavior() public function testDetachBehavior()
{ {
$component=new NewComponent; $component = new NewComponent;
$behavior = new NewBehavior; $behavior = new NewBehavior;
$component->attachBehavior('a',$behavior); $component->attachBehavior('a', $behavior);
$this->assertSame($behavior,$component->detachBehavior('a')); $this->assertSame($behavior, $component->detachBehavior('a'));
} }
public function testDetachingBehaviors() public function testDetachingBehaviors()
{ {
$component=new NewComponent; $component = new NewComponent;
$behavior = new NewBehavior; $behavior = new NewBehavior;
$component->attachBehavior('a',$behavior); $component->attachBehavior('a', $behavior);
$component->detachBehaviors(); $component->detachBehaviors();
$this->setExpectedException('yii\base\Exception'); $this->setExpectedException('yii\base\Exception');
$component->test(); $component->test();
...@@ -198,15 +167,15 @@ class ComponentTest extends \yiiunit\TestCase ...@@ -198,15 +167,15 @@ class ComponentTest extends \yiiunit\TestCase
public function testAsa() public function testAsa()
{ {
$component=new NewComponent; $component = new NewComponent;
$behavior = new NewBehavior; $behavior = new NewBehavior;
$component->attachBehavior('a',$behavior); $component->attachBehavior('a', $behavior);
$this->assertSame($behavior,$component->asa('a')); $this->assertSame($behavior, $component->asa('a'));
} }
public function testCreate() public function testCreate()
{ {
$component = NewComponent2::newInstance(array('a'=>3), 1, 2); $component = NewComponent2::newInstance(array('a' => 3), 1, 2);
$this->assertEquals(1, $component->b); $this->assertEquals(1, $component->b);
$this->assertEquals(2, $component->c); $this->assertEquals(2, $component->c);
$this->assertEquals(3, $component->a); $this->assertEquals(3, $component->a);
...@@ -218,6 +187,7 @@ class NewComponent extends \yii\base\Component ...@@ -218,6 +187,7 @@ class NewComponent extends \yii\base\Component
private $_object = null; private $_object = null;
private $_text = 'default'; private $_text = 'default';
public $eventHandled = false; public $eventHandled = false;
public $event;
public $behaviorCalled = false; public $behaviorCalled = false;
public function getText() public function getText()
...@@ -227,30 +197,27 @@ class NewComponent extends \yii\base\Component ...@@ -227,30 +197,27 @@ class NewComponent extends \yii\base\Component
public function setText($value) public function setText($value)
{ {
$this->_text=$value; $this->_text = $value;
} }
public function getObject() public function getObject()
{ {
if(!$this->_object) if (!$this->_object) {
{ $this->_object = new NewComponent;
$this->_object=new NewComponent; $this->_object->_text = 'object text';
$this->_object->_text='object text';
} }
return $this->_object; return $this->_object;
} }
public function onMyEvent() public function myEventHandler($event)
{ {
$this->raiseEvent('OnMyEvent',new \yii\base\Event($this)); $this->eventHandled = true;
$this->event = $event;
} }
public function myEventHandler($event) public function raiseEvent()
{ {
$this->eventHandled=true; $this->trigger('click', new \yii\base\Event($this));
}
public function exprEvaluator($p1,$comp) {
return "Hello $p1";
} }
} }
...@@ -258,7 +225,7 @@ class NewBehavior extends \yii\base\Behavior ...@@ -258,7 +225,7 @@ class NewBehavior extends \yii\base\Behavior
{ {
public function test() public function test()
{ {
$this->owner->behaviorCalled=true; $this->owner->behaviorCalled = true;
return 2; return 2;
} }
} }
...@@ -268,6 +235,7 @@ class NewComponent2 extends \yii\base\Component ...@@ -268,6 +235,7 @@ class NewComponent2 extends \yii\base\Component
public $a; public $a;
public $b; public $b;
public $c; public $c;
public function __construct($b, $c) public function __construct($b, $c)
{ {
$this->b = $b; $this->b = $b;
......
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