Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
5.88% |
4 / 68 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
FileEnumerator | |
5.88% |
4 / 68 |
|
0.00% |
0 / 4 |
388.66 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
compileFileListForDependencies | |
0.00% |
0 / 34 |
|
0.00% |
0 / 1 |
182 | |||
addFileWithDependency | |
17.39% |
4 / 23 |
|
0.00% |
0 / 1 |
19.09 | |||
compileFileListForPaths | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * Build a list of files from the composer autoloaders. |
4 | * |
5 | * Also record the `files` autoloaders. |
6 | */ |
7 | |
8 | namespace BrianHenryIE\Strauss\Pipeline; |
9 | |
10 | use BrianHenryIE\Strauss\Composer\ComposerPackage; |
11 | use BrianHenryIE\Strauss\Config\FileEnumeratorConfig; |
12 | use BrianHenryIE\Strauss\Files\DiscoveredFiles; |
13 | use BrianHenryIE\Strauss\Files\File; |
14 | use BrianHenryIE\Strauss\Files\FileWithDependency; |
15 | use BrianHenryIE\Strauss\Helpers\FileSystem; |
16 | use League\Flysystem\FilesystemException; |
17 | use Psr\Log\LoggerAwareTrait; |
18 | use Psr\Log\LoggerInterface; |
19 | use Psr\Log\NullLogger; |
20 | |
21 | class FileEnumerator |
22 | { |
23 | use LoggerAwareTrait; |
24 | |
25 | protected FileEnumeratorConfig $config; |
26 | |
27 | protected Filesystem $filesystem; |
28 | |
29 | protected DiscoveredFiles $discoveredFiles; |
30 | |
31 | /** |
32 | * Record the files autoloaders for later use in building our own autoloader. |
33 | * |
34 | * Package-name: [ dir1, file1, file2, ... ]. |
35 | * |
36 | * @var array<string, string[]> |
37 | */ |
38 | protected array $filesAutoloaders = []; |
39 | |
40 | /** |
41 | * Copier constructor. |
42 | */ |
43 | public function __construct( |
44 | FileEnumeratorConfig $config, |
45 | FileSystem $filesystem, |
46 | ?LoggerInterface $logger = null |
47 | ) { |
48 | $this->discoveredFiles = new DiscoveredFiles(); |
49 | |
50 | $this->config = $config; |
51 | |
52 | $this->filesystem = $filesystem; |
53 | |
54 | $this->logger = $logger ?? new NullLogger(); |
55 | } |
56 | |
57 | /** |
58 | * Read the autoload keys of the dependencies and generate a list of the files referenced. |
59 | * |
60 | * Includes all files in the directories and subdirectories mentioned in the autoloaders. |
61 | * |
62 | * @param ComposerPackage[] $dependencies |
63 | * |
64 | * @throws FilesystemException |
65 | */ |
66 | public function compileFileListForDependencies(array $dependencies): DiscoveredFiles |
67 | { |
68 | foreach ($dependencies as $dependency) { |
69 | $this->logger->info("Scanning for files for package {packageName}", ['packageName' => $dependency->getPackageName()]); |
70 | |
71 | /** |
72 | * Where $dependency->autoload is ~ |
73 | * |
74 | * [ "psr-4" => [ "BrianHenryIE\Strauss" => "src" ] ] |
75 | * Exclude "exclude-from-classmap" |
76 | * @see https://getcomposer.org/doc/04-schema.md#exclude-files-from-classmaps |
77 | */ |
78 | $autoloaders = array_filter($dependency->getAutoload(), function ($type) { |
79 | return 'exclude-from-classmap' !== $type; |
80 | }, ARRAY_FILTER_USE_KEY); |
81 | |
82 | $dependencyPackageAbsolutePath = $dependency->getPackageAbsolutePath(); |
83 | |
84 | foreach ($autoloaders as $type => $value) { |
85 | // Might have to switch/case here. |
86 | |
87 | if ('files' === $type) { |
88 | // TODO: This is not in use. |
89 | $this->filesAutoloaders[$dependency->getRelativePath()] = $value; |
90 | } |
91 | |
92 | foreach ($value as $namespace => $namespace_relative_paths) { |
93 | if (!empty($namespace) && in_array($namespace, $this->config->getExcludeNamespacesFromCopy())) { |
94 | $this->logger->info("Excluding namespace " . $namespace); |
95 | continue; |
96 | } |
97 | |
98 | $namespace_relative_paths = (array) $namespace_relative_paths; |
99 | // if (! is_array($namespace_relative_paths)) { |
100 | // $namespace_relative_paths = array( $namespace_relative_paths ); |
101 | // } |
102 | |
103 | foreach ($namespace_relative_paths as $namespaceRelativePath) { |
104 | $sourceAbsoluteDirPath = in_array($namespaceRelativePath, ['.','./']) |
105 | ? $dependencyPackageAbsolutePath |
106 | : $dependencyPackageAbsolutePath . $namespaceRelativePath; |
107 | |
108 | if ($this->filesystem->directoryExists($sourceAbsoluteDirPath)) { |
109 | $fileList = $this->filesystem->listContents($sourceAbsoluteDirPath, true); |
110 | $actualFileList = $fileList->toArray(); |
111 | |
112 | foreach ($actualFileList as $foundFile) { |
113 | $sourceAbsoluteFilepath = '/'. $foundFile->path(); |
114 | // No need to record the directory itself. |
115 | if (!$this->filesystem->fileExists($sourceAbsoluteFilepath) |
116 | || |
117 | $this->filesystem->directoryExists($sourceAbsoluteFilepath) |
118 | ) { |
119 | continue; |
120 | } |
121 | |
122 | $this->addFileWithDependency( |
123 | $dependency, |
124 | $sourceAbsoluteFilepath, |
125 | $type |
126 | ); |
127 | } |
128 | } else { |
129 | $this->addFileWithDependency($dependency, $sourceAbsoluteDirPath, $type); |
130 | } |
131 | } |
132 | } |
133 | } |
134 | } |
135 | |
136 | $this->discoveredFiles->sort(); |
137 | return $this->discoveredFiles; |
138 | } |
139 | |
140 | /** |
141 | * @param ComposerPackage $dependency |
142 | * @param string $sourceAbsoluteFilepath |
143 | * @param string $autoloaderType |
144 | * |
145 | * @throws FilesystemException |
146 | * @uses DiscoveredFiles::add |
147 | * |
148 | */ |
149 | protected function addFileWithDependency( |
150 | ComposerPackage $dependency, |
151 | string $sourceAbsoluteFilepath, |
152 | string $autoloaderType |
153 | ): void { |
154 | |
155 | // Do not add a file if its source does not exist! |
156 | if (!$this->filesystem->fileExists($sourceAbsoluteFilepath) |
157 | && !$this->filesystem->directoryExists($sourceAbsoluteFilepath)) { |
158 | $this->logger->warning("File does not exist: {sourcePath}", ['sourcePath' => $sourceAbsoluteFilepath]); |
159 | return; |
160 | } |
161 | |
162 | $vendorRelativePath = substr( |
163 | $sourceAbsoluteFilepath, |
164 | strpos($sourceAbsoluteFilepath, $dependency->getRelativePath() ?: 0) |
165 | ); |
166 | |
167 | if ($vendorRelativePath === $sourceAbsoluteFilepath) { |
168 | $vendorRelativePath = $dependency->getRelativePath() . str_replace($dependency->getPackageAbsolutePath(), '', $sourceAbsoluteFilepath); |
169 | } |
170 | |
171 | $isOutsideProjectDir = 0 !== strpos($sourceAbsoluteFilepath, $this->config->getVendorDirectory()); |
172 | |
173 | /** @var FileWithDependency $f */ |
174 | $f = $this->discoveredFiles->getFile($sourceAbsoluteFilepath) |
175 | ?? new FileWithDependency($dependency, $vendorRelativePath, $sourceAbsoluteFilepath); |
176 | |
177 | $f->setAbsoluteTargetPath($this->config->getVendorDirectory() . $vendorRelativePath); |
178 | |
179 | $f->addAutoloader($autoloaderType); |
180 | $f->setDoDelete($isOutsideProjectDir); |
181 | |
182 | $this->discoveredFiles->add($f); |
183 | |
184 | $relativeFilePath = |
185 | $this->filesystem->getRelativePath( |
186 | dirname($this->config->getVendorDirectory()), |
187 | $f->getAbsoluteTargetPath() |
188 | ); |
189 | $this->logger->info("Found file " . $relativeFilePath); |
190 | } |
191 | |
192 | /** |
193 | * @param string[] $paths |
194 | */ |
195 | public function compileFileListForPaths(array $paths): DiscoveredFiles |
196 | { |
197 | $absoluteFilePaths = $this->filesystem->findAllFilesAbsolutePaths($paths); |
198 | |
199 | foreach ($absoluteFilePaths as $sourceAbsolutePath) { |
200 | $f = $this->discoveredFiles->getFile($sourceAbsolutePath) |
201 | ?? new File($sourceAbsolutePath); |
202 | |
203 | $this->discoveredFiles->add($f); |
204 | } |
205 | |
206 | $this->discoveredFiles->sort(); |
207 | return $this->discoveredFiles; |
208 | } |
209 | } |