Passed
Push — master ( e09ad1...6923e5 )
by Marwan
02:02
created

Event::hasListener()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
/**
4
 * @author Marwan Al-Soltany <[email protected]>
5
 * @copyright Marwan Al-Soltany 2021
6
 * For the full copyright and license information, please view
7
 * the LICENSE file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace MAKS\Velox\Backend;
13
14
/**
15
 * A class that offers simple events handling functionality (dispatching and listening).
16
 *
17
 * Example:
18
 * ```
19
 * // listening on an event
20
 * Event::listen('some.event', function ($arg1, $arg2) {
21
 *     // do some stuff ...
22
 * });
23
 *
24
 * // dispatching an event
25
 * Event::dispatch('some.event', [$arg1, $arg2]);
26
 *
27
 * // check if an event has listeners
28
 * Event::hasListener('some.event');
29
 *
30
 * // check if an event is dispatched
31
 * Event::isDispatch('some.event');
32
 *
33
 * // get a registered or a new event object
34
 * Event::get('some.event');
35
 *
36
 * // get a all registered events
37
 * Event::getRegisteredEvents();
38
 * ```
39
 *
40
 * @package Velox\Backend
41
 * @since 1.2.0
42
 * @api
43
 */
44
class Event
45
{
46
    /**
47
     * Here live all bindings.
48
     */
49
    protected static array $events = [];
50
51
52
    /**
53
     * Dispatches the passed event by executing all attached listeners and passes them the passed arguments.
54
     *
55
     * @param string $event Event name.
56
     * @param array $arguments [optional] Arguments array.
57
     *      Note that the arguments will be spread (`...$args`) on the callback and an additional argument of the event name will be appended to the arguments.
58
     * @param object|null $callbackThis [optional] The object the callback should be bound to.
59
     *
60
     * @return void
61
     */
62 30
    public static function dispatch(string $event, ?array $arguments = null, ?object $callbackThis = null): void
63
    {
64 30
        if (static::hasListener($event) === false) {
65 21
            static::get($event)->dispatched = true;
66
67 21
            return;
68
        }
69
70 26
        $callbacks = &static::get($event)->listeners;
71 26
        foreach ($callbacks as $callback) {
72 26
            $parameters = array_merge(array_values($arguments ?? []), [$event]);
73
74 26
            if ($callbackThis) {
75 10
                $callback->call($callbackThis, ...$parameters);
76 10
                continue;
77
            }
78
79 19
            $callback(...$parameters);
80
        }
81
82 26
        if (static::isDispatched($event) === false) {
83 3
            static::get($event)->dispatched = true;
84
        }
85 26
    }
86
87
    /**
88
     * Listens on the passed event and attaches the passed callback to it.
89
     *
90
     * @param string $event Event name.
91
     * @param callable $callback A callback to process the event.
92
     *
93
     * @return void
94
     */
95 1
    public static function listen(string $event, callable $callback): void
96
    {
97 1
        static::get($event)->listeners[] = \Closure::fromCallable($callback);
98 1
    }
99
100
    /**
101
     * Checks whether an event has already been dispatched or not.
102
     *
103
     * @param string $event Event name.
104
     *
105
     * @return bool
106
     *
107
     * @since 1.5.0
108
     */
109 26
    public static function isDispatched(string $event): bool
110
    {
111 26
        return static::get($event)->dispatched === true;
112
    }
113
114
    /**
115
     * Checks whether an event has any listeners or not.
116
     *
117
     * @param string $event Event name.
118
     *
119
     * @return bool
120
     *
121
     * @since 1.5.0
122
     */
123 30
    public static function hasListener(string $event): bool
124
    {
125 30
        return empty(static::get($event)->listeners) === false;
126
    }
127
128
    /**
129
     * Returns an event object by its name or creates it if it does not exist.
130
     * The event object consists of the following properties:
131
     * - `name`: The event name.
132
     * - `dispatched`: A boolean flag indicating whether the event has been dispatched or not.
133
     * - `listeners`: An array of callbacks.
134
     *
135
     * @param string $event Event name.
136
     *
137
     * @return object
138
     *
139
     * @since 1.5.0
140
     */
141 30
    public static function get(string $event): object
142
    {
143 30
        return static::$events[$event] ?? static::create($event);
144
    }
145
146
    /**
147
     * Returns array of all registered events as an array `['event.name' => $eventObject, ...]`.
148
     *
149
     * @return object[]
150
     */
151 1
    public static function getRegisteredEvents(): array
152
    {
153 1
        return static::$events;
154
    }
155
156
    /**
157
     * Creates an event object and adds it to the registered events.
158
     *
159
     * @param string $event Event name.
160
     *
161
     * @return object
162
     *
163
     * @since 1.5.0
164
     */
165 11
    protected static function create(string $event): object
166
    {
167 11
        return static::$events[$event] = (object)[
168 11
            'name'       => $event,
169
            'dispatched' => false,
170
            'listeners'  => [],
171
        ];
172
    }
173
}
174