Total Complexity | 45 |
Total Lines | 418 |
Duplicated Lines | 0 % |
Changes | 2 | ||
Bugs | 0 | Features | 0 |
Complex classes like PharInfoRenderer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PharInfoRenderer, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
53 | final class PharInfoRenderer |
||
54 | { |
||
55 | use NotInstantiable; |
||
56 | |||
57 | private const BOX_VERSION_PATTERN = '/ \* Generated by Humbug Box (?<version>.+)\.\s/'; |
||
58 | private const INDENT_SIZE = 2; |
||
59 | |||
60 | public static function renderShortSummary( |
||
61 | PharInfo $pharInfo, |
||
62 | IO $io, |
||
63 | ?Closure $separator = null, |
||
64 | ): void { |
||
65 | $separator ??= Noop::create(); |
||
66 | |||
67 | $methods = [ |
||
68 | self::renderCompression(...), |
||
69 | self::renderSignature(...), |
||
70 | self::renderMetadata(...), |
||
71 | self::renderTimestamp(...), |
||
72 | self::renderRequirementChecker(...), |
||
73 | self::renderContentsSummary(...), |
||
74 | ]; |
||
75 | |||
76 | $lastIndex = count($methods) - 1; |
||
77 | |||
78 | foreach ($methods as $index => $method) { |
||
79 | $method($pharInfo, $io); |
||
80 | |||
81 | if ($index !== $lastIndex) { |
||
82 | $separator(); |
||
83 | } |
||
84 | } |
||
85 | } |
||
86 | |||
87 | public static function renderVersion(PharInfo $pharInfo, IO $io): void |
||
88 | { |
||
89 | $io->writeln( |
||
90 | sprintf( |
||
91 | '<comment>API Version:</comment> %s', |
||
92 | $pharInfo->getVersion(), |
||
93 | ), |
||
94 | ); |
||
95 | } |
||
96 | |||
97 | public static function renderBoxVersion(PharInfo $pharInfo, IO $io): void |
||
98 | { |
||
99 | $version = self::extractBoxVersion($pharInfo); |
||
100 | |||
101 | if (null === $version) { |
||
102 | return; |
||
103 | } |
||
104 | |||
105 | $io->writeln( |
||
106 | sprintf( |
||
107 | '<comment>Built with Box:</comment> %s', |
||
108 | $version, |
||
109 | ), |
||
110 | ); |
||
111 | $io->newLine(); |
||
112 | } |
||
113 | |||
114 | public static function renderCompression(PharInfo $pharInfo, IO $io): void |
||
115 | { |
||
116 | $io->writeln( |
||
117 | sprintf( |
||
118 | '<comment>Archive Compression:</comment> %s', |
||
119 | self::translateCompressionAlgorithm($pharInfo->getCompression()), |
||
120 | ), |
||
121 | ); |
||
122 | |||
123 | $count = $pharInfo->getFilesCompressionCount(); |
||
124 | // Rename "none" to "None" |
||
125 | $count['None'] = $count[CompressionAlgorithm::NONE->name]; |
||
126 | unset($count[CompressionAlgorithm::NONE->name]); |
||
127 | $count = array_filter($count); |
||
128 | |||
129 | $totalCount = array_sum($count); |
||
130 | |||
131 | if (1 === count($count)) { |
||
132 | $io->writeln( |
||
133 | sprintf( |
||
134 | '<comment>Files Compression:</comment> %s', |
||
135 | key($count), |
||
136 | ), |
||
137 | ); |
||
138 | |||
139 | return; |
||
140 | } |
||
141 | |||
142 | $io->writeln('<comment>Files Compression:</comment>'); |
||
143 | $lastAlgorithmName = array_key_last($count); |
||
144 | |||
145 | $totalPercentage = 100; |
||
146 | |||
147 | foreach ($count as $algorithmName => $nbrOfFiles) { |
||
148 | if ($lastAlgorithmName === $algorithmName) { |
||
149 | $percentage = $totalPercentage; |
||
150 | } else { |
||
151 | $percentage = round($nbrOfFiles * 100 / $totalCount, 2); |
||
152 | |||
153 | $totalPercentage -= $percentage; |
||
154 | } |
||
155 | |||
156 | $io->writeln( |
||
157 | sprintf( |
||
158 | ' - %s (%0.2f%%)', |
||
159 | $algorithmName, |
||
160 | $percentage, |
||
161 | ), |
||
162 | ); |
||
163 | } |
||
164 | } |
||
165 | |||
166 | public static function renderSignature(PharInfo $pharInfo, IO $io): void |
||
167 | { |
||
168 | $signature = $pharInfo->getSignature(); |
||
169 | |||
170 | if (null === $signature) { |
||
171 | $io->writeln('<comment>Signature unreadable</comment>'); |
||
172 | |||
173 | return; |
||
174 | } |
||
175 | |||
176 | $io->writeln( |
||
177 | sprintf( |
||
178 | '<comment>Signature:</comment> %s', |
||
179 | $signature['hash_type'], |
||
180 | ), |
||
181 | ); |
||
182 | $io->writeln( |
||
183 | sprintf( |
||
184 | '<comment>Signature Hash:</comment> %s', |
||
185 | $signature['hash'], |
||
186 | ), |
||
187 | ); |
||
188 | } |
||
189 | |||
190 | public static function renderMetadata(PharInfo $pharInfo, IO $io): void |
||
191 | { |
||
192 | $metadata = $pharInfo->getNormalizedMetadata(); |
||
193 | |||
194 | if (null === $metadata) { |
||
195 | $io->writeln('<comment>Metadata:</comment> None'); |
||
196 | } else { |
||
197 | $io->writeln('<comment>Metadata:</comment>'); |
||
198 | $io->writeln($metadata); |
||
199 | } |
||
200 | } |
||
201 | |||
202 | public static function renderTimestamp(PharInfo $pharInfo, IO $io): void |
||
203 | { |
||
204 | $timestamp = $pharInfo->getTimestamp(); |
||
205 | $dateTime = (new DateTimeImmutable())->setTimestamp($timestamp); |
||
206 | |||
207 | $io->writeln( |
||
208 | sprintf( |
||
209 | '<comment>Timestamp:</comment> %s (%s)', |
||
210 | $timestamp, |
||
211 | $dateTime->format(DateTimeImmutable::ATOM), |
||
212 | ), |
||
213 | ); |
||
214 | } |
||
215 | |||
216 | public static function renderRequirementChecker( |
||
217 | PharInfo $pharInfo, |
||
218 | IO $io, |
||
219 | ): void { |
||
220 | try { |
||
221 | $requirements = $pharInfo->getRequirements(); |
||
222 | } catch (NoRequirementsFound) { |
||
223 | $io->writeln('<comment>RequirementChecker:</comment> Not found.'); |
||
224 | |||
225 | return; |
||
226 | } catch (InvalidRequirements) { |
||
227 | $io->writeln('<comment>RequirementChecker:</comment> Could not be checked.'); |
||
228 | |||
229 | return; |
||
230 | } |
||
231 | |||
232 | $io->write('<comment>RequirementChecker:</comment>'); |
||
233 | |||
234 | if (0 === count($requirements)) { |
||
235 | $io->writeln(' No requirement found.'); |
||
236 | |||
237 | return; |
||
238 | } |
||
239 | $io->writeln(''); |
||
240 | |||
241 | [$required, $conflicting] = self::retrieveRequirements($requirements); |
||
242 | |||
243 | self::renderRequiredSection($required, $io); |
||
244 | self::renderConflictingSection($conflicting, $io); |
||
245 | } |
||
246 | |||
247 | public static function renderContentsSummary(PharInfo $pharInfo, IO $io): void |
||
248 | { |
||
249 | $count = array_filter($pharInfo->getFilesCompressionCount()); |
||
250 | $totalCount = array_sum($count); |
||
251 | |||
252 | $io->writeln( |
||
253 | sprintf( |
||
254 | '<comment>Contents:</comment>%s (%s)', |
||
255 | 1 === $totalCount ? ' 1 file' : " {$totalCount} files", |
||
256 | format_size( |
||
257 | filesize($pharInfo->getFile()), |
||
258 | ), |
||
259 | ), |
||
260 | ); |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * @param false|positive-int|0 $maxDepth |
||
265 | * @param false|int $indent Nbr of indent or `false` |
||
266 | */ |
||
267 | public static function renderContent( |
||
311 | ); |
||
312 | } |
||
313 | } |
||
314 | |||
315 | private static function extractBoxVersion(PharInfo $pharInfo): ?string |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * @return array{Requirement[], Requirement[]} |
||
328 | */ |
||
329 | private static function retrieveRequirements(Requirements $requirements): array |
||
330 | { |
||
331 | [$required, $conflicting] = array_reduce( |
||
332 | toArray($requirements), |
||
333 | static function ($carry, Requirement $requirement): array { |
||
334 | $hash = implode( |
||
335 | ':', |
||
336 | [ |
||
337 | $requirement->type->value, |
||
338 | $requirement->condition, |
||
339 | $requirement->source, |
||
340 | ], |
||
341 | ); |
||
342 | |||
343 | if (RequirementType::EXTENSION_CONFLICT === $requirement->type) { |
||
344 | $carry[1][$hash] = $requirement; |
||
345 | } else { |
||
346 | $carry[0][$hash] = $requirement; |
||
347 | } |
||
348 | |||
349 | return $carry; |
||
350 | }, |
||
351 | [[], []], |
||
352 | ); |
||
353 | |||
354 | return [ |
||
355 | array_values($required), |
||
356 | array_values($conflicting), |
||
357 | ]; |
||
358 | } |
||
359 | |||
360 | /** |
||
361 | * @param Requirement[] $required |
||
362 | */ |
||
363 | private static function renderRequiredSection( |
||
387 | ), |
||
388 | ); |
||
389 | } |
||
390 | |||
391 | /** |
||
392 | * @param Requirement[] $conflicting |
||
393 | */ |
||
394 | private static function renderConflictingSection( |
||
395 | array $conflicting, |
||
396 | IO $io, |
||
397 | ): void { |
||
398 | if (0 === count($conflicting)) { |
||
399 | return; |
||
400 | } |
||
401 | |||
402 | $io->writeln(' <comment>Conflict:</comment>'); |
||
403 | $io->writeln( |
||
404 | array_map( |
||
405 | static fn (Requirement $requirement) => sprintf( |
||
406 | ' - ext-%s (%s)', |
||
407 | $requirement->condition, |
||
408 | $requirement->source ?? 'root', |
||
409 | ), |
||
410 | $conflicting, |
||
411 | ), |
||
412 | ); |
||
413 | } |
||
414 | |||
415 | private static function renderParentDirectoriesIfNecessary( |
||
453 | } |
||
454 | |||
455 | private static function print( |
||
456 | OutputInterface $output, |
||
457 | string $message, |
||
458 | int $depth, |
||
459 | bool $indent, |
||
460 | ): void { |
||
461 | if ($indent) { |
||
462 | $output->write(str_repeat(' ', $depth * self::INDENT_SIZE)); |
||
463 | } |
||
464 | |||
465 | $output->writeln($message); |
||
466 | } |
||
467 | |||
468 | private static function translateCompressionAlgorithm(CompressionAlgorithm $algorithm): string |
||
471 | } |
||
472 | } |
||
473 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths