Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
18.52% |
10 / 54 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
ChangeEnumerator | |
18.52% |
10 / 54 |
|
0.00% |
0 / 2 |
173.34 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
determineReplacements | |
19.61% |
10 / 51 |
|
0.00% |
0 / 1 |
149.01 |
1 | <?php |
2 | /** |
3 | * Determine the replacements to be made to the discovered symbols. |
4 | * |
5 | * Typically this will just be a prefix, but more complex rules allow for replacements specific to individual symbols/namespaces. |
6 | */ |
7 | |
8 | namespace BrianHenryIE\Strauss\Pipeline; |
9 | |
10 | use BrianHenryIE\Strauss\Config\ChangeEnumeratorConfigInterface; |
11 | use BrianHenryIE\Strauss\Files\FileWithDependency; |
12 | use BrianHenryIE\Strauss\Types\ClassSymbol; |
13 | use BrianHenryIE\Strauss\Types\DiscoveredSymbols; |
14 | use BrianHenryIE\Strauss\Types\FunctionSymbol; |
15 | use BrianHenryIE\Strauss\Types\NamespaceSymbol; |
16 | use League\Flysystem\FilesystemReader; |
17 | use Psr\Log\LoggerAwareTrait; |
18 | use Psr\Log\LoggerInterface; |
19 | use Psr\Log\NullLogger; |
20 | |
21 | class ChangeEnumerator |
22 | { |
23 | use LoggerAwareTrait; |
24 | |
25 | protected ChangeEnumeratorConfigInterface $config; |
26 | protected FilesystemReader $filesystem; |
27 | |
28 | public function __construct( |
29 | ChangeEnumeratorConfigInterface $config, |
30 | FilesystemReader $filesystem, |
31 | ?LoggerInterface $logger = null |
32 | ) { |
33 | $this->config = $config; |
34 | $this->filesystem = $filesystem; |
35 | $this->setLogger($logger ?? new NullLogger()); |
36 | } |
37 | |
38 | public function determineReplacements(DiscoveredSymbols $discoveredSymbols): void |
39 | { |
40 | |
41 | foreach ($discoveredSymbols->getSymbols() as $symbol) { |
42 | // TODO: this is a bit of a mess. Should be reconsidered. Previously there was 1-1 relationship between symbols and files. |
43 | $symbolSourceFiles = $symbol->getSourceFiles(); |
44 | $symbolSourceFile = $symbolSourceFiles[array_key_first($symbolSourceFiles)]; |
45 | if ($symbolSourceFile instanceof FileWithDependency) { |
46 | if (in_array( |
47 | $symbolSourceFile->getDependency()->getPackageName(), |
48 | $this->config->getExcludePackagesFromPrefixing(), |
49 | true |
50 | )) { |
51 | $symbolSourceFile->setDoPrefix(false); |
52 | continue; |
53 | } |
54 | |
55 | foreach ($this->config->getExcludeFilePatternsFromPrefixing() as $excludeFilePattern) { |
56 | // TODO: This source relative path should be from the vendor dir. |
57 | // TODO: Should the target path be used here? |
58 | if (1 === preg_match($excludeFilePattern, $symbolSourceFile->getSourcePath())) { |
59 | continue 2; |
60 | } |
61 | } |
62 | } |
63 | |
64 | if ($symbol instanceof NamespaceSymbol) { |
65 | $namespaceReplacementPatterns = $this->config->getNamespaceReplacementPatterns(); |
66 | |
67 | // `namespace_prefix` is just a shorthand for a replacement pattern that applies to all namespaces. |
68 | |
69 | // TODO: Maybe need to preg_quote and add regex delimiters to the patterns here. |
70 | foreach ($namespaceReplacementPatterns as $pattern => $replacement) { |
71 | if (substr($pattern, 0, 1) !== substr($pattern, -1, 1)) { |
72 | unset($namespaceReplacementPatterns[$pattern]); |
73 | $pattern = '~'. preg_quote($pattern, '~') . '~'; |
74 | $namespaceReplacementPatterns[$pattern] = $replacement; |
75 | } |
76 | unset($pattern, $replacement); |
77 | } |
78 | |
79 | if (!is_null($this->config->getNamespacePrefix())) { |
80 | $stripPattern = '~^('.preg_quote($this->config->getNamespacePrefix(), '~') .'\\\\*)*(.*)~'; |
81 | $strippedSymbol = preg_replace( |
82 | $stripPattern, |
83 | '$2', |
84 | $symbol->getOriginalSymbol() |
85 | ); |
86 | $namespaceReplacementPatterns[ "~(" . preg_quote($this->config->getNamespacePrefix(), '~') . '\\\\*)*' . preg_quote($strippedSymbol, '~') . '~' ] |
87 | = "{$this->config->getNamespacePrefix()}\\{$strippedSymbol}"; |
88 | unset($stripPattern, $strippedSymbol); |
89 | } |
90 | |
91 | // `namespace_replacement_patterns` should be ordered by priority. |
92 | foreach ($namespaceReplacementPatterns as $namespaceReplacementPattern => $replacement) { |
93 | $prefixed = preg_replace( |
94 | $namespaceReplacementPattern, |
95 | $replacement, |
96 | $symbol->getOriginalSymbol() |
97 | ); |
98 | |
99 | if ($prefixed !== $symbol->getOriginalSymbol()) { |
100 | $symbol->setReplacement($prefixed); |
101 | continue 2; |
102 | } |
103 | } |
104 | $this->logger->debug("Namespace {$symbol->getOriginalSymbol()} not changed."); |
105 | } |
106 | |
107 | if ($symbol instanceof ClassSymbol) { |
108 | // Don't double-prefix classnames. |
109 | if (str_starts_with($symbol->getOriginalSymbol(), $this->config->getClassmapPrefix())) { |
110 | continue; |
111 | } |
112 | |
113 | $symbol->setReplacement($this->config->getClassmapPrefix() . $symbol->getOriginalSymbol()); |
114 | } |
115 | |
116 | if ($symbol instanceof FunctionSymbol) { |
117 | // TODO: Add its own config option. |
118 | $functionPrefix = strtolower($this->config->getClassmapPrefix()); |
119 | if (str_starts_with($symbol->getOriginalSymbol(), $functionPrefix)) { |
120 | continue; |
121 | } |
122 | |
123 | $symbol->setReplacement($functionPrefix . $symbol->getOriginalSymbol()); |
124 | } |
125 | } |
126 | } |
127 | } |