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\Composer; |
||||
16 | |||||
17 | use Humbug\PhpScoper\Symbol\EnrichedReflector; |
||||
18 | use stdClass; |
||||
19 | use function array_map; |
||||
20 | use function array_merge; |
||||
21 | use function is_array; |
||||
22 | use function is_string; |
||||
23 | use function rtrim; |
||||
24 | use function Safe\sprintf; |
||||
25 | use function Safe\substr; |
||||
26 | use function str_replace; |
||||
27 | use function strpos; |
||||
28 | |||||
29 | /** |
||||
30 | * @private |
||||
31 | */ |
||||
32 | final class AutoloadPrefixer |
||||
33 | { |
||||
34 | private string $prefix; |
||||
35 | private EnrichedReflector $enrichedReflector; |
||||
36 | |||||
37 | 11 | public function __construct( |
|||
38 | string $prefix, |
||||
39 | 11 | EnrichedReflector $enrichedReflector |
|||
40 | 11 | ) { |
|||
41 | $this->prefix = $prefix; |
||||
42 | $this->enrichedReflector = $enrichedReflector; |
||||
43 | 11 | } |
|||
44 | 3 | ||||
45 | /** |
||||
46 | * @param stdClass $contents Decoded JSON |
||||
47 | 11 | * |
|||
48 | 1 | * @return stdClass Prefixed decoded JSON |
|||
49 | */ |
||||
50 | public function prefixPackageAutoloadStatements(stdClass $contents): stdClass |
||||
51 | 11 | { |
|||
52 | if (isset($contents->autoload)) { |
||||
53 | $contents->autoload = self::prefixAutoloadStatements( |
||||
54 | 11 | $contents->autoload, |
|||
55 | $this->prefix, |
||||
56 | 11 | $this->enrichedReflector, |
|||
57 | 1 | ); |
|||
58 | } |
||||
59 | |||||
60 | 10 | if (isset($contents->{'autoload-dev'})) { |
|||
61 | 7 | $contents->{'autoload-dev'} = self::prefixAutoloadStatements( |
|||
62 | 7 | $contents->{'autoload-dev'}, |
|||
63 | 7 | $this->prefix, |
|||
64 | 7 | $this->enrichedReflector, |
|||
65 | ); |
||||
66 | } |
||||
67 | 7 | ||||
68 | 2 | if (isset($contents->extra->laravel->providers)) { |
|||
69 | $contents->extra->laravel->providers = self::prefixLaravelProviders( |
||||
70 | 5 | $contents->extra->laravel->providers, |
|||
71 | $this->prefix, |
||||
72 | $this->enrichedReflector, |
||||
73 | 7 | ); |
|||
74 | 5 | } |
|||
75 | |||||
76 | 2 | return $contents; |
|||
77 | } |
||||
78 | |||||
79 | 10 | private static function prefixAutoloadStatements( |
|||
80 | stdClass $autoload, |
||||
81 | 10 | string $prefix, |
|||
82 | 8 | EnrichedReflector $enrichedReflector |
|||
83 | ): stdClass { |
||||
84 | if (!isset($autoload->{'psr-4'}) && !isset($autoload->{'psr-0'})) { |
||||
85 | 10 | return $autoload; |
|||
86 | } |
||||
87 | |||||
88 | 8 | if (isset($autoload->{'psr-0'})) { |
|||
89 | [$psr4, $classMap] = self::transformPsr0ToPsr4AndClassmap( |
||||
90 | 8 | (array) $autoload->{'psr-0'}, |
|||
91 | (array) ($autoload->{'psr-4'} ?? new stdClass()), |
||||
92 | 8 | (array) ($autoload->{'classmap'} ?? new stdClass()), |
|||
93 | 8 | ); |
|||
94 | |||||
95 | 8 | if ([] === $psr4) { |
|||
96 | unset($autoload->{'psr-4'}); |
||||
97 | } else { |
||||
98 | 8 | $autoload->{'psr-4'} = $psr4; |
|||
99 | } |
||||
100 | |||||
101 | 8 | if ([] === $classMap) { |
|||
102 | unset($autoload->{'classmap'}); |
||||
103 | } else { |
||||
104 | $autoload->{'classmap'} = $classMap; |
||||
105 | } |
||||
106 | } |
||||
107 | unset($autoload->{'psr-0'}); |
||||
108 | |||||
109 | 7 | if (isset($autoload->{'psr-4'})) { |
|||
110 | $autoload->{'psr-4'} = self::prefixAutoload( |
||||
111 | 7 | (array) $autoload->{'psr-4'}, |
|||
112 | $prefix, |
||||
113 | 7 | $enrichedReflector, |
|||
114 | 3 | ); |
|||
115 | } |
||||
116 | |||||
117 | 7 | return $autoload; |
|||
118 | 2 | } |
|||
119 | |||||
120 | 2 | private static function prefixAutoload( |
|||
121 | array $autoload, |
||||
122 | string $prefix, |
||||
123 | 5 | EnrichedReflector $enrichedReflector |
|||
124 | ): array { |
||||
125 | 5 | $loader = []; |
|||
126 | 2 | ||||
127 | foreach ($autoload as $namespace => $paths) { |
||||
128 | 2 | $newNamespace = $enrichedReflector->isExcludedNamespace($namespace) |
|||
129 | ? $namespace |
||||
130 | : sprintf('%s\\%s', $prefix, $namespace); |
||||
0 ignored issues
–
show
|
|||||
131 | 3 | ||||
132 | $loader[$newNamespace] = $paths; |
||||
133 | } |
||||
134 | 7 | ||||
135 | return $loader; |
||||
136 | } |
||||
137 | |||||
138 | /** |
||||
139 | * @param array<string, (string|string[])> $psr0 |
||||
140 | * @param (string|string[])[] $psr4 |
||||
141 | * @param string[] $classMap |
||||
142 | 5 | */ |
|||
143 | private static function transformPsr0ToPsr4AndClassmap(array $psr0, array $psr4, array $classMap): array |
||||
144 | 5 | { |
|||
145 | 5 | foreach ($psr0 as $namespace => $path) { |
|||
146 | 5 | // Append backslashes, if needed, since psr-0 does not require this |
|||
147 | if ('\\' !== substr($namespace, -1)) { |
||||
0 ignored issues
–
show
The function
Safe\substr() has been deprecated: The Safe version of this function is no longer needed in PHP 8.0+
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
148 | $namespace .= '\\'; |
||||
149 | 5 | } |
|||
150 | 4 | ||||
151 | 1 | if (false !== strpos($namespace, '_')) { |
|||
152 | $classMap[] = $path; |
||||
153 | |||||
154 | 4 | continue; |
|||
155 | } |
||||
156 | 4 | ||||
157 | $path = self::updatePSR0Path($path, $namespace); |
||||
158 | |||||
159 | 2 | if (!isset($psr4[$namespace])) { |
|||
160 | 2 | $psr4[$namespace] = $path; |
|||
161 | 1 | ||||
162 | continue; |
||||
163 | } |
||||
164 | 2 | ||||
165 | 2 | $psr4[$namespace] = self::mergeNamespaces($namespace, $path, $psr4); |
|||
166 | } |
||||
167 | |||||
168 | 2 | return [$psr4, $classMap]; |
|||
169 | } |
||||
170 | |||||
171 | /** |
||||
172 | * @param string|string[] $path |
||||
173 | * |
||||
174 | * @return string|string[] |
||||
175 | */ |
||||
176 | private static function updatePSR0Path($path, string $namespace) |
||||
177 | { |
||||
178 | $namespaceForPsr = rtrim( |
||||
179 | str_replace('\\', '/', $namespace), |
||||
180 | '/', |
||||
181 | ); |
||||
182 | |||||
183 | if (!is_array($path)) { |
||||
184 | 3 | if ('/' !== substr($path, -1)) { |
|||
0 ignored issues
–
show
The function
Safe\substr() has been deprecated: The Safe version of this function is no longer needed in PHP 8.0+
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
185 | $path .= '/'; |
||||
186 | } |
||||
187 | 3 | ||||
188 | 1 | $path .= $namespaceForPsr.'/'; |
|||
189 | |||||
190 | return $path; |
||||
191 | } |
||||
192 | 2 | ||||
193 | 1 | foreach ($path as $key => $item) { |
|||
194 | if ('/' !== substr($item, -1)) { |
||||
0 ignored issues
–
show
The function
Safe\substr() has been deprecated: The Safe version of this function is no longer needed in PHP 8.0+
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
195 | 1 | $item .= '/'; |
|||
196 | } |
||||
197 | |||||
198 | $item .= $namespaceForPsr.'/'; |
||||
199 | 2 | $path[$key] = $item; |
|||
200 | 1 | } |
|||
201 | |||||
202 | 1 | return $path; |
|||
203 | } |
||||
204 | |||||
205 | 1 | /** |
|||
206 | 1 | * Deals with the 4 possible scenarios: |
|||
207 | * PSR0 | PSR4 |
||||
208 | * array | |
||||
209 | * string | |
||||
210 | * or simply the namespace not existing as a psr-4 entry. |
||||
211 | * |
||||
212 | 1 | * @param string|string[] $psr0Path |
|||
213 | * @param (string|string[])[] $psr4 |
||||
214 | 1 | * |
|||
215 | * @return string|string[] |
||||
216 | 1 | */ |
|||
217 | private static function mergeNamespaces(string $psr0Namespace, $psr0Path, array $psr4) |
||||
218 | 1 | { |
|||
219 | // Both strings |
||||
220 | 1 | if (is_string($psr0Path) && is_string($psr4[$psr0Namespace])) { |
|||
221 | 1 | return [$psr4[$psr0Namespace], $psr0Path]; |
|||
222 | } |
||||
223 | |||||
224 | // PSR-4 is string, and PSR-0 is array |
||||
225 | if (is_array($psr0Path) && is_string($psr4[$psr0Namespace])) { |
||||
226 | $psr0Path[] = $psr4[$psr0Namespace]; |
||||
227 | |||||
228 | return $psr0Path; |
||||
0 ignored issues
–
show
|
|||||
229 | } |
||||
230 | |||||
231 | // PSR-4 is array and PSR-0 is string |
||||
232 | if (is_string($psr0Path) && is_array($psr4[$psr0Namespace])) { |
||||
233 | $psr4[$psr0Namespace][] = $psr0Path; |
||||
234 | |||||
235 | return $psr4[$psr0Namespace]; |
||||
236 | } |
||||
237 | |||||
238 | if (is_array($psr0Path) && is_array($psr4[$psr0Namespace])) { |
||||
239 | return array_merge($psr4[$psr0Namespace], $psr0Path); |
||||
0 ignored issues
–
show
It seems like
$psr4[$psr0Namespace] can also be of type string ; however, parameter $arrays of array_merge() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
240 | } |
||||
241 | |||||
242 | return $psr0Path; |
||||
243 | } |
||||
244 | |||||
245 | private static function prefixLaravelProviders( |
||||
246 | array $providers, |
||||
247 | string $prefix, |
||||
248 | EnrichedReflector $enrichedReflector |
||||
249 | ): array { |
||||
250 | return array_map( |
||||
251 | static fn (string $provider) => $enrichedReflector->isExcludedNamespace($provider) |
||||
252 | ? $provider |
||||
253 | : sprintf('%s\\%s', $prefix, $provider), |
||||
0 ignored issues
–
show
The function
Safe\sprintf() has been deprecated: The Safe version of this function is no longer needed in PHP 8.0+
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
254 | $providers, |
||||
255 | ); |
||||
256 | } |
||||
257 | } |
||||
258 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.