Completed
Push — 5.0 ( d49403...9430f0 )
by Marc André
01:47
created

Events::loadPath()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.2
c 0
b 0
f 0
cc 4
eloc 8
nc 4
nop 1
1
<?php
2
3
4
/**
5
 *
6
 * Copyright (c) 2010-2018 Nevraxe inc. & Marc André Audet <[email protected]>. All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without modification, are
9
 * permitted provided that the following conditions are met:
10
 *
11
 *   1. Redistributions of source code must retain the above copyright notice, this list of
12
 *       conditions and the following disclaimer.
13
 *
14
 *   2. Redistributions in binary form must reproduce the above copyright notice, this list
15
 *       of conditions and the following disclaimer in the documentation and/or other materials
16
 *       provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL NEVRAXE INC. & MARC ANDRÉ AUDET BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 */
30
31
32
namespace Cervo;
33
34
35
use Cervo\Interfaces\SingletonInterface;
36
37
38
/**
39
 * Events manager for Cervo.
40
 *
41
 * @author Marc André Audet <[email protected]>
42
 */
43
class Events implements SingletonInterface
44
{
45
    /** @var array Holds all the events and their callbacks */
46
    private $events = [];
47
48
    /** @var string|null Name of the event in progress, null if there are no active events */
49
    private $inProgress = null;
50
51
    /** @var Context The current context */
52
    private $context;
53
54
    /**
55
     * Events constructor.
56
     *
57
     * @param Context $context
58
     */
59
    public function __construct(Context $context)
60
    {
61
        $this->context = $context;
62
    }
63
64
    /**
65
     * Load every PHP Events files under the directory
66
     *
67
     * @param string $path Path to the module
68
     */
69
    public function loadPath(string $path) : void
70
    {
71
        if (file_exists($path . \DIRECTORY_SEPARATOR . 'Events')) {
72
73
            foreach (
74
                PathUtils::getRecursivePHPFilesIterator($path . \DIRECTORY_SEPARATOR . 'Events')
75
                as $file
76
            ) {
77
78
                $callback = require $file->getPathName();
79
80
                if (is_callable($callback)) {
81
                    $callback($this);
82
                }
83
84
            }
85
86
        }
87
    }
88
89
    /**
90
     * Register a new event.
91
     *
92
     * @param string $name The name of the event
93
     *
94
     * @return bool
95
     */
96
    public function register(string $name) : bool
97
    {
98
        if ($this->isRegistered($name)) {
99
            return false;
100
        }
101
102
        $this->events[$name] = [];
103
104
        return true;
105
    }
106
107
    /**
108
     * Check if the event exists by it's name.
109
     *
110
     * @param string $name The name of the event
111
     *
112
     * @return bool
113
     */
114
    public function isRegistered(string $name) : bool
115
    {
116
        return isset($this->events[$name]);
117
    }
118
119
    /**
120
     * Remove an event and un-hook everything related to it.
121
     *
122
     * @param string $name The name of the event
123
     */
124
    public function unregister(string $name) : void
125
    {
126
        unset($this->events[$name]);
127
    }
128
129
    /**
130
     * Hook a callable to an event.
131
     * If the event is not registered, register it.
132
     *
133
     * @param string $name The name of the event to hook on
134
     * @param callable $callback The callback to call once the event is fired
135
     * @param int $priority The priority order of the callback
136
     *
137
     * @return bool
138
     */
139
    public function hook(string $name, callable $callback, int $priority = 0) : bool
140
    {
141
        if (!$this->isRegistered($name)) {
142
            $this->register($name);
143
        }
144
145
        $this->events[$name][] = [
146
            'callback' => $callback,
147
            'priority' => $priority
148
        ];
149
150
        return true;
151
    }
152
153
    /**
154
     * Fire an event and call all the hooked callables.
155
     *
156
     * @param string $name The name of the event to fire
157
     * @param array $params The parameters to pass down on the callbacks
158
     *
159
     * @return bool
160
     */
161
    public function fire(string $name, array $params = []) : bool
162
    {
163
        if (!is_array($params) || !$this->isRegistered($name)) {
164
            return false;
165
        }
166
167
        $this->inProgress = $name;
168
169
        usort($this->events[$name], function ($a, $b) {
170
            return $a['priority'] <=> $b['priority'];
171
        });
172
173
        foreach ($this->events[$name] as $call) {
174
            call_user_func($call['callback'], $name, $params);
175
        }
176
177
        $this->inProgress = null;
178
179
        return true;
180
    }
181
182
    /**
183
     * Returns the name of the event being fired, null otherwise.
184
     *
185
     * @return string|null
186
     */
187
    public function getInProgress() : ?string
188
    {
189
        return $this->inProgress;
190
    }
191
192
    /**
193
     * Returns true if an event is being fired.
194
     *
195
     * @return bool
196
     */
197
    public function isInProgress() : bool
198
    {
199
        return $this->inProgress !== null;
200
    }
201
}
202