1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | /* |
||
6 | * This file is part of the humbug/php-scoper package. |
||
7 | * |
||
8 | * Copyright (c) 2017 Théo FIDRY <[email protected]>, |
||
9 | * Pádraic Brady <[email protected]> |
||
10 | * |
||
11 | * For the full copyright and license information, please view the LICENSE |
||
12 | * file that was distributed with this source code. |
||
13 | */ |
||
14 | |||
15 | namespace Humbug\PhpScoper\Scoper; |
||
16 | |||
17 | use Humbug\PhpScoper\PhpParser\Printer\Printer; |
||
18 | use Humbug\PhpScoper\PhpParser\TraverserFactory; |
||
19 | use PhpParser\Error as PhpParserError; |
||
20 | use PhpParser\Lexer; |
||
21 | use PhpParser\Parser; |
||
22 | use function basename; |
||
23 | use function func_get_args; |
||
24 | use function ltrim; |
||
25 | use function preg_match as native_preg_match; |
||
26 | |||
27 | final class PhpScoper implements Scoper |
||
28 | { |
||
29 | private const FILE_PATH_PATTERN = '/\.php$/'; |
||
30 | private const NOT_FILE_BINARY = '/\..+?$/'; |
||
31 | private const PHP_TAG = '/^<\?php/'; |
||
32 | private const PHP_BINARY = '/^#!.+?php.*\n{1,}<\?php/'; |
||
33 | |||
34 | private Parser $parser; |
||
35 | private Scoper $decoratedScoper; |
||
36 | 554 | private TraverserFactory $traverserFactory; |
|
37 | private Printer $printer; |
||
38 | 554 | private Lexer $lexer; |
|
39 | 554 | ||
40 | 554 | public function __construct( |
|
41 | Parser $parser, |
||
42 | Scoper $decoratedScoper, |
||
43 | TraverserFactory $traverserFactory, |
||
44 | Printer $printer, |
||
45 | Lexer $lexer |
||
46 | ) { |
||
47 | $this->parser = $parser; |
||
48 | $this->decoratedScoper = $decoratedScoper; |
||
49 | $this->traverserFactory = $traverserFactory; |
||
50 | 553 | $this->printer = $printer; |
|
51 | $this->lexer = $lexer; |
||
52 | 553 | } |
|
53 | 2 | ||
54 | /** |
||
55 | * Scopes PHP files. |
||
56 | 551 | * |
|
57 | * @throws PhpParserError |
||
58 | */ |
||
59 | 551 | public function scope(string $filePath, string $contents): string |
|
60 | { |
||
61 | 551 | if (!self::isPhpFile($filePath, $contents)) { |
|
62 | return $this->decoratedScoper->scope(...func_get_args()); |
||
63 | 550 | } |
|
64 | |||
65 | 550 | return $this->scopePhp($contents); |
|
66 | } |
||
67 | 549 | ||
68 | public function scopePhp(string $php): string |
||
69 | 549 | { |
|
70 | $statements = $this->parser->parse($php); |
||
71 | $oldTokens = $this->lexer->getTokens(); |
||
72 | 553 | ||
73 | $scopedStatements = $this->traverserFactory |
||
74 | 553 | ->create($this) |
|
75 | 549 | ->traverse($statements); |
|
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
76 | |||
77 | return $this->printer->print( |
||
78 | 4 | $scopedStatements, |
|
79 | 1 | $scopedStatements, |
|
80 | $oldTokens, |
||
81 | ); |
||
82 | 3 | } |
|
83 | 1 | ||
84 | private static function isPhpFile(string $filePath, string $contents): bool |
||
85 | { |
||
86 | 2 | if (1 === native_preg_match(self::FILE_PATH_PATTERN, $filePath)) { |
|
87 | return true; |
||
88 | } |
||
89 | |||
90 | if (1 === native_preg_match(self::NOT_FILE_BINARY, basename($filePath))) { |
||
91 | return false; |
||
92 | } |
||
93 | |||
94 | if (1 === native_preg_match(self::PHP_TAG, ltrim($contents))) { |
||
95 | return true; |
||
96 | } |
||
97 | |||
98 | return 1 === native_preg_match(self::PHP_BINARY, $contents); |
||
99 | } |
||
100 | } |
||
101 |