JPSpan_Include_ErrorReader()   F
last analyzed

Complexity

Conditions 11
Paths 432

Size

Total Lines 54
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 32
c 0
b 0
f 0
nc 432
nop 4
dl 0
loc 54
rs 3.9388

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @package    JPSpan
4
 * @subpackage Include
5
 */
6
7
//-----------------------------------------------------------------------------
8
9
/**
10
 * When to compress the Javascript (remove whitespace formatting)
11
 * Set to TRUE and Javascript will be "compressed"
12
 */
13
if (!defined('JPSPAN_INCLUDE_COMPRESS')) {
14
    define('JPSPAN_INCLUDE_COMPRESS', false);
15
}
16
17
//-----------------------------------------------------------------------------
18
/**
19
 * Make sure a file_get_contents() implementation exists
20
 * PHP backwards compatability
21
 */
22
if (!function_exists('file_get_contents')) {
23
    /**
24
     * @see        https://www.php.net/file_get_contents
25
     * @param mixed $filename
26
     * @return string file content
27
     * @package    JPSpan
28
     * @subpackage Include
29
     */
30
    function file_get_contents($filename): string
31
    {
32
        $fd      = fopen((string)$filename, 'rb');
33
        $content = fread($fd, filesize($filename));
34
        fclose($fd);
35
36
        return $content;
37
    }
38
}
39
//-----------------------------------------------------------------------------
40
41
/**
42
 * Include a Javascript file. Filename must be relative to the
43
 * JPSpan/js/ directory (without a leading slash if in subdir)
44
 * This is the recommended point to include Javascript files
45
 * Calling this registers a shutdown function which takes care of displaying
46
 * the Javascript
47
 * @param mixed $file
48
 * @access     public
49
 * @subpackage Include
50
 * @package    JPSpan
51
 */
52
function JPSpan_Include($file)
53
{
54
    $Includer = (new JPSpan_include())->instance();
55
        $Includer->loadFile($file);
56
        register_shutdown_function('JPSpan_Include_Shutdown');
57
        }
58
59
//-----------------------------------------------------------------------------
60
/**
61
 * PHP shutdown function making sure Javascript is displayed
62
 * @package    JPSpan
63
 * @subpackage Include
64
 * @access     private
65
 */
66
function JPSpan_Include_Shutdown()
67
{
68
    $Includer = (new JPSpan_include())->instance();
69
            echo $Includer->getCode();
70
        }
71
72
//-----------------------------------------------------------------------------
73
74
/**
75
 * Loads Javascript but does not register shutdown fn
76
 * @param mixed $file
77
 * @access     public
78
 * @package    JPSpan
79
 * @subpackage Include
80
 * @see        JPSpan_Include
81
 */
82
function JPSpan_Include_Register($file)
83
{
84
    $Includer = (new JPSpan_include())->instance();
85
                $Includer->loadFile($file);
86
        }
87
88
//-----------------------------------------------------------------------------
89
90
/**
91
 * Loads the Javascript error reader
92
 * @param string $lang (optional) 2 letter localization code e.g. 'en'
93
 * @param array  $app
94
 * @param array  $ser
95
 * @param array  $cli
96
 * @see        JPSpan_Include
97
 * @package    JPSpan
98
 * @subpackage Include
99
 * @internal   param array $list of Application_Errors to merge in
100
 * @internal   param array $list of Server_Errors to merge in
101
 * @internal   param array $list of Client_Errors to merge in
102
 * @todo       Break this function up
103
 * @access     public
104
 */
105
function JPSpan_Include_ErrorReader($lang = 'en', $app = [], $ser = [], $cli = [])
106
{
107
    $errorfile = 'errors.' . $lang . '.ini';
108
    if (!file_exists(JPSPAN . 'errors/' . $errorfile)) {
109
        $errorfile = 'errors.en.ini';
110
    }
111
112
    $errors = parse_ini_file(JPSPAN . 'errors/' . $errorfile, true);
113
114
    $script = "/**@\n* require_once __DIR__   . '/util/errorreader.js';\n*/\n";
115
    // Use Object instead of Array as Javascript will fill empty elements
116
    $script .= "JPSpan_Util_ErrorReader.prototype.errorList = new Object();\n";
117
118
    foreach ($errors['Client_Error'] as $key => $value) {
119
        $value  = addcslashes($value, "\000\042\047\134");
120
        $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
121
    }
122
123
    foreach ($cli as $key => $value) {
124
        if (array_key_exists($key, $errors['Client_Error'])) {
125
            continue;
126
        }
127
        $value  = addcslashes($value, "\000\042\047\134");
128
        $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
129
    }
130
131
    foreach ($errors['Server_Error'] as $key => $value) {
132
        $value  = addcslashes($value, "\000\042\047\134");
133
        $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
134
    }
135
136
    foreach ($ser as $key => $value) {
137
        if (array_key_exists($key, $errors['Server_Error'])) {
138
            continue;
139
        }
140
        $value  = addcslashes($value, "\000\042\047\134");
141
        $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
142
    }
143
144
    foreach ($errors['Application_Error'] as $key => $value) {
145
        $value  = addcslashes($value, "\000\042\047\134");
146
        $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
147
    }
148
149
    foreach ($app as $key => $value) {
150
        if (array_key_exists($key, $errors['Application_Error'])) {
151
            continue;
152
        }
153
        $value  = addcslashes($value, "\000\042\047\134");
154
        $script .= "JPSpan_Util_ErrorReader.prototype.errorList[$key] = '$value';\n";
155
    }
156
157
    $Includer = (new JPSpan_include())->instance();
158
                    $Includer->loadString('errorreaderlist', $script);
159
                }
160
161
//-----------------------------------------------------------------------------
162
163
/**
164
 * Returns all loaded Javascript
165
 * @return string
166
 * @access     public
167
 * @package    JPSpan
168
 * @subpackage Include
169
 * @see        JPSpan_Include
170
 */
171
function JPSpan_Includes_Fetch(): string
172
{
173
    $Includer = (new JPSpan_include())->instance();
174
175
                        return $Includer->getCode();
176
                    }
177
178
//-----------------------------------------------------------------------------
179
180
/**
181
 * Displays all loaded Javascript
182
 * @see        JPSpan_Include
183
 * @package    JPSpan
184
 * @subpackage Include
185
 * @access     public
186
 */
187
function JPSpan_Includes_Display()
188
{
189
    echo JPSpan_Includes_Fetch();
190
}
191
192
//-----------------------------------------------------------------------------
193
194
/**
195
 * Front for dealing with includes
196
 * @package    JPSpan
197
 * @subpackage Include
198
 * @access     public
199
 */
200
class JPSpan_Include
201
{
202
    /**
203
     * @var JPSpan_Include_Manager
204
     * @access private
205
     */
206
    public $Manager;
207
208
    /**
209
     * Do not construct JPSpan_Include directly! Use instance method
210
     * @see    instance
211
     * @access private
212
     */
213
    public function __construct()
214
    {
215
        $this->Manager = new JPSpan_Include_Manager();
216
    }
217
218
    /**
219
     * Load a Javascript file
220
     * @param mixed $file
221
     * @access public
222
     */
223
    public function loadFile($file): void
224
    {
225
        $file = JPSPAN . 'js/' . $file;
226
        $this->Manager->loadFile($file);
227
    }
228
229
    /**
230
     * Load a Javascript script from a string
231
     * @param $name
232
     * @param $src
233
     * @internal param source $string code
234
     * @access   public
235
     */
236
    public function loadString($name, $src): void
237
    {
238
        $this->Manager->load($name, $src);
239
    }
240
241
    /**
242
     * Get the code
243
     * @return string Javascript
244
     * @access public
245
     */
246
    public function getCode(): string
247
    {
248
        if (JPSPAN_INCLUDE_COMPRESS) {
249
            require_once JPSPAN . 'Script.php';
250
            $code = $this->Manager->getCode();
251
252
            return (new JPSpan_Script())->compress($code);
253
        }
254
255
        return $this->Manager->getCode();
256
    }
257
258
    /**
259
     * Obtain singleton instance of JPSpan_Include
260
     * @return JPSpan_Include
261
     * @access public
262
     * @static
263
     */
264
    public static function &instance(): ?\JPSpan_Include
265
    {
266
        static $importer = null;
267
268
        if (!$importer) {
269
            $importer = new self();
270
        }
271
272
        return $importer;
273
    }
274
}
275
276
//-----------------------------------------------------------------------------
277
278
/**
279
 * Manages the includes, making sure dependencies are resolved
280
 * @package    JPSpan
281
 * @subpackage Include
282
 * @access     protected
283
 */
284
class JPSpan_Include_Manager
285
{
286
    /**
287
     * List of files to include. Dependencies are added at end of list
288
     * @var array
289
     * @access private
290
     */
291
    public $includes = [];
292
    /**
293
     * Map of file name to source code
294
     * @var array
295
     * @access private
296
     */
297
    public $code = [];
298
299
    /**
300
     * Load a Javascript file
301
     * @param mixed $file
302
     * @access protected
303
     */
304
    public function loadFile($file): void
305
    {
306
        $src = file_get_contents($file);
307
        $this->load($file, $src);
308
    }
309
310
    /**
311
     * Load a Javascript contained in a string
312
     * @param mixed $name
313
     * @param mixed $src
314
     * @access protected
315
     */
316
    public function load($name, $src): void
317
    {
318
        if (!in_array($name, $this->includes)) {
319
            $this->includes[] = $name;
320
            $File             = new JPSpan_Include_File($this);
0 ignored issues
show
Unused Code introduced by
The call to JPSpan_Include_File::__construct() has too many arguments starting with $this. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

320
            $File             = /** @scrutinizer ignore-call */ new JPSpan_Include_File($this);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
321
            $File->parse($src);
322
            $this->code[$name] = $File->src;
323
            $this->resolveDependencies($File->includes);
324
        }
325
    }
326
327
    /**
328
     * Resolve any dependencies a script has on others
329
     * @param mixed $includes
330
     * @access private
331
     */
332
    public function resolveDependencies($includes): void
333
    {
334
        foreach ($includes as $include) {
335
            $src = file_get_contents($include);
336
            $this->load($include, $src);
337
        }
338
    }
339
340
    /**
341
     * Get the source
342
     * @return string
343
     * @access protected
344
     */
345
    public function getCode(): string
346
    {
347
        $includes = array_reverse($this->includes);
348
        $code     = '';
349
        foreach ($includes as $include) {
350
            $code .= $this->code[$include];
351
        }
352
353
        return $code;
354
    }
355
}
356
357
//-----------------------------------------------------------------------------
358
359
/**
360
 * Represents a single file - manages parsing the file for dependencies
361
 * Right now this does no error checking / validation of parse files
362
 * @package    JPSpan
363
 * @subpackage Include
364
 * @access     protected
365
 */
366
class JPSpan_Include_File
367
{
368
    /**
369
     * List of dependencies, obtained from parsing the source
370
     * @var array
371
     * @access protected
372
     */
373
    public $includes = [];
374
    /**
375
     * Source code with dependency statements removed
376
     * @var string
377
     * @access protected
378
     */
379
    public $src = '';
380
381
    /**
382
     * Parse the file for dependencies
383
     * @param mixed $src
384
     * @access protected
385
     */
386
    public function parse($src): void
387
    {
388
        $Parser = new JPSpan_Include_Parser($this);
389
        $Parser->parse($src);
390
    }
391
392
    /**
393
     * Parser handler
394
     * @param mixed $script
395
     * @param mixed $state
396
     * @return bool TRUE
397
     * @access protected
398
     */
399
    public function script($script, $state): bool
0 ignored issues
show
Unused Code introduced by
The parameter $state is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

399
    public function script($script, /** @scrutinizer ignore-unused */ $state): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
400
    {
401
        $this->src .= $script;
402
403
        return true;
404
    }
405
406
    /**
407
     * Parser handler (discards)
408
     * @param mixed $decl
409
     * @param mixed $state
410
     * @return bool TRUE
411
     * @access protected
412
     */
413
    public function declaration($decl, $state): bool
0 ignored issues
show
Unused Code introduced by
The parameter $state is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

413
    public function declaration($decl, /** @scrutinizer ignore-unused */ $state): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $decl is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

413
    public function declaration(/** @scrutinizer ignore-unused */ $decl, $state): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
414
    {
415
        return true;
416
    }
417
418
    /**
419
     * Parser handler - handles include statements
420
     * @param mixed $file
421
     * @param mixed $state
422
     * @return bool TRUE
423
     * @access protected
424
     */
425
    public function inc($file, $state): bool
426
    {
427
        if (JPSPAN_LEXER_UNMATCHED == $state) {
428
            $file             = str_replace(["'", '"'], '', $file);
429
            $this->includes[] = JPSPAN . 'js/' . trim($file);
430
        }
431
432
        return true;
433
    }
434
}
435
436
//-----------------------------------------------------------------------------
437
438
/**
439
 * Parses source for include statements
440
 * @package    JPSpan
441
 * @subpackage Include
442
 * @access     protected
443
 */
444
class JPSpan_Include_Parser
445
{
446
    /**
447
     * Callback handler for parser
448
     * @var JPSpan_Include_File
449
     * @access private
450
     */
451
    public $Handler;
452
453
    /**
454
     * @param mixed $Handler
455
     * @access protected
456
     */
457
    public function __construct(&$Handler)
458
    {
459
        $this->Handler = &$Handler;
460
    }
461
462
    /**
463
     * Parse some Javascript
464
     * @param mixed $src
465
     * @access protected
466
     */
467
    public function parse($src): void
468
    {
469
        $Lexer = &$this->getLexer();
470
        $Lexer->parse($src);
471
    }
472
473
    /**
474
     * Create the Lexer
475
     * @return JPSpan_Lexer
476
     * @access private
477
     * @see    JPSpan_Lexer
478
     */
479
    public function &getLexer(): \JPSpan_Lexer
480
    {
481
        require_once JPSPAN . 'Lexer.php';
482
        $Lexer = new JPSpan_Lexer($this->Handler, 'script');
483
484
        $Lexer->addEntryPattern('/\*\*@', 'script', 'declaration');
485
        $Lexer->addExitPattern('\*/', 'declaration');
486
487
        $Lexer->addEntryPattern('include', 'declaration', 'inc');
488
        $Lexer->addExitPattern(';', 'inc');
489
490
        return $Lexer;
491
    }
492
}
493