diff --git a/.gitattributes b/.gitattributes index 7325c69..071ca8d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ +/benchmarks export-ignore /test export-ignore /vendor export-ignore .coveralls.yml export-ignore diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d4dcbe..277b7ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,15 +2,49 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. -## 2.5.3 - TBD +## 2.6.0 - 2015-09-29 ### Added -- Nothing. +- Added `Zend\EventManager\SharedEventsCapableInterface`. This interface will + largely replace `Zend\EventManager\SharedEventManagerAwareInterface` in + version 3, and the latter was updated to extend it. +- Added `EventManager::triggerEvent(EventInterface $event)` as a + forwards-compatibility feature. +- Add `EventManager::triggerEventUntil(callable $callback, EventIterface $event)` + as a forwards-compatibility feature. +- Adds [Athletic](https://github.com/polyfractal/athletic) benchmarks to aid in + gauging performanc impact of changes; these are a development change only. ### Deprecated -- Nothing. +- Marked `GlobalEventManager` as deprecated; this class will be removed in + version 3. +- Marked `StaticEventManager` as deprecated; this class will be removed in + version 3. +- Marked `SharedListenerAggregateInterface` as deprecated; this interface will + be removed in version 3. +- Marked `SharedEventAggregateAwareInterface` as deprecated; this interface will + be removed in version 3. +- Marked `SharedEventManagerAwareInterface` as deprecated; this interface will + be removed in version 3. +- Marked `EventManager::setSharedManager()` as deprecated; this method will be + removed in version 3. +- Marked `EventManager::unsetSharedManager()` as deprecated; this method will be + removed in version 3. +- Marked `EventManagerInterface::` and `EventManager::getEvents()` as + deprecated; this method will be removed in version 3. +- Marked `EventManagerInterface::` and `EventManager::getListeners()` as + deprecated; this method will be removed in version 3. +- Marked `EventManagerInterface::` and `Eventmanager::setEventClass()` as + deprecated; this method is renamed to `setEventPrototype(EventInterface $event)` + in version 3. +- Marked `EventManagerInterface::` and `EventManager::attachAggregate()` as + deprecated; this method will be removed in version 3. +- Marked `EventManagerInterface::` and `EventManager::detachAggregate()` as + deprecated; this method will be removed in version 3. +- Marked `SharedEventManagerInterface::` and `SharedEventManager::getEvents()` + as deprecated; this method will be removed in version 3. ### Removed diff --git a/composer.json b/composer.json index 5dd096f..28ef7eb 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,8 @@ "prefer-stable": true, "extra": { "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" + "dev-master": "2.6-dev", + "dev-develop": "3.0-dev" } }, "autoload-dev": { diff --git a/src/EventManager.php b/src/EventManager.php index bd9619e..c19e0b3 100644 --- a/src/EventManager.php +++ b/src/EventManager.php @@ -62,6 +62,9 @@ public function __construct($identifiers = null) /** * Set the event class to utilize * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param string $class * @return EventManager */ @@ -74,6 +77,9 @@ public function setEventClass($class) /** * Set shared event manager * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param SharedEventManagerInterface $sharedEventManager * @return EventManager */ @@ -87,6 +93,9 @@ public function setSharedManager(SharedEventManagerInterface $sharedEventManager /** * Remove any shared event manager currently attached * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @return void */ public function unsetSharedManager() @@ -212,12 +221,14 @@ public function trigger($event, $target = null, $argv = [], $callback = null) * Triggers listeners until the provided callback evaluates the return * value of one as true, or until all listeners have been executed. * + * @deprecated The signature of this method will change in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/changed.md} + * for details. * @param string|EventInterface $event * @param string|object $target Object calling emit, or symbol describing target (such as static method name) * @param array|ArrayAccess $argv Array of arguments; typically, should be associative * @param callable $callback * @return ResponseCollection - * @deprecated Please use trigger() * @throws Exception\InvalidCallbackException if invalid callable provided */ public function triggerUntil($event, $target, $argv = null, $callback = null) @@ -229,6 +240,29 @@ public function triggerUntil($event, $target, $argv = null, $callback = null) return $this->trigger($event, $target, $argv, $callback); } + /** + * Trigger an event instance. + * + * @param EventInterface $event + * @return ResponseCollection + */ + public function triggerEvent(EventInterface $event) + { + return $this->triggerListeners($event->getName(), $event); + } + + /** + * Trigger an event instance, short-circuiting if a listener response evaluates true via the callback. + * + * @param callable $callback + * @param EventInterface $event + * @return ResponseCollection + */ + public function triggerEventUntil(callable $callback, EventInterface $event) + { + return $this->triggerListeners($event->getName(), $event, $callback); + } + /** * Attach a listener to an event * @@ -293,6 +327,9 @@ public function attach($event, $callback = null, $priority = 1) * one or more times, typically to attach to multiple events using local * methods. * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param ListenerAggregateInterface $aggregate * @param int $priority If provided, a suggested priority for the aggregate to use * @return mixed return value of {@link ListenerAggregateInterface::attach()} @@ -343,6 +380,9 @@ public function detach($listener) * Listener aggregates accept an EventManagerInterface instance, and call detach() * of all previously attached listeners. * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param ListenerAggregateInterface $aggregate * @return mixed return value of {@link ListenerAggregateInterface::detach()} */ @@ -354,6 +394,9 @@ public function detachAggregate(ListenerAggregateInterface $aggregate) /** * Retrieve all registered events * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @return array */ public function getEvents() @@ -364,6 +407,9 @@ public function getEvents() /** * Retrieve all listeners for a given event * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param string $event * @return PriorityQueue */ diff --git a/src/EventManagerInterface.php b/src/EventManagerInterface.php index 9b689cd..b05c3e5 100644 --- a/src/EventManagerInterface.php +++ b/src/EventManagerInterface.php @@ -44,12 +44,14 @@ public function trigger($event, $target = null, $argv = [], $callback = null); * - Passing event name, target, Event object, and callback * - Passing event name, target, array|ArrayAccess of arguments, and callback * + * @deprecated The signature of this method will change in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/changed.md} + * for details. * @param string|EventInterface $event * @param object|string $target * @param array|object $argv * @param callable $callback * @return ResponseCollection - * @deprecated Please use trigger() */ public function triggerUntil($event, $target, $argv = null, $callback = null); @@ -74,6 +76,9 @@ public function detach($listener); /** * Get a list of events for which this collection has listeners * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @return array */ public function getEvents(); @@ -81,6 +86,9 @@ public function getEvents(); /** * Retrieve a list of listeners registered to a given event * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param string $event * @return array|object */ @@ -97,6 +105,9 @@ public function clearListeners($event); /** * Set the event class to utilize * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param string $class * @return EventManagerInterface */ @@ -128,6 +139,9 @@ public function addIdentifiers($identifiers); /** * Attach a listener aggregate * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param ListenerAggregateInterface $aggregate * @param int $priority If provided, a suggested priority for the aggregate to use * @return mixed return value of {@link ListenerAggregateInterface::attach()} @@ -137,6 +151,9 @@ public function attachAggregate(ListenerAggregateInterface $aggregate, $priority /** * Detach a listener aggregate * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param ListenerAggregateInterface $aggregate * @return mixed return value of {@link ListenerAggregateInterface::detach()} */ diff --git a/src/GlobalEventManager.php b/src/GlobalEventManager.php index c0ca983..6bf37d0 100644 --- a/src/GlobalEventManager.php +++ b/src/GlobalEventManager.php @@ -17,6 +17,10 @@ * * Use the EventManager when you want to create a per-instance notification * system for your objects. + * + * @deprecated This class is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. */ class GlobalEventManager { diff --git a/src/SharedEventAggregateAwareInterface.php b/src/SharedEventAggregateAwareInterface.php index 73b849c..b5e9506 100644 --- a/src/SharedEventAggregateAwareInterface.php +++ b/src/SharedEventAggregateAwareInterface.php @@ -11,6 +11,10 @@ /** * Interface for allowing attachment of shared aggregate listeners. + * + * @deprecated This interface is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. */ interface SharedEventAggregateAwareInterface { diff --git a/src/SharedEventManager.php b/src/SharedEventManager.php index c85a569..3271d7b 100644 --- a/src/SharedEventManager.php +++ b/src/SharedEventManager.php @@ -123,6 +123,9 @@ public function detachAggregate(SharedListenerAggregateInterface $aggregate) /** * Retrieve all registered events for a given resource * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param string|int $id * @return array */ diff --git a/src/SharedEventManagerAwareInterface.php b/src/SharedEventManagerAwareInterface.php index f6c05ec..1e4e3f0 100644 --- a/src/SharedEventManagerAwareInterface.php +++ b/src/SharedEventManagerAwareInterface.php @@ -11,8 +11,12 @@ /** * Interface to automate setter injection for a SharedEventManagerInterface instance + * + * @deprecated This interface is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. */ -interface SharedEventManagerAwareInterface +interface SharedEventManagerAwareInterface extends SharedEventsCapableInterface { /** * Inject a SharedEventManager instance @@ -22,13 +26,6 @@ interface SharedEventManagerAwareInterface */ public function setSharedManager(SharedEventManagerInterface $sharedEventManager); - /** - * Get shared collections container - * - * @return SharedEventManagerInterface - */ - public function getSharedManager(); - /** * Remove any shared collections * diff --git a/src/SharedEventManagerInterface.php b/src/SharedEventManagerInterface.php index 1e26c57..74ad682 100644 --- a/src/SharedEventManagerInterface.php +++ b/src/SharedEventManagerInterface.php @@ -49,6 +49,9 @@ public function detach($id, CallbackHandler $listener); /** * Retrieve all registered events for a given resource * + * @deprecated This method is deprecated with 2.6.0, and will be removed in 3.0.0. + * See {@link https://github.com/zendframework/zend-eventmanager/blob/develop/doc/book/migration/removed.md} + * for details. * @param string|int $id * @return array */ diff --git a/src/SharedEventsCapableInterface.php b/src/SharedEventsCapableInterface.php new file mode 100644 index 0000000..f367acb --- /dev/null +++ b/src/SharedEventsCapableInterface.php @@ -0,0 +1,24 @@ +events->attach('foo.bar', function () { return 'bogus'; }, 4); $this->events->attach('foo.bar', function () { return 'nada'; }, 3); $this->events->attach('foo.bar', function () { return 'found'; }, 2); $this->events->attach('foo.bar', function () { return 'zero'; }, 1); + // @codingStandardsIgnoreEnd + $responses = $this->events->trigger('foo.bar', $this, [], function ($result) { return ($result === 'found'); }); @@ -217,10 +220,13 @@ public function testTriggerUntilShouldMarkResponseCollectionStoppedWhenCondition public function testTriggerUntilShouldMarkResponseCollectionStoppedWhenConditionMetByLastListener() { + // @codingStandardsIgnoreStart $this->events->attach('foo.bar', function () { return 'bogus'; }); $this->events->attach('foo.bar', function () { return 'nada'; }); $this->events->attach('foo.bar', function () { return 'zero'; }); $this->events->attach('foo.bar', function () { return 'found'; }); + // @codingStandardsIgnoreEnd + $responses = $this->events->trigger('foo.bar', $this, [], function ($result) { return ($result === 'found'); }); @@ -231,10 +237,13 @@ public function testTriggerUntilShouldMarkResponseCollectionStoppedWhenCondition public function testResponseCollectionIsNotStoppedWhenNoCallbackMatchedByTriggerUntil() { + // @codingStandardsIgnoreStart $this->events->attach('foo.bar', function () { return 'bogus'; }, 4); $this->events->attach('foo.bar', function () { return 'nada'; }, 3); $this->events->attach('foo.bar', function () { return 'found'; }, 2); $this->events->attach('foo.bar', function () { return 'zero'; }, 1); + // @codingStandardsIgnoreEnd + $responses = $this->events->trigger('foo.bar', $this, [], function ($result) { return ($result === 'never found'); }); @@ -370,10 +379,13 @@ public function testAttachAggregateAcceptsOptionalPriorityValueViaAttachCallback public function testCallingEventsStopPropagationMethodHaltsEventEmission() { + // @codingStandardsIgnoreStart $this->events->attach('foo.bar', function ($e) { return 'bogus'; }, 4); $this->events->attach('foo.bar', function ($e) { $e->stopPropagation(true); return 'nada'; }, 3); $this->events->attach('foo.bar', function ($e) { return 'found'; }, 2); $this->events->attach('foo.bar', function ($e) { return 'zero'; }, 1); + // @codingStandardsIgnoreEnd + $responses = $this->events->trigger('foo.bar', $this, []); $this->assertInstanceOf('Zend\EventManager\ResponseCollection', $responses); $this->assertTrue($responses->stopped()); @@ -385,6 +397,7 @@ public function testCallingEventsStopPropagationMethodHaltsEventEmission() public function testCanAlterParametersWithinAEvent() { + // @codingStandardsIgnoreStart $this->events->attach('foo.bar', function ($e) { $e->setParam('foo', 'bar'); }); $this->events->attach('foo.bar', function ($e) { $e->setParam('bar', 'baz'); }); $this->events->attach('foo.bar', function ($e) { @@ -392,6 +405,8 @@ public function testCanAlterParametersWithinAEvent() $bar = $e->getParam('bar', '__NO_BAR__'); return $foo . ":" . $bar; }); + // @codingStandardsIgnoreEnd + $responses = $this->events->trigger('foo.bar', $this, []); $this->assertEquals('bar:baz', $responses->last()); } @@ -400,8 +415,12 @@ public function testParametersArePassedToEventByReference() { $params = [ 'foo' => 'bar', 'bar' => 'baz']; $args = $this->events->prepareArgs($params); + + // @codingStandardsIgnoreStart $this->events->attach('foo.bar', function ($e) { $e->setParam('foo', 'FOO'); }); $this->events->attach('foo.bar', function ($e) { $e->setParam('bar', 'BAR'); }); + // @codingStandardsIgnoreEnd + $responses = $this->events->trigger('foo.bar', $this, $args); $this->assertEquals('FOO', $args['foo']); $this->assertEquals('BAR', $args['bar']); @@ -410,8 +429,11 @@ public function testParametersArePassedToEventByReference() public function testCanPassObjectForEventParameters() { $params = (object) [ 'foo' => 'bar', 'bar' => 'baz']; + // @codingStandardsIgnoreStart $this->events->attach('foo.bar', function ($e) { $e->setParam('foo', 'FOO'); }); $this->events->attach('foo.bar', function ($e) { $e->setParam('bar', 'BAR'); }); + // @codingStandardsIgnoreEnd + $responses = $this->events->trigger('foo.bar', $this, $params); $this->assertEquals('FOO', $params->foo); $this->assertEquals('BAR', $params->bar); @@ -678,7 +700,8 @@ public function testTriggerUntilDeprecated() $deprecated = true; }, E_USER_DEPRECATED); - $this->events->triggerUntil('foo.bar', $this, ['foo' => 'bar'], function () {}); + $this->events->triggerUntil('foo.bar', $this, ['foo' => 'bar'], function () { + }); restore_error_handler(); $this->assertTrue($deprecated, 'EventManager::triggerUntil not marked as E_USER_DEPRECATED'); @@ -698,8 +721,10 @@ public function testSetEventClass() public function testTriggerThrowsInvalidCallbackExceptionForInvalidCallback() { - $this->setExpectedException('Zend\EventManager\Exception\InvalidCallbackException', - 'Invalid callback provided'); + $this->setExpectedException( + 'Zend\EventManager\Exception\InvalidCallbackException', + 'Invalid callback provided' + ); $responses = $this->events->trigger( 'foo.bar', @@ -774,4 +799,52 @@ public function testResponseCollectionLastReturnsNull() $responses = $this->events->trigger('string.transform', $this, ['string' => ' foo ']); $this->assertNull($responses->last()); } + + public function testTriggerEventAcceptsEventInstanceAndTriggersListeners() + { + $event = $this->prophesize(EventInterface::class); + $event->getName()->willReturn('test'); + $event->propagationIsStopped()->willReturn(false); + + $triggered = false; + $this->events->attach('test', function ($e) use ($event, &$triggered) { + $this->assertSame($event->reveal(), $e); + $triggered = true; + }); + + $this->events->triggerEvent($event->reveal()); + $this->assertTrue($triggered, 'Listener for event was not triggered'); + } + + public function testTriggerEventUntilAcceptsEventInstanceAndTriggersListenersUntilCallbackEvaluatesTrue() + { + $event = $this->prophesize(EventInterface::class); + $event->getName()->willReturn('test'); + $event->propagationIsStopped()->willReturn(false); + + $callback = function ($result) { + return ($result === true); + }; + + $triggeredOne = false; + $this->events->attach('test', function ($e) use ($event, &$triggeredOne) { + $this->assertSame($event->reveal(), $e); + $triggeredOne = true; + }); + + $triggeredTwo = false; + $this->events->attach('test', function ($e) use ($event, &$triggeredTwo) { + $this->assertSame($event->reveal(), $e); + $triggeredTwo = true; + return true; + }); + + $this->events->attach('test', function ($e) { + $this->fail('Third listener was triggered and should not have been'); + }); + + $this->events->triggerEventUntil($callback, $event->reveal()); + $this->assertTrue($triggeredOne, 'First Listener for event was not triggered'); + $this->assertTrue($triggeredTwo, 'First Listener for event was not triggered'); + } }