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); |
|
|
|
|
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)) { |
|
|
|
|
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)) { |
|
|
|
|
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)) { |
|
|
|
|
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; |
|
|
|
|
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); |
|
|
|
|
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), |
|
|
|
|
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.