Total Complexity | 131 |
Total Lines | 821 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like ConfigurationResolver 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 ConfigurationResolver, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
57 | final class ConfigurationResolver |
||
58 | { |
||
59 | public const PATH_MODE_OVERRIDE = 'override'; |
||
60 | public const PATH_MODE_INTERSECTION = 'intersection'; |
||
61 | |||
62 | /** |
||
63 | * @var null|bool |
||
64 | */ |
||
65 | private $allowRisky; |
||
66 | |||
67 | /** |
||
68 | * @var null|ConfigInterface |
||
69 | */ |
||
70 | private $config; |
||
71 | |||
72 | /** |
||
73 | * @var null|string |
||
74 | */ |
||
75 | private $configFile; |
||
76 | |||
77 | /** |
||
78 | * @var string |
||
79 | */ |
||
80 | private $cwd; |
||
81 | |||
82 | /** |
||
83 | * @var ConfigInterface |
||
84 | */ |
||
85 | private $defaultConfig; |
||
86 | |||
87 | /** |
||
88 | * @var null|ReporterInterface |
||
89 | */ |
||
90 | private $reporter; |
||
91 | |||
92 | /** |
||
93 | * @var null|bool |
||
94 | */ |
||
95 | private $isStdIn; |
||
96 | |||
97 | /** |
||
98 | * @var null|bool |
||
99 | */ |
||
100 | private $isDryRun; |
||
101 | |||
102 | /** |
||
103 | * @var null|FixerInterface[] |
||
104 | */ |
||
105 | private $fixers; |
||
106 | |||
107 | /** |
||
108 | * @var null|bool |
||
109 | */ |
||
110 | private $configFinderIsOverridden; |
||
111 | |||
112 | /** |
||
113 | * @var ToolInfoInterface |
||
114 | */ |
||
115 | private $toolInfo; |
||
116 | |||
117 | /** |
||
118 | * @var array |
||
119 | */ |
||
120 | private $options = [ |
||
121 | 'allow-risky' => null, |
||
122 | 'cache-file' => null, |
||
123 | 'config' => null, |
||
124 | 'diff' => null, |
||
125 | 'dry-run' => null, |
||
126 | 'format' => null, |
||
127 | 'path' => [], |
||
128 | 'path-mode' => self::PATH_MODE_OVERRIDE, |
||
129 | 'rules' => null, |
||
130 | 'show-progress' => null, |
||
131 | 'stop-on-violation' => null, |
||
132 | 'using-cache' => null, |
||
133 | 'verbosity' => null, |
||
134 | ]; |
||
135 | |||
136 | private $cacheFile; |
||
137 | |||
138 | /** |
||
139 | * @var null|CacheManagerInterface |
||
140 | */ |
||
141 | private $cacheManager; |
||
142 | |||
143 | /** |
||
144 | * @var null|DifferInterface |
||
145 | */ |
||
146 | private $differ; |
||
147 | |||
148 | /** |
||
149 | * @var null|Directory |
||
150 | */ |
||
151 | private $directory; |
||
152 | |||
153 | /** |
||
154 | * @var null|iterable |
||
155 | */ |
||
156 | private $finder; |
||
157 | |||
158 | private $format; |
||
159 | |||
160 | /** |
||
161 | * @var null|Linter |
||
162 | */ |
||
163 | private $linter; |
||
164 | |||
165 | private $path; |
||
166 | |||
167 | /** |
||
168 | * @var null|string |
||
169 | */ |
||
170 | private $progress; |
||
171 | |||
172 | /** |
||
173 | * @var null|RuleSet |
||
174 | */ |
||
175 | private $ruleSet; |
||
176 | |||
177 | /** |
||
178 | * @var null|bool |
||
179 | */ |
||
180 | private $usingCache; |
||
181 | |||
182 | /** |
||
183 | * @var FixerFactory |
||
184 | */ |
||
185 | private $fixerFactory; |
||
186 | |||
187 | public function __construct( |
||
188 | ConfigInterface $config, |
||
189 | array $options, |
||
190 | string $cwd, |
||
191 | ToolInfoInterface $toolInfo |
||
192 | ) { |
||
193 | $this->cwd = $cwd; |
||
194 | $this->defaultConfig = $config; |
||
195 | $this->toolInfo = $toolInfo; |
||
196 | |||
197 | foreach ($options as $name => $value) { |
||
198 | $this->setOption($name, $value); |
||
199 | } |
||
200 | } |
||
201 | |||
202 | public function getCacheFile(): ?string |
||
203 | { |
||
204 | if (!$this->getUsingCache()) { |
||
205 | return null; |
||
206 | } |
||
207 | |||
208 | if (null === $this->cacheFile) { |
||
209 | if (null === $this->options['cache-file']) { |
||
210 | $this->cacheFile = $this->getConfig()->getCacheFile(); |
||
211 | } else { |
||
212 | $this->cacheFile = $this->options['cache-file']; |
||
213 | } |
||
214 | } |
||
215 | |||
216 | return $this->cacheFile; |
||
217 | } |
||
218 | |||
219 | public function getCacheManager(): CacheManagerInterface |
||
220 | { |
||
221 | if (null === $this->cacheManager) { |
||
222 | $cacheFile = $this->getCacheFile(); |
||
223 | |||
224 | if (null === $cacheFile) { |
||
225 | $this->cacheManager = new NullCacheManager(); |
||
226 | } else { |
||
227 | $this->cacheManager = new FileCacheManager( |
||
228 | new FileHandler($cacheFile), |
||
229 | new Signature( |
||
230 | PHP_VERSION, |
||
231 | $this->toolInfo->getVersion(), |
||
232 | $this->getConfig()->getIndent(), |
||
233 | $this->getConfig()->getLineEnding(), |
||
234 | $this->getRules() |
||
235 | ), |
||
236 | $this->isDryRun(), |
||
237 | $this->getDirectory() |
||
238 | ); |
||
239 | } |
||
240 | } |
||
241 | |||
242 | return $this->cacheManager; |
||
243 | } |
||
244 | |||
245 | public function getConfig(): ConfigInterface |
||
246 | { |
||
247 | if (null === $this->config) { |
||
248 | foreach ($this->computeConfigFiles() as $configFile) { |
||
249 | if (!file_exists($configFile)) { |
||
250 | continue; |
||
251 | } |
||
252 | |||
253 | $configFileBasename = basename($configFile); |
||
254 | $deprecatedConfigs = [ |
||
255 | '.php_cs' => '.php-cs-fixer.php', |
||
256 | '.php_cs.dist' => '.php-cs-fixer.dist.php', |
||
257 | ]; |
||
258 | |||
259 | if (isset($deprecatedConfigs[$configFileBasename])) { |
||
260 | throw new InvalidConfigurationException("Configuration file `{$configFileBasename}` is outdated, rename to `{$deprecatedConfigs[$configFileBasename]}`."); |
||
261 | } |
||
262 | |||
263 | $this->config = self::separatedContextLessInclude($configFile); |
||
264 | $this->configFile = $configFile; |
||
265 | |||
266 | break; |
||
267 | } |
||
268 | |||
269 | if (null === $this->config) { |
||
270 | $this->config = $this->defaultConfig; |
||
271 | } |
||
272 | } |
||
273 | |||
274 | return $this->config; |
||
275 | } |
||
276 | |||
277 | public function getConfigFile(): ?string |
||
278 | { |
||
279 | if (null === $this->configFile) { |
||
280 | $this->getConfig(); |
||
281 | } |
||
282 | |||
283 | return $this->configFile; |
||
284 | } |
||
285 | |||
286 | public function getDiffer(): DifferInterface |
||
287 | { |
||
288 | if (null === $this->differ) { |
||
289 | if ($this->options['diff']) { |
||
290 | $this->differ = new UnifiedDiffer(); |
||
291 | } else { |
||
292 | $this->differ = new NullDiffer(); |
||
293 | } |
||
294 | } |
||
295 | |||
296 | return $this->differ; |
||
297 | } |
||
298 | |||
299 | public function getDirectory(): DirectoryInterface |
||
300 | { |
||
301 | if (null === $this->directory) { |
||
302 | $path = $this->getCacheFile(); |
||
303 | if (null === $path) { |
||
304 | $absolutePath = $this->cwd; |
||
305 | } else { |
||
306 | $filesystem = new Filesystem(); |
||
307 | |||
308 | $absolutePath = $filesystem->isAbsolutePath($path) |
||
309 | ? $path |
||
310 | : $this->cwd.\DIRECTORY_SEPARATOR.$path; |
||
311 | } |
||
312 | |||
313 | $this->directory = new Directory(\dirname($absolutePath)); |
||
314 | } |
||
315 | |||
316 | return $this->directory; |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * @return FixerInterface[] An array of FixerInterface |
||
321 | */ |
||
322 | public function getFixers(): array |
||
323 | { |
||
324 | if (null === $this->fixers) { |
||
325 | $this->fixers = $this->createFixerFactory() |
||
326 | ->useRuleSet($this->getRuleSet()) |
||
327 | ->setWhitespacesConfig(new WhitespacesFixerConfig($this->config->getIndent(), $this->config->getLineEnding())) |
||
|
|||
328 | ->getFixers() |
||
329 | ; |
||
330 | |||
331 | if (false === $this->getRiskyAllowed()) { |
||
332 | $riskyFixers = array_map( |
||
333 | static function (FixerInterface $fixer) { |
||
334 | return $fixer->getName(); |
||
335 | }, |
||
336 | array_filter( |
||
337 | $this->fixers, |
||
338 | static function (FixerInterface $fixer) { |
||
339 | return $fixer->isRisky(); |
||
340 | } |
||
341 | ) |
||
342 | ); |
||
343 | |||
344 | if (\count($riskyFixers)) { |
||
345 | throw new InvalidConfigurationException(sprintf('The rules contain risky fixers ("%s"), but they are not allowed to run. Perhaps you forget to use --allow-risky=yes option?', implode('", "', $riskyFixers))); |
||
346 | } |
||
347 | } |
||
348 | } |
||
349 | |||
350 | return $this->fixers; |
||
351 | } |
||
352 | |||
353 | public function getLinter(): LinterInterface |
||
354 | { |
||
355 | if (null === $this->linter) { |
||
356 | $this->linter = new Linter($this->getConfig()->getPhpExecutable()); |
||
357 | } |
||
358 | |||
359 | return $this->linter; |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * Returns path. |
||
364 | * |
||
365 | * @return string[] |
||
366 | */ |
||
367 | public function getPath(): array |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * @throws InvalidConfigurationException |
||
407 | */ |
||
408 | public function getProgress(): string |
||
409 | { |
||
410 | if (null === $this->progress) { |
||
411 | if (OutputInterface::VERBOSITY_VERBOSE <= $this->options['verbosity'] && 'txt' === $this->getFormat()) { |
||
412 | $progressType = $this->options['show-progress']; |
||
413 | $progressTypes = ['none', 'dots']; |
||
414 | |||
415 | if (null === $progressType) { |
||
416 | $progressType = $this->getConfig()->getHideProgress() ? 'none' : 'dots'; |
||
417 | } elseif (!\in_array($progressType, $progressTypes, true)) { |
||
418 | throw new InvalidConfigurationException(sprintf( |
||
419 | 'The progress type "%s" is not defined, supported are "%s".', |
||
420 | $progressType, |
||
421 | implode('", "', $progressTypes) |
||
422 | )); |
||
423 | } |
||
424 | |||
425 | $this->progress = $progressType; |
||
426 | } else { |
||
427 | $this->progress = 'none'; |
||
428 | } |
||
429 | } |
||
430 | |||
431 | return $this->progress; |
||
432 | } |
||
433 | |||
434 | public function getReporter(): ReporterInterface |
||
435 | { |
||
436 | if (null === $this->reporter) { |
||
437 | $reporterFactory = new ReporterFactory(); |
||
438 | $reporterFactory->registerBuiltInReporters(); |
||
439 | |||
440 | $format = $this->getFormat(); |
||
441 | |||
442 | try { |
||
443 | $this->reporter = $reporterFactory->getReporter($format); |
||
444 | } catch (\UnexpectedValueException $e) { |
||
445 | $formats = $reporterFactory->getFormats(); |
||
446 | sort($formats); |
||
447 | |||
448 | throw new InvalidConfigurationException(sprintf('The format "%s" is not defined, supported are "%s".', $format, implode('", "', $formats))); |
||
449 | } |
||
450 | } |
||
451 | |||
452 | return $this->reporter; |
||
453 | } |
||
454 | |||
455 | public function getRiskyAllowed(): bool |
||
456 | { |
||
457 | if (null === $this->allowRisky) { |
||
458 | if (null === $this->options['allow-risky']) { |
||
459 | $this->allowRisky = $this->getConfig()->getRiskyAllowed(); |
||
460 | } else { |
||
461 | $this->allowRisky = $this->resolveOptionBooleanValue('allow-risky'); |
||
462 | } |
||
463 | } |
||
464 | |||
465 | return $this->allowRisky; |
||
466 | } |
||
467 | |||
468 | /** |
||
469 | * Returns rules. |
||
470 | */ |
||
471 | public function getRules(): array |
||
472 | { |
||
473 | return $this->getRuleSet()->getRules(); |
||
474 | } |
||
475 | |||
476 | public function getUsingCache(): bool |
||
477 | { |
||
478 | if (null === $this->usingCache) { |
||
479 | if (null === $this->options['using-cache']) { |
||
480 | $this->usingCache = $this->getConfig()->getUsingCache(); |
||
481 | } else { |
||
482 | $this->usingCache = $this->resolveOptionBooleanValue('using-cache'); |
||
483 | } |
||
484 | } |
||
485 | |||
486 | $this->usingCache = $this->usingCache && ($this->toolInfo->isInstalledAsPhar() || $this->toolInfo->isInstalledByComposer()); |
||
487 | |||
488 | return $this->usingCache; |
||
489 | } |
||
490 | |||
491 | public function getFinder(): iterable |
||
492 | { |
||
493 | if (null === $this->finder) { |
||
494 | $this->finder = $this->resolveFinder(); |
||
495 | } |
||
496 | |||
497 | return $this->finder; |
||
498 | } |
||
499 | |||
500 | /** |
||
501 | * Returns dry-run flag. |
||
502 | */ |
||
503 | public function isDryRun(): bool |
||
504 | { |
||
505 | if (null === $this->isDryRun) { |
||
506 | if ($this->isStdIn()) { |
||
507 | // Can't write to STDIN |
||
508 | $this->isDryRun = true; |
||
509 | } else { |
||
510 | $this->isDryRun = $this->options['dry-run']; |
||
511 | } |
||
512 | } |
||
513 | |||
514 | return $this->isDryRun; |
||
515 | } |
||
516 | |||
517 | public function shouldStopOnViolation(): bool |
||
518 | { |
||
519 | return $this->options['stop-on-violation']; |
||
520 | } |
||
521 | |||
522 | public function configFinderIsOverridden(): bool |
||
529 | } |
||
530 | |||
531 | /** |
||
532 | * Compute file candidates for config file. |
||
533 | * |
||
534 | * @return string[] |
||
535 | */ |
||
536 | private function computeConfigFiles(): array |
||
537 | { |
||
538 | $configFile = $this->options['config']; |
||
539 | |||
540 | if (null !== $configFile) { |
||
541 | if (false === file_exists($configFile) || false === is_readable($configFile)) { |
||
542 | throw new InvalidConfigurationException(sprintf('Cannot read config file "%s".', $configFile)); |
||
543 | } |
||
544 | |||
545 | return [$configFile]; |
||
546 | } |
||
547 | |||
548 | $path = $this->getPath(); |
||
549 | |||
550 | if ($this->isStdIn() || 0 === \count($path)) { |
||
551 | $configDir = $this->cwd; |
||
552 | } elseif (1 < \count($path)) { |
||
553 | throw new InvalidConfigurationException('For multiple paths config parameter is required.'); |
||
554 | } elseif (!is_file($path[0])) { |
||
555 | $configDir = $path[0]; |
||
556 | } else { |
||
557 | $dirName = pathinfo($path[0], PATHINFO_DIRNAME); |
||
558 | $configDir = $dirName ?: $path[0]; |
||
559 | } |
||
560 | |||
561 | $candidates = [ |
||
562 | $configDir.\DIRECTORY_SEPARATOR.'.php-cs-fixer.php', |
||
563 | $configDir.\DIRECTORY_SEPARATOR.'.php-cs-fixer.dist.php', |
||
564 | $configDir.\DIRECTORY_SEPARATOR.'.php_cs', // old v2 config, present here only to throw nice error message later |
||
565 | $configDir.\DIRECTORY_SEPARATOR.'.php_cs.dist', // old v2 config, present here only to throw nice error message later |
||
566 | ]; |
||
567 | |||
568 | if ($configDir !== $this->cwd) { |
||
569 | $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php-cs-fixer.php'; |
||
570 | $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php-cs-fixer.dist.php'; |
||
571 | $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php_cs'; // old v2 config, present here only to throw nice error message later |
||
572 | $candidates[] = $this->cwd.\DIRECTORY_SEPARATOR.'.php_cs.dist'; // old v2 config, present here only to throw nice error message later |
||
573 | } |
||
574 | |||
575 | return $candidates; |
||
576 | } |
||
577 | |||
578 | private function createFixerFactory(): FixerFactory |
||
579 | { |
||
580 | if (null === $this->fixerFactory) { |
||
581 | $fixerFactory = new FixerFactory(); |
||
582 | $fixerFactory->registerBuiltInFixers(); |
||
583 | $fixerFactory->registerCustomFixers($this->getConfig()->getCustomFixers()); |
||
584 | |||
585 | $this->fixerFactory = $fixerFactory; |
||
586 | } |
||
587 | |||
588 | return $this->fixerFactory; |
||
589 | } |
||
590 | |||
591 | private function getFormat(): string |
||
592 | { |
||
593 | if (null === $this->format) { |
||
594 | $this->format = null === $this->options['format'] |
||
595 | ? $this->getConfig()->getFormat() |
||
596 | : $this->options['format']; |
||
597 | } |
||
598 | |||
599 | return $this->format; |
||
600 | } |
||
601 | |||
602 | private function getRuleSet(): RuleSetInterface |
||
603 | { |
||
604 | if (null === $this->ruleSet) { |
||
605 | $rules = $this->parseRules(); |
||
606 | $this->validateRules($rules); |
||
607 | |||
608 | $this->ruleSet = new RuleSet($rules); |
||
609 | } |
||
610 | |||
611 | return $this->ruleSet; |
||
612 | } |
||
613 | |||
614 | private function isStdIn(): bool |
||
621 | } |
||
622 | |||
623 | private function iterableToTraversable(iterable $iterable): \Traversable |
||
624 | { |
||
625 | return \is_array($iterable) ? new \ArrayIterator($iterable) : $iterable; |
||
626 | } |
||
627 | |||
628 | /** |
||
629 | * Compute rules. |
||
630 | */ |
||
631 | private function parseRules(): array |
||
632 | { |
||
633 | if (null === $this->options['rules']) { |
||
634 | return $this->getConfig()->getRules(); |
||
635 | } |
||
636 | |||
637 | $rules = trim($this->options['rules']); |
||
638 | if ('' === $rules) { |
||
639 | throw new InvalidConfigurationException('Empty rules value is not allowed.'); |
||
640 | } |
||
641 | |||
642 | if ('{' === $rules[0]) { |
||
643 | $rules = json_decode($rules, true); |
||
644 | if (JSON_ERROR_NONE !== json_last_error()) { |
||
645 | throw new InvalidConfigurationException(sprintf('Invalid JSON rules input: "%s".', json_last_error_msg())); |
||
646 | } |
||
647 | |||
648 | return $rules; |
||
649 | } |
||
650 | |||
651 | $rules = []; |
||
652 | |||
653 | foreach (explode(',', $this->options['rules']) as $rule) { |
||
654 | $rule = trim($rule); |
||
655 | if ('' === $rule) { |
||
656 | throw new InvalidConfigurationException('Empty rule name is not allowed.'); |
||
657 | } |
||
658 | |||
659 | if ('-' === $rule[0]) { |
||
660 | $rules[substr($rule, 1)] = false; |
||
661 | } else { |
||
662 | $rules[$rule] = true; |
||
663 | } |
||
664 | } |
||
665 | |||
666 | return $rules; |
||
667 | } |
||
668 | |||
669 | /** |
||
670 | * @throws InvalidConfigurationException |
||
671 | */ |
||
672 | private function validateRules(array $rules): void |
||
673 | { |
||
674 | /** |
||
675 | * Create a ruleset that contains all configured rules, even when they originally have been disabled. |
||
676 | * |
||
677 | * @see RuleSet::resolveSet() |
||
678 | */ |
||
679 | $ruleSet = []; |
||
680 | foreach ($rules as $key => $value) { |
||
681 | if (\is_int($key)) { |
||
682 | throw new InvalidConfigurationException(sprintf('Missing value for "%s" rule/set.', $value)); |
||
683 | } |
||
684 | |||
685 | $ruleSet[$key] = true; |
||
686 | } |
||
687 | $ruleSet = new RuleSet($ruleSet); |
||
688 | |||
689 | /** @var string[] $configuredFixers */ |
||
690 | $configuredFixers = array_keys($ruleSet->getRules()); |
||
691 | |||
692 | $fixers = $this->createFixerFactory()->getFixers(); |
||
693 | |||
694 | /** @var string[] $availableFixers */ |
||
695 | $availableFixers = array_map(static function (FixerInterface $fixer) { |
||
696 | return $fixer->getName(); |
||
697 | }, $fixers); |
||
698 | |||
699 | $unknownFixers = array_diff( |
||
700 | $configuredFixers, |
||
701 | $availableFixers |
||
702 | ); |
||
703 | |||
704 | if (\count($unknownFixers)) { |
||
705 | $matcher = new WordMatcher($availableFixers); |
||
706 | |||
707 | $message = 'The rules contain unknown fixers: '; |
||
708 | foreach ($unknownFixers as $unknownFixer) { |
||
709 | $alternative = $matcher->match($unknownFixer); |
||
710 | $message .= sprintf( |
||
711 | '"%s"%s, ', |
||
712 | $unknownFixer, |
||
713 | null === $alternative ? '' : ' (did you mean "'.$alternative.'"?)' |
||
714 | ); |
||
715 | } |
||
716 | |||
717 | throw new InvalidConfigurationException(substr($message, 0, -2).'.'); |
||
718 | } |
||
719 | |||
720 | foreach ($fixers as $fixer) { |
||
721 | $fixerName = $fixer->getName(); |
||
722 | if (isset($rules[$fixerName]) && $fixer instanceof DeprecatedFixerInterface) { |
||
723 | $successors = $fixer->getSuccessorsNames(); |
||
724 | $messageEnd = [] === $successors |
||
725 | ? sprintf(' and will be removed in version %d.0.', Application::getMajorVersion() + 1) |
||
726 | : sprintf('. Use %s instead.', str_replace('`', '"', Utils::naturalLanguageJoinWithBackticks($successors))); |
||
727 | |||
728 | Utils::triggerDeprecation(new \RuntimeException("Rule \"{$fixerName}\" is deprecated{$messageEnd}")); |
||
729 | } |
||
730 | } |
||
731 | } |
||
732 | |||
733 | /** |
||
734 | * Apply path on config instance. |
||
735 | */ |
||
736 | private function resolveFinder(): iterable |
||
737 | { |
||
738 | $this->configFinderIsOverridden = false; |
||
739 | |||
740 | if ($this->isStdIn()) { |
||
741 | return new \ArrayIterator([new StdinFileInfo()]); |
||
742 | } |
||
743 | |||
744 | $modes = [self::PATH_MODE_OVERRIDE, self::PATH_MODE_INTERSECTION]; |
||
745 | |||
746 | if (!\in_array( |
||
747 | $this->options['path-mode'], |
||
748 | $modes, |
||
749 | true |
||
750 | )) { |
||
751 | throw new InvalidConfigurationException(sprintf( |
||
752 | 'The path-mode "%s" is not defined, supported are "%s".', |
||
753 | $this->options['path-mode'], |
||
754 | implode('", "', $modes) |
||
755 | )); |
||
756 | } |
||
757 | |||
758 | $isIntersectionPathMode = self::PATH_MODE_INTERSECTION === $this->options['path-mode']; |
||
759 | |||
760 | $paths = array_filter(array_map( |
||
761 | static function (string $path) { |
||
762 | return realpath($path); |
||
763 | }, |
||
764 | $this->getPath() |
||
765 | )); |
||
766 | |||
767 | if (!\count($paths)) { |
||
768 | if ($isIntersectionPathMode) { |
||
769 | return new \ArrayIterator([]); |
||
770 | } |
||
771 | |||
772 | return $this->iterableToTraversable($this->getConfig()->getFinder()); |
||
773 | } |
||
774 | |||
775 | $pathsByType = [ |
||
776 | 'file' => [], |
||
777 | 'dir' => [], |
||
778 | ]; |
||
779 | |||
780 | foreach ($paths as $path) { |
||
781 | if (is_file($path)) { |
||
782 | $pathsByType['file'][] = $path; |
||
783 | } else { |
||
784 | $pathsByType['dir'][] = $path.\DIRECTORY_SEPARATOR; |
||
785 | } |
||
786 | } |
||
787 | |||
788 | $nestedFinder = null; |
||
789 | $currentFinder = $this->iterableToTraversable($this->getConfig()->getFinder()); |
||
790 | |||
791 | try { |
||
792 | $nestedFinder = $currentFinder instanceof \IteratorAggregate ? $currentFinder->getIterator() : $currentFinder; |
||
793 | } catch (\Exception $e) { |
||
794 | } |
||
795 | |||
796 | if ($isIntersectionPathMode) { |
||
797 | if (null === $nestedFinder) { |
||
798 | throw new InvalidConfigurationException( |
||
799 | 'Cannot create intersection with not-fully defined Finder in configuration file.' |
||
800 | ); |
||
801 | } |
||
802 | |||
803 | return new \CallbackFilterIterator( |
||
804 | new \IteratorIterator($nestedFinder), |
||
805 | static function (\SplFileInfo $current) use ($pathsByType) { |
||
806 | $currentRealPath = $current->getRealPath(); |
||
807 | |||
808 | if (\in_array($currentRealPath, $pathsByType['file'], true)) { |
||
809 | return true; |
||
810 | } |
||
811 | |||
812 | foreach ($pathsByType['dir'] as $path) { |
||
813 | if (0 === strpos($currentRealPath, $path)) { |
||
814 | return true; |
||
815 | } |
||
816 | } |
||
817 | |||
818 | return false; |
||
819 | } |
||
820 | ); |
||
821 | } |
||
822 | |||
823 | if (null !== $this->getConfigFile() && null !== $nestedFinder) { |
||
824 | $this->configFinderIsOverridden = true; |
||
825 | } |
||
826 | |||
827 | if ($currentFinder instanceof SymfonyFinder && null === $nestedFinder) { |
||
828 | // finder from configuration Symfony finder and it is not fully defined, we may fulfill it |
||
829 | return $currentFinder->in($pathsByType['dir'])->append($pathsByType['file']); |
||
830 | } |
||
831 | |||
832 | return Finder::create()->in($pathsByType['dir'])->append($pathsByType['file']); |
||
833 | } |
||
834 | |||
835 | /** |
||
836 | * Set option that will be resolved. |
||
837 | * |
||
838 | * @param mixed $value |
||
839 | */ |
||
840 | private function setOption(string $name, $value): void |
||
841 | { |
||
842 | if (!\array_key_exists($name, $this->options)) { |
||
843 | throw new InvalidConfigurationException(sprintf('Unknown option name: "%s".', $name)); |
||
844 | } |
||
845 | |||
846 | $this->options[$name] = $value; |
||
847 | } |
||
848 | |||
849 | private function resolveOptionBooleanValue(string $optionName): bool |
||
850 | { |
||
851 | $value = $this->options[$optionName]; |
||
852 | |||
853 | if (!\is_string($value)) { |
||
854 | throw new InvalidConfigurationException(sprintf('Expected boolean or string value for option "%s".', $optionName)); |
||
855 | } |
||
856 | |||
857 | if ('yes' === $value) { |
||
858 | return true; |
||
859 | } |
||
860 | |||
861 | if ('no' === $value) { |
||
862 | return false; |
||
863 | } |
||
864 | |||
865 | throw new InvalidConfigurationException(sprintf('Expected "yes" or "no" for option "%s", got "%s".', $optionName, $value)); |
||
866 | } |
||
867 | |||
868 | private static function separatedContextLessInclude(string $path): ConfigInterface |
||
878 | } |
||
879 | } |
||
880 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.