Dispatcher   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 143
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 29
eloc 48
dl 0
loc 143
rs 10
c 1
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A removeListener() 0 15 4
A getListeners() 0 13 4
A removeSubscriber() 0 4 2
A hasListener() 0 15 4
A addSubscriber() 0 4 2
A removeAllListener() 0 7 4
A dispatch() 0 21 6
A addListener() 0 14 3
1
<?php
2
3
/**
4
 * Platine Event Dispatcher
5
 *
6
 * Platine Event Dispatcher is the minimal implementation of PSR 14
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine Event Dispatcher
11
 *
12
 * Permission is hereby granted, free of charge, to any person obtaining a copy
13
 * of this software and associated documentation files (the "Software"), to deal
14
 * in the Software without restriction, including without limitation the rights
15
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
 * copies of the Software, and to permit persons to whom the Software is
17
 * furnished to do so, subject to the following conditions:
18
 *
19
 * The above copyright notice and this permission notice shall be included in all
20
 * copies or substantial portions of the Software.
21
 *
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
 * SOFTWARE.
29
 */
30
31
/**
32
 *  @file Dispatcher.php
33
 *
34
 *  The Event Dispatcher class used to manage the event dispatcher, listener, subscriber
35
 *
36
 *  @package    Platine\Event
37
 *  @author Platine Developers Team
38
 *  @copyright  Copyright (c) 2020
39
 *  @license    http://opensource.org/licenses/MIT  MIT License
40
 *  @link   https://www.platine-php.com
41
 *  @version 1.0.0
42
 *  @filesource
43
 */
44
45
declare(strict_types=1);
46
47
namespace Platine\Event;
48
49
use Platine\Event\Listener\CallableListener;
50
use Platine\Event\Listener\ListenerInterface;
51
use Platine\Event\Listener\ListenerPriorityQueue;
52
53
/**
54
 * @class Dispatcher
55
 * @package Platine\Event
56
 */
57
class Dispatcher implements DispatcherInterface
58
{
59
    /**
60
     * The list of listener
61
     * @var array<string, ListenerPriorityQueue>
62
     */
63
    protected array $listeners = [];
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function dispatch(
69
        string|EventInterface $eventName,
70
        ?EventInterface $event = null
71
    ): EventInterface {
72
        if ($eventName instanceof EventInterface) {
73
            $event = $eventName;
74
        } elseif (is_null($event)) {
75
            $event = new Event($eventName);
76
        }
77
78
        if (isset($this->listeners[$event->getName()])) {
79
            foreach ($this->listeners[$event->getName()] as $listener) {
80
                if ($event->isStopPropagation()) {
81
                    break;
82
                }
83
84
                ([$listener, 'handle'])($event);
85
            }
86
        }
87
88
        return $event;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94
    public function addListener(
95
        string $eventName,
96
        ListenerInterface|callable $listener,
97
        int $priority = self::PRIORITY_DEFAULT
98
    ): void {
99
        if (!isset($this->listeners[$eventName])) {
100
            $this->listeners[$eventName] = new ListenerPriorityQueue();
101
        }
102
103
        if (is_callable($listener)) {
104
            $listener = CallableListener::fromCallable($listener);
0 ignored issues
show
Bug introduced by
It seems like $listener can also be of type Platine\Event\Listener\ListenerInterface; however, parameter $callable of Platine\Event\Listener\C...istener::fromCallable() does only seem to accept callable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
            $listener = CallableListener::fromCallable(/** @scrutinizer ignore-type */ $listener);
Loading history...
105
        }
106
107
        $this->listeners[$eventName]->insert($listener, $priority);
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function addSubscriber(SubscriberInterface $subscriber): void
114
    {
115
        foreach ($subscriber->getSubscribedEvents() as $eventName => $action) {
116
            $this->addListener($eventName, [$subscriber, $action]);
117
        }
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function removeListener(string $eventName, ListenerInterface|callable $listener): void
124
    {
125
        if (empty($this->listeners[$eventName])) {
126
            return;
127
        }
128
129
        if (is_callable($listener)) {
130
            $listener = CallableListener::getListener($listener);
0 ignored issues
show
Bug introduced by
It seems like $listener can also be of type Platine\Event\Listener\ListenerInterface; however, parameter $callable of Platine\Event\Listener\C...Listener::getListener() does only seem to accept callable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

130
            $listener = CallableListener::getListener(/** @scrutinizer ignore-type */ $listener);
Loading history...
131
        }
132
133
        if ($listener === false) {
134
            return;
135
        }
136
137
        $this->listeners[$eventName]->detach($listener);
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function removeSubscriber(SubscriberInterface $subscriber): void
144
    {
145
        foreach ($subscriber->getSubscribedEvents() as $eventName => $action) {
146
            $this->removeListener($eventName, [$subscriber, $action]);
147
        }
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function removeAllListener(?string $eventName = null): void
154
    {
155
        if (!is_null($eventName) && isset($this->listeners[$eventName])) {
156
            $this->listeners[$eventName]->clear();
157
        } else {
158
            foreach ($this->listeners as $queue) {
159
                $queue->clear();
160
            }
161
        }
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function hasListener(string $eventName, ListenerInterface|callable $listener): bool
168
    {
169
        if (!isset($this->listeners[$eventName])) {
170
            return false;
171
        }
172
173
        if (is_callable($listener)) {
174
            $listener = CallableListener::getListener($listener);
0 ignored issues
show
Bug introduced by
It seems like $listener can also be of type Platine\Event\Listener\ListenerInterface; however, parameter $callable of Platine\Event\Listener\C...Listener::getListener() does only seem to accept callable, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

174
            $listener = CallableListener::getListener(/** @scrutinizer ignore-type */ $listener);
Loading history...
175
        }
176
177
        if ($listener === false) {
178
            return false;
179
        }
180
181
        return $this->listeners[$eventName]->contains($listener);
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187
    public function getListeners(?string $eventName = null): array
188
    {
189
        if (!is_null($eventName)) {
190
            return isset($this->listeners[$eventName])
191
                    ? $this->listeners[$eventName]->all()
192
                    : [];
193
        } else {
194
            $listeners = [];
195
            foreach ($this->listeners as $queue) {
196
                $listeners = array_merge($listeners, $queue->all());
197
            }
198
199
            return $listeners;
200
        }
201
    }
202
}
203