Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
Manager
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
10 / 10
22
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
 on
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 off
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 has
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getResults
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 alive
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 trigger
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
6
 __set
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Pop PHP Framework (https://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@noladev.com>
7 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
8 * @license    https://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Event;
15
16use Pop\AbstractManager;
17use Pop\Utils\CallableObject;
18
19/**
20 * Event manager class
21 *
22 * @category   Pop
23 * @package    Pop\Event
24 * @author     Nick Sagona, III <dev@noladev.com>
25 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
26 * @license    https://www.popphp.org/license     New BSD License
27 * @version    4.4.0
28 */
29class Manager extends AbstractManager
30{
31
32    /**
33     * Constant to stop the event manager
34     * @var string
35     */
36    const STOP = 'Pop\Event\Manager::STOP';
37
38    /**
39     * Constant to send a kill signal to the application
40     * @var string
41     */
42    const KILL = 'Pop\Event\Manager::KILL';
43
44    /**
45     * Event results
46     * @var array
47     */
48    protected array $results = [];
49
50    /**
51     * Event 'alive' tracking flag
52     * @var bool
53     */
54    protected bool $alive = true;
55
56    /**
57     * Constructor
58     *
59     * Instantiate the event manager object.
60     *
61     * @param  ?string $name
62     * @param  mixed   $action
63     * @param  int     $priority
64     */
65    public function __construct(?string $name = null, mixed $action = null, int $priority = 0)
66    {
67        if (($name !== null) && ($action !== null)) {
68            $this->on($name, $action, $priority);
69        }
70    }
71
72    /**
73     * Attach an event listener
74     *
75     *     $event->on('event.name', 'someFunction');
76     *     $event->on('event.name', function() { ... });
77     *     $event->on('event.name', new SomeClass());
78     *     $event->on('event.name', [new SomeClass, 'foo']);
79     *     $event->on('event.name', 'SomeClass');
80     *     $event->on('event.name', 'SomeClass->foo');
81     *     $event->on('event.name', 'SomeClass::bar');
82     *
83     * @param  string $name
84     * @param  mixed  $action
85     * @param  int    $priority
86     * @return Manager
87     */
88    public function on(string $name, mixed $action, int $priority = 0): static
89    {
90        if (!isset($this->items[$name])) {
91            $this->items[$name] = new \SplPriorityQueue();
92        }
93        if (!($action instanceof CallableObject)) {
94            $action = new CallableObject($action);
95        }
96        $this->items[$name]->insert($action, $priority);
97
98        return $this;
99    }
100
101    /**
102     * Detach an event listener
103     *
104     * @param  string $name
105     * @param  mixed  $action
106     * @return Manager
107     */
108    public function off(string $name, mixed $action): static
109    {
110        // If the event exists, loop through and remove the action if found.
111        if (isset($this->items[$name])) {
112            $newListeners = new \SplPriorityQueue();
113
114            $listeners = clone $this->items[$name];
115            $listeners->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
116
117            foreach ($listeners as $value) {
118                $item = $listeners->current();
119                if ($action !== $item['data']) {
120                    $newListeners->insert($item['data'], $item['priority']);
121                }
122            }
123
124            $this->items[$name] = $newListeners;
125        }
126
127        return $this;
128    }
129
130    /**
131     * Return an event
132     *
133     * @param  string $name
134     * @return mixed
135     */
136    public function get(string $name): mixed
137    {
138        return $this->getItem($name);
139    }
140
141    /**
142     * Determine whether the event manager has an event registered with it
143     *
144     * @param  string $name
145     * @return bool
146     */
147    public function has(string $name): bool
148    {
149        return $this->hasItem($name);
150    }
151
152    /**
153     * Return the event results
154     *
155     * @param  string $name
156     * @return mixed
157     */
158    public function getResults(string $name): mixed
159    {
160        return $this->results[$name] ?? null;
161    }
162
163    /**
164     * Determine if the project application is still alive or has been killed
165     *
166     * @return bool
167     */
168    public function alive(): bool
169    {
170        return $this->alive;
171    }
172
173    /**
174     * Trigger an event listener
175     *
176     * @param  string $name
177     * @param  array  $params
178     * @return void
179     */
180    public function trigger(string $name, array $params = []): void
181    {
182        if (isset($this->items[$name])) {
183            if (!isset($this->results[$name])) {
184                $this->results[$name] = [];
185            }
186
187            foreach ($this->items[$name] as $action) {
188                if (end($this->results[$name]) == self::STOP) {
189                    return;
190                }
191
192                $params['result']       = end($this->results[$name]);
193                $result                 = $action->call($params);
194                $this->results[$name][] = $result;
195
196                if ($result == self::KILL) {
197                    $this->alive = false;
198                }
199            }
200        }
201    }
202
203    /**
204     * Set an event
205     *
206     * @param  string $name
207     * @param  mixed  $value
208     * @return void
209     */
210    public function __set(string $name, mixed $value): void
211    {
212        $this->on($name, $value);
213    }
214
215    /**
216     * Set an event
217     *
218     * @param  mixed $offset
219     * @param  mixed  $value
220     * @return void
221     */
222    public function offsetSet(mixed $offset, mixed $value): void
223    {
224        $this->on($offset, $value);
225    }
226
227}