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

Commit 7e39bea

Browse files
committed
feat: Provides AbstractListenerSubscriber and ListenerSubscriberTrait
Each implements ListenerSubscriberInterface::detach
1 parent 30e2255 commit 7e39bea

File tree

5 files changed

+186
-2
lines changed

5 files changed

+186
-2
lines changed

TODO-PSR-14.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@
4949
- [x] Create `ListenerSubscriberInterface`
5050
- [x] `attach(PrioritizedListenerAttachmentInterface $provider, $priority = 1)`
5151
- [x] `detach(PrioritizedListenerAttachmentInterface $provider)`
52-
- [ ] Create `AbstractListenerSubscriber` and/or `ListenerSubscriberTrait`
53-
- [ ] define a default `detach()` implementation
52+
- [x] Create `AbstractListenerSubscriber` and/or `ListenerSubscriberTrait`
53+
- [x] define a default `detach()` implementation
5454
- [ ] Create `LazyListenerSubscriber` based on `LazyListenerAggregate`
5555
- [ ] Define an alternate LazyListener:
5656
- [ ] `__construct(ContainerInterface $container, string $event = null, int $priority = 1)`
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-eventmanager for the canonical source repository
4+
* @copyright Copyright (c) 2019 Zend Technologies USA Inc. (https://www.zend.com)
5+
* @license https://github.com/zendframework/zend-eventmanager/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace Zend\EventManager\ListenerProvider;
9+
10+
abstract class AbstractListenerSubscriber implements ListenerSubscriberInterface
11+
{
12+
/**
13+
* @var callable[]
14+
*/
15+
protected $listeners = [];
16+
17+
/**
18+
* {@inheritDoc}
19+
*/
20+
public function detach(PrioritizedListenerAttachmentInterface $provider)
21+
{
22+
foreach ($this->listeners as $index => $callback) {
23+
$provider->detach($callback);
24+
unset($this->listeners[$index]);
25+
}
26+
}
27+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-eventmanager for the canonical source repository
4+
* @copyright Copyright (c) 2019 Zend Technologies USA Inc. (https://www.zend.com)
5+
* @license https://github.com/zendframework/zend-eventmanager/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace Zend\EventManager\ListenerProvider;
9+
10+
/**
11+
* Provides an implementation of ListenerSubscriberInterface::detach
12+
*/
13+
trait ListenerSubscriberTrait
14+
{
15+
/**
16+
* @var callable[]
17+
*/
18+
private $listeners = [];
19+
20+
/**
21+
* {@inheritDoc}
22+
*/
23+
public function detach(PrioritizedListenerAttachmentInterface $provider)
24+
{
25+
foreach ($this->listeners as $index => $callback) {
26+
$provider->detach($callback);
27+
unset($this->listeners[$index]);
28+
}
29+
}
30+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-eventmanager for the canonical source repository
4+
* @copyright Copyright (c) 2019 Zend Technologies USA Inc. (https://www.zend.com)
5+
* @license https://github.com/zendframework/zend-eventmanager/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace ZendTest\EventManager\ListenerProvider;
9+
10+
use Closure;
11+
use Zend\EventManager\ListenerProvider\AbstractListenerSubscriber;
12+
use Zend\EventManager\ListenerProvider\PrioritizedListenerAttachmentInterface;
13+
14+
class AbstractListenerSubscriberTest extends ListenerSubscriberTraitTest
15+
{
16+
/**
17+
* {@inheritDoc}
18+
*/
19+
public function createProvider(callable $attachmentCallback)
20+
{
21+
return new class($attachmentCallback) extends AbstractListenerSubscriber {
22+
/** @var callable */
23+
private $attachmentCallback;
24+
25+
public function __construct(callable $attachmentCallback)
26+
{
27+
$this->attachmentCallback = $attachmentCallback;
28+
}
29+
30+
public function attach(PrioritizedListenerAttachmentInterface $provider, $priority = 1)
31+
{
32+
$attachmentCallback = $this->attachmentCallback->bindTo($this, $this);
33+
$attachmentCallback($provider, $priority);
34+
}
35+
};
36+
}
37+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-eventmanager for the canonical source repository
4+
* @copyright Copyright (c) 2019 Zend Technologies USA Inc. (https://www.zend.com)
5+
* @license https://github.com/zendframework/zend-eventmanager/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace ZendTest\EventManager\ListenerProvider;
9+
10+
use PHPUnit\Framework\TestCase;
11+
use Prophecy\Argument;
12+
use Zend\EventManager\ListenerProvider\ListenerSubscriberInterface;
13+
use Zend\EventManager\ListenerProvider\ListenerSubscriberTrait;
14+
use Zend\EventManager\ListenerProvider\PrioritizedListenerAttachmentInterface;
15+
16+
class ListenerSubscriberTraitTest extends TestCase
17+
{
18+
/**
19+
* @return ListenerSubscriberInterface
20+
*/
21+
public function createProvider(callable $attachmentCallback)
22+
{
23+
return new class($attachmentCallback) implements ListenerSubscriberInterface {
24+
use ListenerSubscriberTrait;
25+
26+
/** @var callable */
27+
private $attachmentCallback;
28+
29+
public function __construct(callable $attachmentCallback)
30+
{
31+
$this->attachmentCallback = $attachmentCallback;
32+
}
33+
34+
public function attach(PrioritizedListenerAttachmentInterface $provider, $priority = 1)
35+
{
36+
$attachmentCallback = $this->attachmentCallback->bindTo($this, $this);
37+
$attachmentCallback($provider, $priority);
38+
}
39+
};
40+
}
41+
42+
public function testSubscriberAttachesListeners()
43+
{
44+
$baseListener = function () {
45+
};
46+
$listener1 = clone $baseListener;
47+
$listener2 = clone $baseListener;
48+
$listener3 = clone $baseListener;
49+
50+
$provider = $this->prophesize(PrioritizedListenerAttachmentInterface::class);
51+
$provider->attach('foo.bar', $listener1, 100)->will(function ($args) {
52+
return $args[1];
53+
});
54+
$provider->attach('foo.baz', $listener2, 100)->will(function ($args) {
55+
return $args[1];
56+
});
57+
58+
$subscriber = $this->createProvider(function ($provider, $priority) use ($listener1, $listener2) {
59+
$this->listeners[] = $provider->attach('foo.bar', $listener1, $priority);
60+
$this->listeners[] = $provider->attach('foo.baz', $listener2, $priority);
61+
});
62+
63+
$subscriber->attach($provider->reveal(), 100);
64+
65+
$this->assertAttributeSame([$listener1, $listener2], 'listeners', $subscriber);
66+
67+
return [
68+
'subscriber' => $subscriber,
69+
'provider' => $provider,
70+
'listener1' => $listener1,
71+
'listener2' => $listener2,
72+
];
73+
}
74+
75+
/**
76+
* @depends testSubscriberAttachesListeners
77+
* @param array $dependencies
78+
*/
79+
public function testDetachRemovesAttachedListeners(array $dependencies)
80+
{
81+
$subscriber = $dependencies['subscriber'];
82+
$provider = $dependencies['provider'];
83+
84+
$provider->detach($dependencies['listener1'])->shouldBeCalledTimes(1);
85+
$provider->detach($dependencies['listener2'])->shouldBeCalledTimes(1);
86+
87+
$subscriber->detach($provider->reveal());
88+
$this->assertAttributeSame([], 'listeners', $subscriber);
89+
}
90+
}

0 commit comments

Comments
 (0)