Completed
Push — master ( f813e0...5f1c56 )
by Thierry
03:59 queued 02:07
created

Jaxon   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 408
Duplicated Lines 2.21 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 0
Metric Value
dl 9
loc 408
rs 9.2
c 0
b 0
f 0
wmc 34
lcom 1
cbo 14

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getVersion() 0 4 1
B register() 0 24 4
A addClassDir() 0 4 1
A registerClasses() 0 4 1
A registerClass() 0 5 2
A getScript() 0 18 4
A printScript() 0 4 1
A getJs() 0 4 1
A getCss() 0 4 1
A canProcessRequest() 0 4 1
D processRequest() 9 97 13
A sendResponse() 0 4 1
A sendHeaders() 0 4 1
A getOutput() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * Jaxon.php - Jaxon class
5
 *
6
 * The Jaxon class uses a modular plug-in system to facilitate the processing
7
 * of special Ajax requests made by a PHP page.
8
 * It generates Javascript that the page must include in order to make requests.
9
 * It handles the output of response commands (see <Jaxon\Response\Response>).
10
 * Many flags and settings can be adjusted to effect the behavior of the Jaxon class
11
 * as well as the client-side javascript.
12
 *
13
 * @package jaxon-core
14
 * @author Jared White
15
 * @author J. Max Wilson
16
 * @author Joseph Woolley
17
 * @author Steffen Konerow
18
 * @author Thierry Feuzeu <[email protected]>
19
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
20
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
21
 * @copyright 2016 Thierry Feuzeu <[email protected]>
22
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
23
 * @link https://github.com/jaxon-php/jaxon-core
24
 */
25
26
namespace Jaxon;
27
28
use Jaxon\Plugin\Manager as PluginManager;
29
use Jaxon\Request\Manager as RequestManager;
30
use Jaxon\Response\Manager as ResponseManager;
31
32
use Jaxon\Utils\URI;
33
use Exception;
34
use Closure;
35
36
class Jaxon
37
{
38
    use \Jaxon\Utils\Traits\Config;
39
    use \Jaxon\Utils\Traits\Manager;
40
    use \Jaxon\Utils\Traits\Translator;
41
    use \Jaxon\Utils\Traits\Paginator;
42
    use \Jaxon\Utils\Traits\Template;
43
44
    use Traits\Autoload;
45
    use Traits\Config;
46
    use Traits\Plugin;
47
    use Traits\Upload;
48
    use Traits\Sentry;
49
50
    /**
51
     * Package version number
52
     *
53
     * @var string
54
     */
55
    private $sVersion = 'Jaxon 2.1.0';
56
57
    /*
58
     * Processing events
59
     */
60
    const PROCESSING_EVENT = 'ProcessingEvent';
61
    const PROCESSING_EVENT_BEFORE = 'BeforeProcessing';
62
    const PROCESSING_EVENT_AFTER = 'AfterProcessing';
63
    const PROCESSING_EVENT_INVALID = 'InvalidRequest';
64
    const PROCESSING_EVENT_ERROR = 'ProcessingError';
65
66
    /*
67
     * Request methods
68
     */
69
    const METHOD_UNKNOWN = 0;
70
    const METHOD_GET = 1;
71
    const METHOD_POST = 2;
72
73
    /*
74
     * Request plugins
75
     */
76
    // For objects who's methods will be callable from the browser.
77
    const CALLABLE_OBJECT = 'CallableObject';
78
    // For functions available at global scope, or from an instance of an object.
79
    const USER_FUNCTION = 'UserFunction';
80
    // For browser events.
81
    const BROWSER_EVENT = 'BrowserEvent';
82
    // For event handlers.
83
    const EVENT_HANDLER = 'EventHandler';
84
    // For uploaded files.
85
    const FILE_UPLOAD = 'FileUpload';
86
87
    /*
88
     * Request parameters
89
     */
90
    // Specifies that the parameter will consist of an array of form values.
91
    const FORM_VALUES = 'FormValues';
92
    // Specifies that the parameter will contain the value of an input control.
93
    const INPUT_VALUE = 'InputValue';
94
    // Specifies that the parameter will consist of a boolean value of a checkbox.
95
    const CHECKED_VALUE = 'CheckedValue';
96
    // Specifies that the parameter value will be the innerHTML value of the element.
97
    const ELEMENT_INNERHTML = 'ElementInnerHTML';
98
    // Specifies that the parameter will be a quoted value (string).
99
    const QUOTED_VALUE = 'QuotedValue';
100
    // Specifies that the parameter will be a boolean value (true or false).
101
    const BOOL_VALUE = 'BoolValue';
102
    // Specifies that the parameter will be a numeric, non-quoted value.
103
    const NUMERIC_VALUE = 'NumericValue';
104
    // Specifies that the parameter will be a non-quoted value
105
    // (evaluated by the browsers javascript engine at run time).
106
    const JS_VALUE = 'UnquotedValue';
107
    // Specifies that the parameter will be an integer used to generate pagination links.
108
    const PAGE_NUMBER = 'PageNumber';
109
110
    /**
111
     * Processing event handlers that have been assigned during this run of the script
112
     *
113
     * @var array
114
     */
115
    private $aProcessingEvents;
116
117
    public function __construct()
118
    {
119
        $this->aProcessingEvents = array();
120
        $this->setDefaultOptions();
121
    }
122
123
    /**
124
     * The current Jaxon version
125
     *
126
     * @return string
127
     */
128
    public function getVersion()
129
    {
130
        return $this->sVersion;
131
    }
132
133
    /**
134
     * Register request handlers, including functions, callable objects and events.
135
     *
136
     * New plugins can be added that support additional registration methods and request processors.
137
     *
138
     * @param string    $sType            The type of request handler being registered
139
     *        Options include:
140
     *        - Jaxon::USER_FUNCTION: a function declared at global scope
141
     *        - Jaxon::CALLABLE_OBJECT: an object who's methods are to be registered
142
     *        - Jaxon::BROWSER_EVENT: an event which will cause zero or more event handlers to be called
143
     *        - Jaxon::EVENT_HANDLER: register an event handler function.
144
     * @param mixed        $sFunction | $objObject | $sEvent
145
     *        When registering a function, this is the name of the function
146
     *        When registering a callable object, this is the object being registered
147
     *        When registering an event or event handler, this is the name of the event
148
     * @param mixed        $sIncludeFile | $aCallOptions | $sEventHandler
149
     *        When registering a function, this is the (optional) include file
150
     *        When registering a callable object, this is an (optional) array
151
     *             of call options for the functions being registered
152
     *        When registering an event handler, this is the name of the function
153
     *
154
     * @return mixed
155
     */
156
    public function register($sType, $xArgs)
157
    {
158
        $aArgs = func_get_args();
159
        $nArgs = func_num_args();
160
161
        if(self::PROCESSING_EVENT == $sType)
162
        {
163
            if($nArgs > 2)
164
            {
165
                $sEvent = $xArgs;
166
                $xUserFunction = $aArgs[2];
167
                if(!is_a($xUserFunction, 'Request\\Support\\UserFunction'))
168
                    $xUserFunction = new Request\Support\UserFunction($xUserFunction);
169
                $this->aProcessingEvents[$sEvent] = $xUserFunction;
170
            }
171
            /*else
172
            {
173
                // Todo: return error
174
            }*/
175
            return true;
176
        }
177
178
        return $this->getPluginManager()->register($aArgs);
179
    }
180
181
    /**
182
     * Add a path to the class directories
183
     *
184
     * @param string            $sDirectory             The path to the directory
185
     * @param string|null       $sNamespace             The associated namespace
186
     * @param string            $sSeparator             The character to use as separator in javascript class names
187
     * @param array             $aProtected             The functions that are not to be exported
188
     *
189
     * @return boolean
190
     */
191
    public function addClassDir($sDirectory, $sNamespace = null, $sSeparator = '.', array $aProtected = array())
192
    {
193
        return $this->getPluginManager()->addClassDir($sDirectory, $sNamespace, $sSeparator, $aProtected);
194
    }
195
196
    /**
197
     * Register callable objects from all class directories
198
     *
199
     * @param array             $aOptions               The options to register the classes with
200
     *
201
     * @return void
202
     */
203
    public function registerClasses(array $aOptions = array())
204
    {
205
        return $this->getPluginManager()->registerClasses($aOptions);
206
    }
207
208
    /**
209
     * Register a callable object from one of the class directories
210
     *
211
     * The class name can be dot, slash or anti-slash separated.
212
     * If the $bGetObject parameter is set to true, the registered instance of the class is returned.
213
     *
214
     * @param string            $sClassName             The name of the class to register
215
     * @param array             $aOptions               The options to register the class with
216
     * @param boolean           $bGetObject             Return the registered instance of the class
217
     *
218
     * @return void
219
     */
220
    public function registerClass($sClassName, array $aOptions = array(), $bGetObject = false)
221
    {
222
        $this->getPluginManager()->registerClass($sClassName, $aOptions);
223
        return (($bGetObject) ? $this->getPluginManager()->getRegisteredObject($sClassName) : null);
224
    }
225
226
    /**
227
     * Returns the Jaxon Javascript header and wrapper code to be printed into the page
228
     *
229
     * The javascript code returned by this function is dependent on the plugins
230
     * that are included and the functions and classes that are registered.
231
     *
232
     * @param boolean        $bIncludeJs            Also get the JS files
233
     * @param boolean        $bIncludeCss        Also get the CSS files
234
     *
235
     * @return string
236
     */
237
    public function getScript($bIncludeJs = false, $bIncludeCss = false)
238
    {
239
        if(!$this->getOption('core.request.uri'))
240
        {
241
            $this->setOption('core.request.uri', URI::detect());
242
        }
243
        $sCode = '';
244
        if(($bIncludeCss))
245
        {
246
            $sCode .= $this->getPluginManager()->getCss() . "\n";
247
        }
248
        if(($bIncludeJs))
249
        {
250
            $sCode .= $this->getPluginManager()->getJs() . "\n";
251
        }
252
        $sCode .= $this->getPluginManager()->getScript();
253
        return $sCode;
254
    }
255
    
256
    /**
257
     * Print the jaxon Javascript header and wrapper code into your page
258
     *
259
     * The javascript code returned by this function is dependent on the plugins
260
     * that are included and the functions and classes that are registered.
261
     *
262
     * @param boolean        $bIncludeJs            Also print the JS files
263
     * @param boolean        $bIncludeCss        Also print the CSS files
264
     *
265
     * @return void
266
     */
267
    public function printScript($bIncludeJs = false, $bIncludeCss = false)
268
    {
269
        print $this->getScript($bIncludeJs, $bIncludeCss);
270
    }
271
    
272
    /**
273
     * Return the javascript header code and file includes
274
     *
275
     * @return string
276
     */
277
    public function getJs()
278
    {
279
        return $this->getPluginManager()->getJs();
280
    }
281
    
282
    /**
283
     * Return the CSS header code and file includes
284
     *
285
     * @return string
286
     */
287
    public function getCss()
288
    {
289
        return $this->getPluginManager()->getCss();
290
    }
291
292
    /**
293
     * Determine if a call is a jaxon request or a page load request
294
     *
295
     * @return boolean
296
     */
297
    public function canProcessRequest()
298
    {
299
        return $this->getPluginManager()->canProcessRequest();
300
    }
301
302
    /**
303
     * If this is a jaxon request, call the requested PHP function, build the response and send it back to the browser
304
     *
305
     * This is the main server side engine for Jaxon.
306
     * It handles all the incoming requests, including the firing of events and handling of the response.
307
     * If your RequestURI is the same as your web page, then this function should be called before ANY
308
     * headers or HTML is output from your script.
309
     *
310
     * This function may exit after the request is processed, if the 'core.process.exit' option is set to true.
311
     *
312
     * @return void
313
     *
314
     * @see <Jaxon\Jaxon->canProcessRequest>
315
     */
316
    public function processRequest()
317
    {
318
        // Check to see if headers have already been sent out, in which case we can't do our job
319
        if(headers_sent($filename, $linenumber))
320
        {
321
            echo $this->trans('errors.output.already-sent', array(
322
                'location' => $filename . ':' . $linenumber
323
            )), "\n", $this->trans('errors.output.advice');
324
            exit();
325
        }
326
327
        // Check if there is a plugin to process this request
328
        if(!$this->canProcessRequest())
329
        {
330
            return;
331
        }
332
333
        $bEndRequest = false;
334
        $mResult = true;
335
336
        // Handle before processing event
337 View Code Duplication
        if(isset($this->aProcessingEvents[self::PROCESSING_EVENT_BEFORE]))
338
        {
339
            $this->aProcessingEvents[self::PROCESSING_EVENT_BEFORE]->call(array(&$bEndRequest));
340
        }
341
342
        if(!$bEndRequest)
343
        {
344
            try
345
            {
346
                $mResult = $this->getPluginManager()->processRequest();
347
            }
348
            catch(Exception $e)
349
            {
350
                // An exception was thrown while processing the request.
351
                // The request missed the corresponding handler function,
352
                // or an error occurred while attempting to execute the handler.
353
                // Replace the response, if one has been started and send a debug message.
354
355
                $xResponseManager = $this->getResponseManager();
356
                $xResponseManager->clear();
357
                $xResponseManager->append(new Response\Response());
358
                $xResponseManager->debug($e->getMessage());
359
                $mResult = false;
360
361
                if($e instanceof \Jaxon\Exception\Error)
362
                {
363
                    $sEvent = self::PROCESSING_EVENT_INVALID;
364
                    $aParams = array($e->getMessage());
365
                }
366
                else
367
                {
368
                    $sEvent = self::PROCESSING_EVENT_ERROR;
369
                    $aParams = array($e);
370
                }
371
372
                if(isset($this->aProcessingEvents[$sEvent]))
373
                {
374
                    // Call the processing event
375
                    $this->aProcessingEvents[$sEvent]->call($aParams);
376
                }
377
                else
378
                {
379
                    // The exception is not to be processed here.
380
                    throw $e;
381
                }
382
            }
383
        }
384
        // Clean the processing buffer
385
        if(($this->getOption('core.process.clean')))
386
        {
387
            $er = error_reporting(0);
388
            while (ob_get_level() > 0)
389
            {
390
                ob_end_clean();
391
            }
392
            error_reporting($er);
393
        }
394
395
        if($mResult === true)
396
        {
397
            // Handle after processing event
398 View Code Duplication
            if(isset($this->aProcessingEvents[self::PROCESSING_EVENT_AFTER]))
399
            {
400
                $bEndRequest = false;
401
                $this->aProcessingEvents[self::PROCESSING_EVENT_AFTER]->call(array($bEndRequest));
402
            }
403
        }
404
405
        $this->getResponseManager()->printDebug();
406
407
        if(($this->getOption('core.process.exit')))
408
        {
409
            $this->getResponseManager()->sendOutput();
410
            exit();
411
        }
412
    }
413
414
    /**
415
     * Send the response output back to the browser
416
     *
417
     * @return void
418
     */
419
    public function sendResponse()
420
    {
421
        $this->getResponseManager()->sendOutput();
422
    }
423
424
    /**
425
     * Send the HTTP headers back to the browser
426
     *
427
     * @return void
428
     */
429
    public function sendHeaders()
430
    {
431
        $this->getResponseManager()->sendHeaders();
432
    }
433
434
    /**
435
     * Get the response output
436
     *
437
     * @return string
438
     */
439
    public function getOutput()
440
    {
441
        $this->getResponseManager()->getOutput();
442
    }
443
}
444