Passed
Push — master ( eb1365...37d9b5 )
by Thierry
01:52
created

RequestHandler::onBefore()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 4
nop 1
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * RequestHandler.php - Jaxon RequestPlugin Handler
5
 *
6
 * This class processes an incoming jaxon request.
7
 *
8
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
9
 * @author Jared White
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
10
 * @author J. Max Wilson
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
11
 * @author Joseph Woolley
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
12
 * @author Steffen Konerow
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
13
 * @author Thierry Feuzeu <[email protected]>
14
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
15
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
16
 * @copyright 2016 Thierry Feuzeu <[email protected]>
17
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
18
 * @link https://github.com/jaxon-php/jaxon-core
19
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
20
21
namespace Jaxon\Request\Handler;
22
23
use Jaxon\Container\Container;
24
use Jaxon\Config\ConfigManager;
25
use Jaxon\Plugin\PluginManager;
26
use Jaxon\Plugin\RequestPlugin;
27
use Jaxon\Response\AbstractResponse;
28
use Jaxon\Response\ResponseManager;
29
use Jaxon\Response\Plugin\DataBag\DataBagPlugin;
30
use Jaxon\Exception\RequestException;
31
use Jaxon\Exception\SetupException;
32
use Jaxon\Utils\Translation\Translator;
33
34
use Exception;
35
36
use function call_user_func;
37
use function call_user_func_array;
38
use function error_reporting;
39
use function headers_sent;
40
use function ob_end_clean;
41
use function ob_get_level;
42
43
class RequestHandler
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class RequestHandler
Loading history...
44
{
45
    /**
46
     * @var Container
47
     */
48
    private $di;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
49
50
    /**
51
     * @var ConfigManager
52
     */
53
    protected $xConfigManager;
54
55
    /**
56
     * The plugin manager.
57
     *
58
     * @var PluginManager
59
     */
60
    private $xPluginManager;
61
62
    /**
63
     * The response manager.
64
     *
65
     * @var ResponseManager
66
     */
67
    private $xResponseManager;
68
69
    /**
70
     * The argument manager.
71
     *
72
     * @var ArgumentManager
73
     */
74
    private $xArgumentManager;
75
76
    /**
77
     * The callbacks to run while processing the request
78
     *
79
     * @var CallbackManager
80
     */
81
    private $xCallbackManager;
82
83
    /**
84
     * @var UploadHandler
85
     */
86
    private $xUploadHandler;
87
88
    /**
89
     * The data bag response plugin
90
     *
91
     * @var DataBagPlugin
92
     */
93
    private $xDataBagPlugin;
94
95
    /**
96
     * @var Translator
97
     */
98
    private $xTranslator;
99
100
    /**
101
     * The request plugin that is able to process the current request
102
     *
103
     * @var RequestPlugin
104
     */
105
    private $xTargetRequestPlugin = null;
106
107
    /**
108
     * The constructor
109
     *
110
     * @param Container $di
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
111
     * @param ConfigManager $xConfigManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
112
     * @param ArgumentManager $xArgument
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
113
     * @param PluginManager $xPluginManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
114
     * @param ResponseManager $xResponseManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
115
     * @param CallbackManager $xCallbackManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
116
     * @param UploadHandler|null $xUploadHandler
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
117
     * @param DataBagPlugin $xDataBagPlugin
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
118
     * @param Translator $xTranslator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 9 spaces after parameter type; 1 found
Loading history...
119
     */
120
    public function __construct(Container $di, ConfigManager $xConfigManager, ArgumentManager $xArgument,
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
121
        PluginManager $xPluginManager, ResponseManager $xResponseManager, CallbackManager $xCallbackManager,
122
        ?UploadHandler $xUploadHandler, DataBagPlugin $xDataBagPlugin, Translator $xTranslator)
123
    {
124
        $this->di = $di;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 15 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
125
        $this->xConfigManager = $xConfigManager;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
126
        $this->xPluginManager = $xPluginManager;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
127
        $this->xResponseManager = $xResponseManager;
128
        $this->xArgumentManager = $xArgument;
129
        $this->xCallbackManager = $xCallbackManager;
130
        $this->xUploadHandler = $xUploadHandler;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
131
        $this->xDataBagPlugin = $xDataBagPlugin;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
132
        $this->xTranslator = $xTranslator;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
133
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
134
135
    /**
136
     * Return the method that was used to send the arguments from the client
137
     *
138
     * The method is one of: ArgumentManager::METHOD_UNKNOWN, ArgumentManager::METHOD_GET, ArgumentManager::METHOD_POST.
139
     *
140
     * @return int
141
     */
142
    public function getRequestMethod(): int
143
    {
144
        return $this->xArgumentManager->getRequestMethod();
145
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
146
147
    /**
148
     * Return the array of arguments that were extracted and parsed from the GET or POST data
149
     *
150
     * @return array
151
     * @throws RequestException
152
     */
153
    public function processArguments(): array
154
    {
155
        return $this->xArgumentManager->process();
156
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
157
158
    /**
159
     * Get the callback handler
160
     *
161
     * @return CallbackManager
162
     */
163
    public function getCallbackManager(): CallbackManager
164
    {
165
        return $this->xCallbackManager;
166
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
167
168
    /**
169
     * These callbacks are called whenever an invalid request is processed.
170
     *
171
     * @return void
172
     */
173
    public function onBoot()
174
    {
175
        foreach($this->xCallbackManager->getBootCallbacks() as $xCallback)
176
        {
177
            call_user_func($xCallback);
178
        }
179
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
180
181
    /**
182
     * These are the pre-request processing callbacks passed to the Jaxon library.
183
     *
184
     * @param bool $bEndRequest    If set to true, the request processing is interrupted.
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
185
     *
186
     * @return void
187
     */
188
    public function onBefore(bool &$bEndRequest)
189
    {
190
        $xTarget = $this->xTargetRequestPlugin->getTarget();
191
        // Call the user defined callback
192
        foreach($this->xCallbackManager->getBeforeCallbacks() as $xCallback)
193
        {
194
            $xReturn = call_user_func_array($xCallback, [$xTarget, &$bEndRequest]);
195
            if($bEndRequest)
196
            {
197
                return;
198
            }
199
            if($xReturn instanceof AbstractResponse)
200
            {
201
                $this->xResponseManager->append($xReturn);
202
            }
203
        }
204
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
205
206
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $bEndRequest should have a doc-comment as per coding-style.
Loading history...
207
     * These are the post-request processing callbacks passed to the Jaxon library.
208
     *
209
     * @return void
210
     */
211
    public function onAfter(bool $bEndRequest)
212
    {
213
        foreach($this->xCallbackManager->getAfterCallbacks() as $xCallback)
214
        {
215
            $xReturn = call_user_func_array($xCallback,
216
                [$this->xTargetRequestPlugin->getTarget(), $bEndRequest]);
217
            if($xReturn instanceof AbstractResponse)
218
            {
219
                $this->xResponseManager->append($xReturn);
220
            }
221
        }
222
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
223
224
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $sMessage should have a doc-comment as per coding-style.
Loading history...
225
     * These callbacks are called whenever an invalid request is processed.
226
     *
227
     * @return void
228
     */
229
    public function onInvalid(string $sMessage)
230
    {
231
        foreach($this->xCallbackManager->getInvalidCallbacks() as $xCallback)
232
        {
233
            $xReturn = call_user_func($xCallback, $sMessage);
234
            if($xReturn instanceof AbstractResponse)
235
            {
236
                $this->xResponseManager->append($xReturn);
237
            }
238
        }
239
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
240
241
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $xException should have a doc-comment as per coding-style.
Loading history...
242
     * These callbacks are called whenever an invalid request is processed.
243
     *
244
     * @var Exception $xException
245
     *
246
     * @return void
247
     */
248
    public function onError(Exception $xException)
249
    {
250
        foreach($this->xCallbackManager->getErrorCallbacks() as $xCallback)
251
        {
252
            $xReturn = call_user_func($xCallback, $xException);
253
            if($xReturn instanceof AbstractResponse)
254
            {
255
                $this->xResponseManager->append($xReturn);
256
            }
257
        }
258
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
259
260
    /**
261
     * Check if the current request can be processed
262
     *
263
     * Calls each of the request plugins and determines if the current request can be processed by one of them.
264
     *
265
     * @return bool
266
     */
267
    public function canProcessRequest(): bool
268
    {
269
        // Return true if the request plugin was already found
270
        if($this->xTargetRequestPlugin !== null)
271
        {
272
            return true;
273
        }
274
275
        // Find a plugin to process the request
276
        foreach($this->xPluginManager->getRequestPlugins() as $sClassName)
277
        {
278
            if($sClassName::canProcessRequest())
279
            {
280
                $this->xTargetRequestPlugin = $this->di->get($sClassName);
281
                return true;
282
            }
283
        }
284
285
        // Check if the upload plugin is enabled
286
        if($this->xUploadHandler === null)
287
        {
288
            return false;
289
        }
290
291
        // If no other plugin than the upload plugin can process the request,
292
        // then it is an HTTP (not ajax) upload request
293
        $this->xUploadHandler->isHttpUpload();
294
        return $this->xUploadHandler->canProcessRequest();
295
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
296
297
    /**
298
     * Process the current request and handle errors and exceptions.
299
     *
300
     * @return void
301
     * @throws RequestException
302
     * @throws SetupException
303
     */
304
    private function _processRequest()
305
    {
306
        $bEndRequest = false;
307
        // Handle before processing event
308
        if(($this->xTargetRequestPlugin))
309
        {
310
            $this->onBefore($bEndRequest);
311
        }
312
        if($bEndRequest)
313
        {
314
            return;
315
        }
316
317
        try
318
        {
319
            // Process uploaded files, if the upload plugin is enabled
320
            if($this->xUploadHandler !== null)
321
            {
322
                $this->xUploadHandler->processRequest();
323
            }
324
            // Process the request
325
            if(($this->xTargetRequestPlugin))
326
            {
327
                $this->xTargetRequestPlugin->processRequest();
328
            }
329
        }
330
        catch(Exception $e)
331
        {
332
            // An exception was thrown while processing the request.
333
            // The request missed the corresponding handler function,
334
            // or an error occurred while attempting to execute the handler.
335
            $this->xResponseManager->error($e->getMessage());
336
            if($e instanceof RequestException || $e instanceof SetupException)
337
            {
338
                $this->onInvalid($e->getMessage());
339
            }
340
            else
341
            {
342
                $this->onError($e);
343
            }
344
            throw $e;
345
        }
346
347
        // Handle after processing event
348
        if(($this->xTargetRequestPlugin))
349
        {
350
            $this->onAfter($bEndRequest);
351
        }
352
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
353
354
    /**
355
     * Clean output buffers.
356
     *
357
     * @return void
358
     */
359
    private function _cleanOutputBuffers()
360
    {
361
        $er = error_reporting(0);
362
        while(ob_get_level() > 0)
363
        {
364
            ob_end_clean();
365
        }
366
        error_reporting($er);
367
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
368
369
    /**
370
     * Process the current request.
371
     *
372
     * Calls each of the request plugins to request that they process the current request.
373
     * If any plugin processes the request, it will return true.
374
     *
375
     * @return void
376
     * @throws RequestException
377
     * @throws SetupException
378
     */
379
    public function processRequest()
380
    {
381
        // Check to see if headers have already been sent out, in which case we can't do our job
382
        if(headers_sent($sFilename, $nLineNumber))
383
        {
384
            echo $this->xTranslator->trans('errors.output.already-sent', [
385
                'location' => $sFilename . ':' . $nLineNumber
386
            ]), "\n", $this->xTranslator->trans('errors.output.advice');
387
            exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
388
        }
389
390
        // Check if there is a plugin to process this request
391
        if(!$this->canProcessRequest())
392
        {
393
            return;
394
        }
395
396
        $this->_processRequest();
397
398
        // Process the databag
399
        $this->xDataBagPlugin->writeCommand();
400
401
        // Clean the processing buffer
402
        if(($this->xConfigManager->getOption('core.process.clean')))
403
        {
404
            $this->_cleanOutputBuffers();
405
        }
406
407
        // If the called function returned no response, take the global response
408
        if(!$this->xResponseManager->getResponse())
409
        {
410
            $this->xResponseManager->append($this->di->getResponse());
411
        }
412
413
        $this->xResponseManager->printDebug();
414
415
        if(($this->xConfigManager->getOption('core.response.send')))
416
        {
417
            $this->xResponseManager->sendOutput();
418
            if(($this->xConfigManager->getOption('core.process.exit')))
419
            {
420
                exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
421
            }
422
        }
423
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
424
}
425