GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( f9c1aa...ebbda5 )
by Steeven
19:04 queued 02:32
created

Compiler   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 383
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 137
dl 0
loc 383
rs 8.48
c 0
b 0
f 0
wmc 49

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getSourceFilePath() 0 3 1
A loadVars() 0 5 1
A getSourceString() 0 3 1
A loadFile() 0 20 5
A parsePhp() 0 33 3
B __construct() 0 23 7
A loadString() 0 25 2
F validateSyntax() 0 88 27
A getSourceFileDirectory() 0 3 1
A parse() 0 13 1

How to fix   Complexity   

Complex Class

Complex classes like Compiler often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Compiler, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * This file is part of the O2System Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
12
// ------------------------------------------------------------------------
13
14
namespace O2System\Parser;
15
16
// ------------------------------------------------------------------------
17
18
use O2System\Spl\Patterns\Structural\Provider\AbstractProvider;
0 ignored issues
show
Bug introduced by
The type O2System\Spl\Patterns\St...ovider\AbstractProvider was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
20
/**
21
 * Class Compiler
22
 *
23
 * @package O2System\Parser
24
 */
25
class Compiler extends AbstractProvider
26
{
27
    /**
28
     * Compiler::$config
29
     * 
30
     * Compiler Config
31
     *
32
     * @var DataStructures\Config
33
     */
34
    private $config;
35
36
    /**
37
     * Compiler::$sourceFilePath
38
     *
39
     * Compiler Source File Path
40
     *
41
     * @var string
42
     */
43
    private $sourceFilePath;
44
45
    /**
46
     * Compiler::$sourceFileDirectory
47
     *
48
     * Compiler Source File Directory
49
     *
50
     * @var string
51
     */
52
    private $sourceFileDirectory;
53
54
    /**
55
     * Compiler::$sourceString
56
     *
57
     * Compiler Source String
58
     *
59
     * @var string
60
     */
61
    private $sourceString;
62
63
    /**
64
     * Compiler::$vars
65
     *
66
     * Compiler Vars
67
     *
68
     * @var array
69
     */
70
    private $vars = [];
71
72
    /**
73
     * Compiler::$template
74
     *
75
     * @var \O2System\Parser\Template\Collection
76
     */
77
    private $template;
78
79
    /**
80
     * Compiler::$string
81
     *
82
     * @var \O2System\Parser\String\Collection
83
     */
84
    private $string;
85
86
    // ------------------------------------------------------------------------
87
88
    /**
89
     * Compiler::__construct
90
     *
91
     * @param DataStructures\Config $config
92
     */
93
    public function __construct(DataStructures\Config $config)
94
    {
95
        language()
96
            ->addFilePath(__DIR__ . DIRECTORY_SEPARATOR)
97
            ->loadFile('parser');
98
99
        $this->template = new Template\Collection();
100
        $this->string = new String\Collection();
101
102
        $this->config = $config;
103
104
        if ($this->config->offsetExists('template')) {
105
            if(is_array($this->config->template)) {
0 ignored issues
show
Bug Best Practice introduced by
The property template does not exist on O2System\Parser\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
106
                foreach($this->config->template as $engine) {
107
                    $this->template->load($engine);
108
                }
109
            }
110
        }
111
112
        if ($this->config->offsetExists('string')) {
113
            if(is_array($this->config->string)) {
0 ignored issues
show
Bug Best Practice introduced by
The property string does not exist on O2System\Parser\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
114
                foreach($this->config->string as $engine) {
115
                    $this->string->load($engine);
116
                }
117
            }
118
        }
119
    }
120
121
    // ------------------------------------------------------------------------
122
123
    /**
124
     * Compiler::getSourceString
125
     *
126
     * @return string
127
     */
128
    public function getSourceString()
129
    {
130
        return $this->sourceString;
131
    }
132
    
133
    // ------------------------------------------------------------------------
134
135
    /**
136
     * Compiler::loadFile
137
     *
138
     * @param string $filePath
139
     *
140
     * @return bool
141
     */
142
    public function loadFile($filePath)
143
    {
144
        if ($filePath instanceof \SplFileInfo) {
0 ignored issues
show
introduced by
$filePath is never a sub-type of SplFileInfo.
Loading history...
145
            $filePath = $filePath->getRealPath();
146
        }
147
148
        if (isset($this->sourceFileDirectory)) {
149
            if (is_file($this->sourceFileDirectory . $filePath)) {
150
                $filePath = $this->sourceFileDirectory . $filePath;
151
            }
152
        }
153
154
        if (is_file($filePath)) {
155
            $this->sourceFilePath = realpath($filePath);
156
            $this->sourceFileDirectory = pathinfo($this->sourceFilePath, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR;
157
158
            return $this->loadString(file_get_contents($filePath));
159
        }
160
161
        return false;
162
    }
163
164
    // ------------------------------------------------------------------------
165
166
    /**
167
     * Compiler::loadString
168
     *
169
     * @param string $string
170
     *
171
     * @return bool
172
     */
173
    public function loadString($string)
174
    {
175
        $this->sourceString = $string;
176
177
        if ($this->config->allowPhpScripts === false) {
0 ignored issues
show
Bug Best Practice introduced by
The property allowPhpScripts does not exist on O2System\Parser\DataStructures\Config. Since you implemented __get, consider adding a @property annotation.
Loading history...
178
            $this->sourceString = preg_replace(
179
                '/<\\?.*(\\?>|$)/Us',
180
                '',
181
                str_replace('<?=', '<?php echo ', $this->sourceString)
182
            );
183
        }
184
185
        $this->sourceString = str_replace(
186
            [
187
                '__DIR__',
188
                '__FILE__',
189
            ],
190
            [
191
                "'" . $this->getSourceFileDirectory() . "'",
192
                "'" . $this->getSourceFilePath() . "'",
193
            ],
194
            $this->sourceString
195
        );
196
197
        return empty($this->sourceString);
198
    }
199
200
    // ------------------------------------------------------------------------
201
202
    /**
203
     * Compiler::getSourceFileDirectory
204
     *
205
     * @return string
206
     */
207
    public function getSourceFileDirectory()
208
    {
209
        return $this->sourceFileDirectory;
210
    }
211
212
    // ------------------------------------------------------------------------
213
214
    /**
215
     * Compiler::getSourceFilePath
216
     *
217
     * @return string
218
     */
219
    public function getSourceFilePath()
220
    {
221
        return $this->sourceFilePath;
222
    }
223
224
    // ------------------------------------------------------------------------
225
226
    /**
227
     * Compiler::parse
228
     *
229
     * @param array $vars
230
     *
231
     * @return bool|string Returns FALSE if failed.
232
     */
233
    public function parse(array $vars = [])
234
    {
235
        $this->loadVars($vars);
236
237
        $output = $this->parsePhp();
238
239
        // Run Template Engines
240
        $output = $this->template->parse($output, $this->vars);
241
242
        // Run String Engines
243
        $output = $this->string->parse($output, $this->vars);
244
245
        return $output;
246
    }
247
248
    // ------------------------------------------------------------------------
249
250
    /**
251
     * Compiler::parsePhp
252
     *
253
     * @param array $vars
254
     *
255
     * @return bool|string Returns FALSE if failed
256
     */
257
    public function parsePhp(array $vars = [])
258
    {
259
        if(count($vars)) {
260
            $this->loadVars($vars);
261
        }
262
263
        extract($this->vars);
264
265
        /*
266
         * Buffer the output
267
         *
268
         * We buffer the output for two reasons:
269
         * 1. Speed. You get a significant speed boost.
270
         * 2. So that the final rendered template can be post-processed by
271
         *  the output class. Why do we need post processing? For one thing,
272
         *  in order to show the elapsed page load time. Unless we can
273
         *  intercept the content right before it's sent to the browser and
274
         *  then stop the timer it won't be accurate.
275
         */
276
        ob_start();
277
278
        echo eval('?>' . str_replace([';?>', ')?>', ');?>'], ['; ?>', '); ?>', '); ?>'], $this->sourceString));
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
279
280
        $output = ob_get_contents();
281
        @ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ob_end_clean(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

281
        /** @scrutinizer ignore-unhandled */ @ob_end_clean();

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
282
283
        $lastError = error_get_last();
284
285
        if (is_array($lastError)) {
0 ignored issues
show
introduced by
The condition is_array($lastError) is always true.
Loading history...
286
            $this->errorFilePath = $this->getSourceFilePath();
0 ignored issues
show
Bug Best Practice introduced by
The property errorFilePath does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
287
        }
288
289
        return $output;
290
    }
291
292
    // ------------------------------------------------------------------------
293
294
    /**
295
     * Compiler::loadVars
296
     *
297
     * @param array $vars
298
     *
299
     * @return bool
300
     */
301
    public function loadVars(array $vars)
302
    {
303
        $this->vars = array_merge($this->vars, $vars);
304
305
        return (bool)empty($this->vars);
306
    }
307
308
    // ------------------------------------------------------------------------
309
310
    /**
311
     * Drivers::validateSyntax
312
     *
313
     * Check the syntax of some PHP code.
314
     *
315
     * @param string $sourceCode PHP code to check.
316
     *
317
     * @return bool|array If false, then check was successful, otherwise an array(message,line) of errors is
318
     *                       returned.
319
     */
320
    function validateSyntax($sourceCode)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
321
    {
322
        if ( ! defined("CR")) {
323
            define("CR", "\r");
324
        }
325
        if ( ! defined("LF")) {
326
            define("LF", "\n");
327
        }
328
        if ( ! defined("CRLF")) {
329
            define("CRLF", "\r\n");
330
        }
331
        $braces = 0;
332
        $inString = 0;
333
        foreach (token_get_all('<?php ' . $sourceCode) as $token) {
334
            if (is_array($token)) {
335
                switch ($token[ 0 ]) {
336
                    case T_CURLY_OPEN:
337
                    case T_DOLLAR_OPEN_CURLY_BRACES:
338
                    case T_START_HEREDOC:
339
                        ++$inString;
340
                        break;
341
                    case T_END_HEREDOC:
342
                        --$inString;
343
                        break;
344
                }
345
            } else {
346
                if ($inString & 1) {
347
                    switch ($token) {
348
                        case '`':
349
                        case '\'':
350
                        case '"':
351
                            --$inString;
352
                            break;
353
                    }
354
                } else {
355
                    switch ($token) {
356
                        case '`':
357
                        case '\'':
358
                        case '"':
359
                            ++$inString;
360
                            break;
361
                        case '{':
362
                            ++$braces;
363
                            break;
364
                        case '}':
365
                            if ($inString) {
366
                                --$inString;
367
                            } else {
368
                                --$braces;
369
                                if ($braces < 0) {
370
                                    break 2;
371
                                }
372
                            }
373
                            break;
374
                    }
375
                }
376
            }
377
        }
378
        $inString = @ini_set('log_errors', false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

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

378
        $inString = @ini_set('log_errors', /** @scrutinizer ignore-type */ false);
Loading history...
379
        $token = @ini_set('display_errors', true);
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type string expected by parameter $newvalue of ini_set(). ( Ignorable by Annotation )

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

379
        $token = @ini_set('display_errors', /** @scrutinizer ignore-type */ true);
Loading history...
380
        ob_start();
381
        $sourceCode = substr($sourceCode, strlen('<?php '));
382
        $braces || $sourceCode = "if(0){{$sourceCode}\n}";
383
        if (eval($sourceCode) === false) {
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
384
            if ($braces) {
385
                $braces = PHP_INT_MAX;
386
            } else {
387
                false !== strpos($sourceCode, CR) && $sourceCode = strtr(str_replace(CRLF, LF, $sourceCode), CR, LF);
388
                $braces = substr_count($sourceCode, LF);
389
            }
390
            $sourceCode = ob_get_clean();
391
            $sourceCode = strip_tags($sourceCode);
392
            if (preg_match("'syntax error, (.+) in .+ on line (\d+)$'s", $sourceCode, $sourceCode)) {
0 ignored issues
show
Bug introduced by
$sourceCode of type string is incompatible with the type array|null expected by parameter $matches of preg_match(). ( Ignorable by Annotation )

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

392
            if (preg_match("'syntax error, (.+) in .+ on line (\d+)$'s", $sourceCode, /** @scrutinizer ignore-type */ $sourceCode)) {
Loading history...
393
                $sourceCode[ 2 ] = (int)$sourceCode[ 2 ];
394
                $sourceCode = $sourceCode[ 2 ] <= $braces
395
                    ? [$sourceCode[ 1 ], $sourceCode[ 2 ]]
396
                    : ['unexpected $end' . substr($sourceCode[ 1 ], 14), $braces];
397
            } else {
398
                $sourceCode = ['syntax error', 0];
399
            }
400
        } else {
401
            ob_end_clean();
402
            $sourceCode = false;
403
        }
404
        @ini_set('display_errors', $token);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ini_set(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

404
        /** @scrutinizer ignore-unhandled */ @ini_set('display_errors', $token);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
405
        @ini_set('log_errors', $inString);
406
407
        return $sourceCode;
408
    }
409
}