1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection\SourceLocator\Type;
6:
7: use Iterator;
8: use PHPStan\BetterReflection\Identifier\Identifier;
9: use PHPStan\BetterReflection\Identifier\IdentifierType;
10: use PHPStan\BetterReflection\Reflection\Reflection;
11: use PHPStan\BetterReflection\Reflector\Reflector;
12: use PHPStan\BetterReflection\SourceLocator\Ast\Locator;
13: use PHPStan\BetterReflection\SourceLocator\Exception\InvalidFileInfo;
14: use PHPStan\BetterReflection\SourceLocator\Exception\InvalidFileLocation;
15: use SplFileInfo;
16:
17: use function array_filter;
18: use function array_map;
19: use function array_values;
20: use function iterator_to_array;
21: use function pathinfo;
22:
23: use const PATHINFO_EXTENSION;
24:
25: /**
26: * This source locator loads all php files from \FileSystemIterator
27: */
28: class FileIteratorSourceLocator implements SourceLocator
29: {
30: /**
31: * @var \PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator|null
32: */
33: private $aggregateSourceLocator = null;
34:
35: /** @var Iterator<SplFileInfo> */
36: private $fileSystemIterator;
37: /**
38: * @var \PHPStan\BetterReflection\SourceLocator\Ast\Locator
39: */
40: private $astLocator;
41:
42: /**
43: * @param Iterator<SplFileInfo> $fileInfoIterator note: only SplFileInfo allowed in this iterator
44: *
45: * @throws InvalidFileInfo In case of iterator not contains only SplFileInfo.
46: */
47: public function __construct(Iterator $fileInfoIterator, Locator $astLocator)
48: {
49: $this->astLocator = $astLocator;
50: foreach ($fileInfoIterator as $fileInfo) {
51: if (! $fileInfo instanceof SplFileInfo) {
52: throw InvalidFileInfo::fromNonSplFileInfo($fileInfo);
53: }
54: }
55:
56: $this->fileSystemIterator = $fileInfoIterator;
57: }
58:
59: /** @throws InvalidFileLocation */
60: private function getAggregatedSourceLocator(): AggregateSourceLocator
61: {
62: return $this->aggregateSourceLocator
63: ?? $this->aggregateSourceLocator = new AggregateSourceLocator(array_values(array_filter(array_map(function (SplFileInfo $item): ?\PHPStan\BetterReflection\SourceLocator\Type\SingleFileSourceLocator {
64: if (! ($item->isFile() && pathinfo($item->getRealPath(), PATHINFO_EXTENSION) === 'php')) {
65: return null;
66: }
67:
68: return new SingleFileSourceLocator($item->getRealPath(), $this->astLocator);
69: }, iterator_to_array($this->fileSystemIterator)))));
70: }
71:
72: /**
73: * {@inheritDoc}
74: *
75: * @throws InvalidFileLocation
76: */
77: public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?\PHPStan\BetterReflection\Reflection\Reflection
78: {
79: return $this->getAggregatedSourceLocator()->locateIdentifier($reflector, $identifier);
80: }
81:
82: /**
83: * {@inheritDoc}
84: *
85: * @throws InvalidFileLocation
86: */
87: public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
88: {
89: return $this->getAggregatedSourceLocator()->locateIdentifiersByType($reflector, $identifierType);
90: }
91: }
92: