Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' of git://github.com/zendframework/zf2 into cach…
Browse files Browse the repository at this point in the history
…e_internals

Conflicts:
	library/Zend/Cache/Storage/Adapter/Filesystem.php
  • Loading branch information
marc-mabe committed Mar 16, 2012
2 parents 768365d + 5859e98 commit f8dd43d
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 20 deletions.
77 changes: 62 additions & 15 deletions src/EventManager.php
Expand Up @@ -254,28 +254,47 @@ public function triggerUntil($event, $target, $argv = null, $callback = null)
* executed. By default, this value is 1; however, you may set it for any
* integer value. Higher values have higher priority (i.e., execute first).
*
* @param string|ListenerAggregate $event
* You can specify "*" for the event name. In such cases, the listener will
* be triggered for every event.
*
* @param string|array|ListenerAggregate $event An event or array of event names. If a ListenerAggregate, proxies to {@link attachAggregate()}.
* @param callback|int $callback If string $event provided, expects PHP callback; for a ListenerAggregate $event, this will be the priority
* @param int $priority If provided, the priority at which to register the callback
* @return CallbackHandler|mixed CallbackHandler if attaching callback (to allow later unsubscribe); mixed if attaching aggregate
*/
public function attach($event, $callback = null, $priority = 1)
{
// Proxy ListenerAggregate arguments to attachAggregate()
if ($event instanceof ListenerAggregate) {
return $this->attachAggregate($event, $callback);
}

// Null callback is invalid
if (null === $callback) {
throw new Exception\InvalidArgumentException(sprintf(
'%s: expects a callback; none provided',
__METHOD__
));
}

// Array of events should be registered individually, and return an array of all listeners
if (is_array($event)) {
$listeners = array();
foreach ($event as $name) {
$listeners[] = $this->attach($name, $callback, $priority);
}
return $listeners;
}

// If we don't have a priority queue for the event yet, create one
if (empty($this->events[$event])) {
$this->events[$event] = new PriorityQueue();
}

// Create a callback handler, setting the event and priority in its metadata
$listener = new CallbackHandler($callback, array('event' => $event, 'priority' => $priority));

// Inject the callback handler into the queue
$this->events[$event]->insert($listener, $priority);
return $listener;
}
Expand Down Expand Up @@ -413,24 +432,24 @@ protected function triggerListeners($event, EventDescription $e, $callback = nul
$responses = new ResponseCollection;
$listeners = $this->getListeners($event);

// add static listeners to the list of listeners
// Add static/wildcard listeners to the list of listeners,
// but don't modify the listeners object
$staticListeners = $this->getStaticListeners($event);
if (count($staticListeners)) {
$staticListeners = $this->getStaticListeners($event);
$staticWildcardListeners = $this->getStaticListeners('*');
$wildcardListeners = $this->getListeners('*');
if (count($staticListeners) || count($staticWildcardListeners) || count($wildcardListeners)) {
$listeners = clone $listeners;
foreach ($staticListeners as $listener) {
$priority = $listener->getMetadatum('priority');
if (null === $priority) {
$priority = 1;
} elseif (is_array($priority)) {
// If we have an array, likely using PriorityQueue. Grab first
// element of the array, as that's the actual priority.
$priority = array_shift($priority);
}
$listeners->insert($listener, $priority);
}
}

// Static listeners on this specific event
$this->insertListeners($listeners, $staticListeners);

// Static wildcard listeners
$this->insertListeners($listeners, $staticWildcardListeners);

// Add wildcard listeners
$this->insertListeners($listeners, $wildcardListeners);

if ($listeners->isEmpty()) {
return $responses;
}
Expand Down Expand Up @@ -492,4 +511,32 @@ protected function getStaticListeners($event)

return $staticListeners;
}

/**
* Add listeners to the master queue of listeners
*
* Used to inject static listeners and wildcard listeners.
*
* @param PriorityQueue $masterListeners
* @param PriorityQueue $listeners
* @return void
*/
protected function insertListeners($masterListeners, $listeners)
{
if (!count($listeners)) {
return;
}

foreach ($listeners as $listener) {
$priority = $listener->getMetadatum('priority');
if (null === $priority) {
$priority = 1;
} elseif (is_array($priority)) {
// If we have an array, likely using PriorityQueue. Grab first
// element of the array, as that's the actual priority.
$priority = array_shift($priority);
}
$masterListeners->insert($listener, $priority);
}
}
}
54 changes: 51 additions & 3 deletions test/EventManagerTest.php
Expand Up @@ -21,7 +21,9 @@

namespace ZendTest\EventManager;

use Zend\EventManager\Event,
use ArrayIterator,
stdClass,
Zend\EventManager\Event,
Zend\EventManager\EventDescription,
Zend\EventManager\EventManager,
Zend\EventManager\ResponseCollection,
Expand Down Expand Up @@ -69,6 +71,37 @@ public function testAttachShouldAddEventIfItDoesNotExist()
$this->assertContains('test', $events);
}

public function testAllowsPassingArrayOfEventNamesWhenAttaching()
{
$callback = function ($e) {
return $e->getName();
};
$this->events->attach(array('foo', 'bar'), $callback);

foreach (array('foo', 'bar') as $event) {
$listeners = $this->events->getListeners($event);
$this->assertTrue(count($listeners) > 0);
foreach ($listeners as $listener) {
$this->assertSame($callback, $listener->getCallback());
}
}
}

public function testPassingArrayOfEventNamesWhenAttachingReturnsArrayOfCallbackHandlers()
{
$callback = function ($e) {
return $e->getName();
};
$listeners = $this->events->attach(array('foo', 'bar'), $callback);

$this->assertInternalType('array', $listeners);

foreach ($listeners as $listener) {
$this->assertInstanceOf('Zend\Stdlib\CallbackHandler', $listener);
$this->assertSame($callback, $listener->getCallback());
}
}

public function testDetachShouldRemoveListenerFromEvent()
{
$listener = $this->events->attach('test', array($this, __METHOD__));
Expand Down Expand Up @@ -539,11 +572,26 @@ public function testIdentifierGetterSettersWorkWithArrays()

public function testIdentifierGetterSettersWorkWithTraversables()
{
$identifiers = new \ArrayIterator(array('foo', 'bar'));
$identifiers = new ArrayIterator(array('foo', 'bar'));
$this->assertInstanceOf('Zend\EventManager\EventManager', $this->events->setIdentifiers($identifiers));
$this->assertSame($this->events->getIdentifiers(), (array) $identifiers);
$identifiers = new \ArrayIterator(array('foo', 'bar', 'baz'));
$identifiers = new ArrayIterator(array('foo', 'bar', 'baz'));
$this->assertInstanceOf('Zend\EventManager\EventManager', $this->events->addIdentifiers($identifiers));
$this->assertSame($this->events->getIdentifiers(), (array) $identifiers);
}

public function testListenersAttachedWithWildcardAreTriggeredForAllEvents()
{
$test = new stdClass;
$test->events = array();
$callback = function($e) use ($test) {
$test->events[] = $e->getName();
};

$this->events->attach('*', $callback);
foreach (array('foo', 'bar', 'baz') as $event) {
$this->events->trigger($event);
$this->assertContains($event, $test->events);
}
}
}
71 changes: 69 additions & 2 deletions test/StaticEventManagerTest.php
Expand Up @@ -20,9 +20,11 @@
*/

namespace ZendTest\EventManager;
use Zend\EventManager\StaticEventManager,

use PHPUnit_Framework_TestCase as TestCase,
stdClass,
Zend\EventManager\EventManager,
PHPUnit_Framework_TestCase as TestCase;
Zend\EventManager\StaticEventManager;

/**
* @category Zend
Expand Down Expand Up @@ -83,6 +85,28 @@ public function testCanAttachCallbackToEvent()
$this->assertTrue($found, 'Did not find listener!');
}

public function testCanAttachCallbackToMultipleEventsAtOnce()
{
$events = StaticEventManager::getInstance();
$events->attach('bar', array('foo', 'test'), array($this, __FUNCTION__));
$this->assertContains('foo', $events->getEvents('bar'));
$this->assertContains('test', $events->getEvents('bar'));
$expected = array($this, __FUNCTION__);
foreach (array('foo', 'test') as $event) {
$found = false;
$listeners = $events->getListeners('bar', $event);
$this->assertInstanceOf('Zend\Stdlib\PriorityQueue', $listeners);
$this->assertTrue(0 < count($listeners), 'Empty listeners!');
foreach ($listeners as $listener) {
if ($expected === $listener->getCallback()) {
$found = true;
break;
}
}
$this->assertTrue($found, 'Did not find listener!');
}
}

public function testCanAttachSameEventToMultipleResourcesAtOnce()
{
$events = StaticEventManager::getInstance();
Expand All @@ -105,6 +129,49 @@ public function testCanAttachSameEventToMultipleResourcesAtOnce()
}
}

public function testCanAttachCallbackToMultipleEventsOnMultipleResourcesAtOnce()
{
$events = StaticEventManager::getInstance();
$events->attach(array('bar', 'baz'), array('foo', 'test'), array($this, __FUNCTION__));
$this->assertContains('foo', $events->getEvents('bar'));
$this->assertContains('test', $events->getEvents('bar'));
$expected = array($this, __FUNCTION__);
foreach (array('bar', 'baz') as $resource) {
foreach (array('foo', 'test') as $event) {
$found = false;
$listeners = $events->getListeners($resource, $event);
$this->assertInstanceOf('Zend\Stdlib\PriorityQueue', $listeners);
$this->assertTrue(0 < count($listeners), 'Empty listeners!');
foreach ($listeners as $listener) {
if ($expected === $listener->getCallback()) {
$found = true;
break;
}
}
$this->assertTrue($found, 'Did not find listener!');
}
}
}

public function testListenersAttachedUsingWildcardEventWillBeTriggeredByResource()
{
$test = new stdClass;
$test->events = array();
$callback = function($e) use ($test) {
$test->events[] = $e->getName();
};

$staticEvents = StaticEventManager::getInstance();
$staticEvents->attach('bar', '*', $callback);

$events = new EventManager('bar');

foreach (array('foo', 'bar', 'baz') as $event) {
$events->trigger($event);
$this->assertContains($event, $test->events);
}
}

public function testCanDetachListenerFromResource()
{
$events = StaticEventManager::getInstance();
Expand Down

0 comments on commit f8dd43d

Please sign in to comment.