Passed
Push — main ( 4ddaea...7c5fe7 )
by Thierry
04:58
created

CallbackManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * Callbacks.php
5
 *
6
 * Jaxon request callback manager
7
 *
8
 * @package jaxon-core
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2017 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
14
15
namespace Jaxon\Request\Handler;
16
17
use Jaxon\Exception\RequestException;
18
use Jaxon\Request\Target;
19
use Exception;
20
21
use function array_merge;
22
use function array_values;
23
use function count;
24
use function call_user_func_array;
25
use function is_a;
26
27
class CallbackManager
28
{
29
    /**
30
     * The callbacks to run after booting the library
31
     *
32
     * @var callable[]
33
     */
34
    protected $aBootCallbacks = [];
35
36
    /**
37
     * The callbacks to run before processing the request
38
     *
39
     * @var callable[]
40
     */
41
    protected $aBeforeCallbacks = [];
42
43
    /**
44
     * The callbacks to run after processing the request
45
     *
46
     * @var callable[]
47
     */
48
    protected $aAfterCallbacks = [];
49
50
    /**
51
     * The callbacks to run in case of invalid request
52
     *
53
     * @var callable[]
54
     */
55
    protected $aInvalidCallbacks = [];
56
57
    /**
58
     * The callbacks to run in case of error
59
     *
60
     * @var callable[]
61
     */
62
    protected $aErrorCallbacks = [];
63
64
    /**
65
     * The callbacks to run in case of exception
66
     *
67
     * @var callable[][]
68
     */
69
    protected $aExceptionCallbacks = [];
70
71
    /**
72
     * The callbacks to run when a class is instanced
73
     *
74
     * @var callable[]
75
     */
76
    protected $aInitCallbacks = [];
77
78
    /**
79
     * Get the library booting callbacks, and reset the array.
80
     *
81
     * @return callable[]
82
     */
83
    public function popBootCallbacks(): array
84
    {
85
        if(empty($this->aBootCallbacks))
86
        {
87
            return [];
88
        }
89
        $aCallbacks = $this->aBootCallbacks;
90
        $this->aBootCallbacks = [];
91
        return $aCallbacks;
92
    }
93
94
    /**
95
     * Get the exception callbacks.
96
     *
97
     * @param Exception $xException      The exception class
98
     *
99
     * @return callable[]
100
     */
101
    private function getExceptionCallbacks(Exception $xException): array
102
    {
103
        $aExceptionCallbacks = [];
104
        foreach($this->aExceptionCallbacks as $sExClass => $aCallbacks)
105
        {
106
            if(is_a($xException, $sExClass))
107
            {
108
                $aExceptionCallbacks = array_merge($aExceptionCallbacks, $aCallbacks);
109
            }
110
        }
111
        return array_values($aExceptionCallbacks);
112
    }
113
114
    /**
115
     * Add a library booting callback.
116
     *
117
     * @param callable $xCallable    The callback function
118
     *
119
     * @return CallbackManager
120
     */
121
    public function boot(callable $xCallable): CallbackManager
122
    {
123
        $this->aBootCallbacks[] = $xCallable;
124
        return $this;
125
    }
126
127
    /**
128
     * Add a pre-request processing callback.
129
     *
130
     * @param callable $xCallable    The callback function
131
     *
132
     * @return CallbackManager
133
     */
134
    public function before(callable $xCallable): CallbackManager
135
    {
136
        $this->aBeforeCallbacks[] = $xCallable;
137
        return $this;
138
    }
139
140
    /**
141
     * Add a post-request processing callback.
142
     *
143
     * @param callable $xCallable    The callback function
144
     *
145
     * @return CallbackManager
146
     */
147
    public function after(callable $xCallable): CallbackManager
148
    {
149
        $this->aAfterCallbacks[] = $xCallable;
150
        return $this;
151
    }
152
153
    /**
154
     * Add a invalid request callback.
155
     *
156
     * @param callable $xCallable    The callback function
157
     *
158
     * @return CallbackManager
159
     */
160
    public function invalid(callable $xCallable): CallbackManager
161
    {
162
        $this->aInvalidCallbacks[] = $xCallable;
163
        return $this;
164
    }
165
166
    /**
167
     * Add a processing error callback.
168
     *
169
     * @param callable $xCallable   The callback function
170
     * @param string $sExClass      The exception class
171
     *
172
     * @return CallbackManager
173
     */
174
    public function error(callable $xCallable, string $sExClass = ''): CallbackManager
175
    {
176
        if($sExClass === '' || $sExClass === Exception::class)
177
        {
178
            $this->aErrorCallbacks[] = $xCallable;
179
            return $this;
180
        }
181
        // Callback for a given exception class
182
        if(isset($this->aExceptionCallbacks[$sExClass]))
183
        {
184
            $this->aExceptionCallbacks[$sExClass][] = $xCallable;
185
            return $this;
186
        }
187
        $this->aExceptionCallbacks[$sExClass] = [$xCallable];
188
        return $this;
189
    }
190
191
    /**
192
     * Add a class initialisation callback.
193
     *
194
     * @param callable $xCallable    The callback function
195
     *
196
     * @return CallbackManager
197
     */
198
    public function init(callable $xCallable): CallbackManager
199
    {
200
        $this->aInitCallbacks[] = $xCallable;
201
        return $this;
202
    }
203
204
    /**
205
     * @param callable $xCallback
206
     * @param array $aParameters
207
     *
208
     * @return void
209
     */
210
    private function executeCallback(callable $xCallback, array $aParameters): void
211
    {
212
        call_user_func_array($xCallback, $aParameters);
213
    }
214
215
    /**
216
     * @param array $aCallbacks
217
     * @param array $aParameters
218
     *
219
     * @return void
220
     */
221
    private function executeCallbacks(array $aCallbacks, array $aParameters): void
222
    {
223
        foreach($aCallbacks as $xCallback)
224
        {
225
            $this->executeCallback($xCallback, $aParameters);
226
        }
227
    }
228
229
    /**
230
     * Execute the class initialisation callbacks.
231
     *
232
     * @param mixed $xComponent
233
     *
234
     * @return void
235
     */
236
    public function onInit($xComponent): void
237
    {
238
        $this->executeCallbacks($this->aInitCallbacks, [$xComponent]);
239
    }
240
241
    /**
242
     * These are the pre-request processing callbacks passed to the Jaxon library.
243
     *
244
     * @param Target $xTarget
245
     * @param bool $bEndRequest If set to true, the request processing is interrupted.
246
     *
247
     * @return void
248
     * @throws RequestException
249
     */
250
    public function onBefore(Target $xTarget, bool &$bEndRequest): void
251
    {
252
        // Call the user defined callback
253
        foreach($this->aBeforeCallbacks as $xCallback)
254
        {
255
            $this->executeCallback($xCallback, [$xTarget, &$bEndRequest]);
256
            if($bEndRequest)
257
            {
258
                return;
259
            }
260
        }
261
    }
262
263
    /**
264
     * These are the post-request processing callbacks passed to the Jaxon library.
265
     *
266
     * @param Target $xTarget
267
     * @param bool $bEndRequest
268
     *
269
     * @return void
270
     * @throws RequestException
271
     */
272
    public function onAfter(Target $xTarget, bool $bEndRequest): void
273
    {
274
        $this->executeCallbacks($this->aAfterCallbacks, [$xTarget, $bEndRequest]);
275
    }
276
277
    /**
278
     * These callbacks are called whenever an invalid request is processed.
279
     *
280
     * @param RequestException $xException
281
     *
282
     * @return void
283
     * @throws RequestException
284
     */
285
    public function onInvalid(RequestException $xException): void
286
    {
287
        $this->executeCallbacks($this->aInvalidCallbacks, [$xException]);
288
        throw $xException;
289
    }
290
291
    /**
292
     * These callbacks are called whenever an invalid request is processed.
293
     *
294
     * @param Exception $xException
295
     *
296
     * @return void
297
     * @throws Exception
298
     */
299
    public function onError(Exception $xException): void
300
    {
301
        $aExceptionCallbacks = $this->getExceptionCallbacks($xException);
302
        $this->executeCallbacks($aExceptionCallbacks, [$xException]);
303
        if(count($aExceptionCallbacks) > 0)
304
        {
305
            // Do not throw the exception if a custom handler is defined
306
            return;
307
        }
308
309
        $this->executeCallbacks($this->aErrorCallbacks, [$xException]);
310
        throw $xException;
311
    }
312
}
313