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\Console\Command; |
||||
16 | |||||
17 | use Fidry\Console\Command\Command; |
||||
18 | use Fidry\Console\Command\CommandRegistry; |
||||
19 | use Fidry\Console\Command\Configuration as CommandConfiguration; |
||||
20 | use Fidry\Console\ExitCode; |
||||
21 | use Fidry\Console\Input\IO; |
||||
22 | use Humbug\PhpScoper\Configuration\Configuration; |
||||
23 | use Humbug\PhpScoper\Configuration\ConfigurationFactory; |
||||
24 | use Humbug\PhpScoper\Console\ConfigLoader; |
||||
25 | use Humbug\PhpScoper\Symbol\EnrichedReflector; |
||||
26 | use Humbug\PhpScoper\Symbol\EnrichedReflectorFactory; |
||||
27 | use InvalidArgumentException; |
||||
28 | use Symfony\Component\Console\Application as DummyApplication; |
||||
29 | use Symfony\Component\Console\Input\InputArgument; |
||||
30 | use Symfony\Component\Console\Input\InputOption; |
||||
31 | use Symfony\Component\Console\Output\NullOutput; |
||||
32 | use Symfony\Component\Filesystem\Filesystem; |
||||
33 | use Symfony\Component\Filesystem\Path; |
||||
34 | use function assert; |
||||
35 | use function file_exists; |
||||
36 | use function implode; |
||||
37 | use function Safe\getcwd; |
||||
38 | use function Safe\sprintf; |
||||
39 | use const DIRECTORY_SEPARATOR; |
||||
40 | |||||
41 | /** |
||||
42 | * @private |
||||
43 | */ |
||||
44 | final class InspectSymbolCommand implements Command |
||||
45 | { |
||||
46 | private const SYMBOL_ARG = 'symbol'; |
||||
47 | private const SYMBOL_TYPE_ARG = 'type'; |
||||
48 | private const CONFIG_FILE_OPT = 'config'; |
||||
49 | private const NO_CONFIG_OPT = 'no-config'; |
||||
50 | |||||
51 | private Filesystem $fileSystem; |
||||
52 | private ConfigurationFactory $configFactory; |
||||
53 | private EnrichedReflectorFactory $enrichedReflectorFactory; |
||||
54 | |||||
55 | public function __construct( |
||||
56 | Filesystem $fileSystem, |
||||
57 | ConfigurationFactory $configFactory, |
||||
58 | EnrichedReflectorFactory $enrichedReflectorFactory |
||||
59 | ) { |
||||
60 | $this->fileSystem = $fileSystem; |
||||
61 | $this->configFactory = $configFactory; |
||||
62 | $this->enrichedReflectorFactory = $enrichedReflectorFactory; |
||||
63 | } |
||||
64 | |||||
65 | public function getConfiguration(): CommandConfiguration |
||||
66 | { |
||||
67 | return new CommandConfiguration( |
||||
68 | 'inspect-symbol', |
||||
69 | 'Checks the given symbol for a given configuration. Helpful to have an insight on how PHP-Scoper will interpret this symbol', |
||||
70 | '', |
||||
71 | [ |
||||
72 | new InputArgument( |
||||
73 | self::SYMBOL_ARG, |
||||
74 | InputArgument::REQUIRED, |
||||
75 | 'The symbol to inspect.', |
||||
76 | ), |
||||
77 | new InputArgument( |
||||
78 | self::SYMBOL_TYPE_ARG, |
||||
79 | InputArgument::OPTIONAL, |
||||
80 | sprintf( |
||||
0 ignored issues
–
show
|
|||||
81 | 'The symbol type inspect ("%s").', |
||||
82 | implode('", "', SymbolType::ALL), |
||||
83 | ), |
||||
84 | SymbolType::ANY_TYPE, |
||||
85 | ), |
||||
86 | ], |
||||
87 | [ |
||||
88 | ChangeableDirectory::createOption(), |
||||
89 | new InputOption( |
||||
90 | self::CONFIG_FILE_OPT, |
||||
91 | 'c', |
||||
92 | InputOption::VALUE_REQUIRED, |
||||
93 | sprintf( |
||||
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. ![]() |
|||||
94 | 'Configuration file. Will use "%s" if found by default.', |
||||
95 | ConfigurationFactory::DEFAULT_FILE_NAME, |
||||
96 | ), |
||||
97 | ), |
||||
98 | new InputOption( |
||||
99 | self::NO_CONFIG_OPT, |
||||
100 | null, |
||||
101 | InputOption::VALUE_NONE, |
||||
102 | 'Do not look for a configuration file.', |
||||
103 | ), |
||||
104 | ], |
||||
105 | ); |
||||
106 | } |
||||
107 | |||||
108 | public function execute(IO $io): int |
||||
109 | { |
||||
110 | $io->newLine(); |
||||
111 | |||||
112 | ChangeableDirectory::changeWorkingDirectory($io); |
||||
113 | |||||
114 | // Only get current working directory _after_ we changed to the desired |
||||
115 | // working directory |
||||
116 | $cwd = getcwd(); |
||||
117 | |||||
118 | $symbol = $io->getArgument(self::SYMBOL_ARG)->asString(); |
||||
119 | /** @var SymbolType::*_TYPE $symbolType */ |
||||
120 | $symbolType = $io->getArgument(self::SYMBOL_TYPE_ARG)->asStringChoice(SymbolType::ALL); |
||||
121 | $config = $this->retrieveConfig($io, $cwd); |
||||
122 | |||||
123 | $enrichedReflector = $this->enrichedReflectorFactory->create( |
||||
124 | $config->getSymbolsConfiguration(), |
||||
125 | ); |
||||
126 | |||||
127 | self::printSymbol( |
||||
128 | $io, |
||||
129 | $symbol, |
||||
130 | $symbolType, |
||||
131 | $config->getPath(), |
||||
132 | $enrichedReflector, |
||||
133 | ); |
||||
134 | |||||
135 | return ExitCode::SUCCESS; |
||||
136 | } |
||||
137 | |||||
138 | private function retrieveConfig(IO $io, string $cwd): Configuration |
||||
139 | { |
||||
140 | $configLoader = new ConfigLoader( |
||||
141 | new CommandRegistry(new DummyApplication()), |
||||
142 | $this->fileSystem, |
||||
143 | $this->configFactory, |
||||
144 | ); |
||||
145 | |||||
146 | $configFilePath = $this->getConfigFilePath($io, $cwd); |
||||
147 | $noConfig = $io->getOption(self::NO_CONFIG_OPT)->asBoolean(); |
||||
148 | |||||
149 | if (null === $configFilePath) { |
||||
150 | // Unlike when scoping, we do not want a config file to be created |
||||
151 | // neither bother the user with passing the no-config option if the |
||||
152 | // file does not exist. |
||||
153 | $noConfig = true; |
||||
154 | } |
||||
155 | |||||
156 | return $configLoader->loadConfig( |
||||
157 | new IO( |
||||
158 | $io->getInput(), |
||||
159 | new NullOutput(), |
||||
160 | ), |
||||
161 | '', |
||||
162 | $noConfig, |
||||
163 | $configFilePath, |
||||
164 | ConfigurationFactory::DEFAULT_FILE_NAME, |
||||
165 | // We do not want the init command to be triggered if there is no |
||||
166 | // config file. |
||||
167 | true, |
||||
168 | [], |
||||
169 | getcwd(), |
||||
170 | ); |
||||
171 | } |
||||
172 | |||||
173 | /** |
||||
174 | * @return non-empty-string|null |
||||
0 ignored issues
–
show
|
|||||
175 | */ |
||||
176 | private function getConfigFilePath(IO $io, string $cwd): ?string |
||||
177 | { |
||||
178 | $configPath = (string) $io->getOption(self::CONFIG_FILE_OPT)->asNullableString(); |
||||
179 | |||||
180 | if ('' === $configPath) { |
||||
181 | $configPath = ConfigurationFactory::DEFAULT_FILE_NAME; |
||||
182 | } |
||||
183 | |||||
184 | $configPath = $this->canonicalizePath($configPath, $cwd); |
||||
185 | |||||
186 | return file_exists($configPath) ? $configPath : null; |
||||
187 | } |
||||
188 | |||||
189 | /** |
||||
190 | * @param SymbolType::*_TYPE $type |
||||
0 ignored issues
–
show
|
|||||
191 | */ |
||||
192 | private static function printSymbol( |
||||
193 | IO $io, |
||||
194 | string $symbol, |
||||
195 | string $type, |
||||
196 | ?string $configPath, |
||||
197 | EnrichedReflector $reflector |
||||
198 | ): void { |
||||
199 | self::printDocBlock($io); |
||||
200 | self::printConfigLoaded($io, $configPath); |
||||
201 | self::printInspectionHeadline($io, $symbol, $type); |
||||
202 | |||||
203 | $io->newLine(); |
||||
204 | |||||
205 | if (!(SymbolType::ANY_TYPE === $type)) { |
||||
206 | self::printTypedSymbol($io, $symbol, $type, $reflector); |
||||
207 | } else { |
||||
208 | self::printAnyTypeSymbol($io, $symbol, $reflector); |
||||
209 | } |
||||
210 | } |
||||
211 | |||||
212 | private static function printDocBlock(IO $io): void |
||||
213 | { |
||||
214 | $io->writeln([ |
||||
215 | 'Internal (configured via the `excluded-*` settings) are treated as PHP native symbols, i.e. will remain untouched.', |
||||
216 | 'Exposed symbols (configured via the `expose-*` settings) will be prefixed but aliased to its original symbol.', |
||||
217 | 'If a symbol is neither internal or exposed, it will be prefixed and not aliased', |
||||
218 | '', |
||||
219 | 'For more information, see:', |
||||
220 | ]); |
||||
221 | $io->listing([ |
||||
222 | '<href=https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#excluded-symbols>Doc link for excluded symbols</>', |
||||
223 | '<href=https://github.com/humbug/php-scoper/blob/master/docs/configuration.md#exposed-symbols>Doc link for exposed symbols</>', |
||||
224 | ]); |
||||
225 | } |
||||
226 | |||||
227 | private static function printConfigLoaded(IO $io, ?string $configPath): void |
||||
228 | { |
||||
229 | $io->writeln( |
||||
230 | null === $configPath |
||||
231 | ? 'No configuration loaded.' |
||||
232 | : sprintf( |
||||
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. ![]() |
|||||
233 | 'Loaded the configuration <comment>%s</comment>', |
||||
234 | $configPath, |
||||
235 | ), |
||||
236 | ); |
||||
237 | $io->newLine(); |
||||
238 | } |
||||
239 | |||||
240 | /** |
||||
241 | * @param SymbolType::*_TYPE $type |
||||
0 ignored issues
–
show
|
|||||
242 | */ |
||||
243 | private static function printInspectionHeadline( |
||||
244 | IO $io, |
||||
245 | string $symbol, |
||||
246 | string $type |
||||
247 | ): void { |
||||
248 | $io->writeln( |
||||
249 | sprintf( |
||||
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. ![]() |
|||||
250 | 'Inspecting the symbol <comment>%s</comment> %s', |
||||
251 | $symbol, |
||||
252 | SymbolType::ANY_TYPE === $type |
||||
253 | ? 'for all types.' |
||||
254 | : sprintf('for type <comment>%s</comment>:', $type), |
||||
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. ![]() |
|||||
255 | ), |
||||
256 | ); |
||||
257 | } |
||||
258 | |||||
259 | private static function printAnyTypeSymbol( |
||||
260 | IO $io, |
||||
261 | string $symbol, |
||||
262 | EnrichedReflector $reflector |
||||
263 | ): void { |
||||
264 | foreach (SymbolType::getAllSpecificTypes() as $specificType) { |
||||
265 | $io->writeln( |
||||
266 | sprintf( |
||||
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. ![]() |
|||||
267 | 'As a <comment>%s</comment>:', |
||||
268 | $specificType, |
||||
269 | ), |
||||
270 | ); |
||||
271 | |||||
272 | self::printTypedSymbol($io, $symbol, $specificType, $reflector); |
||||
273 | } |
||||
274 | } |
||||
275 | |||||
276 | /** |
||||
277 | * @param SymbolType::*_TYPE $type |
||||
0 ignored issues
–
show
|
|||||
278 | */ |
||||
279 | private static function printTypedSymbol( |
||||
280 | IO $io, |
||||
281 | string $symbol, |
||||
282 | string $type, |
||||
283 | EnrichedReflector $reflector |
||||
284 | ): void { |
||||
285 | [$internal, $exposed] = self::determineSymbolStatus( |
||||
286 | $symbol, |
||||
287 | $type, |
||||
288 | $reflector, |
||||
289 | ); |
||||
290 | |||||
291 | $io->listing([ |
||||
292 | sprintf( |
||||
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. ![]() |
|||||
293 | 'Internal: %s', |
||||
294 | self::convertBoolToString($internal), |
||||
295 | ), |
||||
296 | sprintf( |
||||
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. ![]() |
|||||
297 | 'Exposed: %s', |
||||
298 | self::convertBoolToString($exposed), |
||||
299 | ), |
||||
300 | ]); |
||||
301 | } |
||||
302 | |||||
303 | /** |
||||
304 | * @param SymbolType::*_TYPE $type |
||||
0 ignored issues
–
show
|
|||||
305 | */ |
||||
306 | private static function determineSymbolStatus( |
||||
307 | string $symbol, |
||||
308 | string $type, |
||||
309 | EnrichedReflector $reflector |
||||
310 | ): array { |
||||
311 | switch ($type) { |
||||
312 | case SymbolType::CLASS_TYPE: |
||||
313 | return [ |
||||
314 | $reflector->isClassInternal($symbol), |
||||
315 | $reflector->isExposedClass($symbol), |
||||
316 | ]; |
||||
317 | |||||
318 | case SymbolType::FUNCTION_TYPE: |
||||
319 | return [ |
||||
320 | $reflector->isFunctionInternal($symbol), |
||||
321 | $reflector->isExposedFunction($symbol), |
||||
322 | ]; |
||||
323 | |||||
324 | case SymbolType::CONSTANT_TYPE: |
||||
325 | return [ |
||||
326 | $reflector->isConstantInternal($symbol), |
||||
327 | $reflector->isExposedConstant($symbol), |
||||
328 | ]; |
||||
329 | } |
||||
330 | |||||
331 | throw new InvalidArgumentException( |
||||
332 | sprintf( |
||||
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. ![]() |
|||||
333 | 'Invalid type "%s"', |
||||
334 | $type, |
||||
335 | ), |
||||
336 | ); |
||||
337 | } |
||||
338 | |||||
339 | private static function convertBoolToString(bool $bool): string |
||||
340 | { |
||||
341 | return true === $bool ? '<question>true</question>' : '<error>false</error>'; |
||||
342 | } |
||||
343 | |||||
344 | /** |
||||
345 | * @param non-empty-string $path |
||||
0 ignored issues
–
show
|
|||||
346 | * |
||||
347 | * @return non-empty-string Absolute canonical path |
||||
0 ignored issues
–
show
|
|||||
348 | */ |
||||
349 | private function canonicalizePath(string $path, string $cwd): string |
||||
350 | { |
||||
351 | $canonicalPath = Path::canonicalize( |
||||
352 | $this->fileSystem->isAbsolutePath($path) |
||||
353 | ? $path |
||||
354 | : $cwd.DIRECTORY_SEPARATOR.$path, |
||||
355 | ); |
||||
356 | |||||
357 | assert('' !== $canonicalPath); |
||||
358 | |||||
359 | return $canonicalPath; |
||||
360 | } |
||||
361 | } |
||||
362 |
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.