Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.00% covered (warning)
85.00%
34 / 40
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Psr0
85.00% covered (warning)
85.00%
34 / 40
0.00% covered (danger)
0.00%
0 / 2
8.22
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setTargetDirectory
89.47% covered (warning)
89.47%
34 / 38
0.00% covered (danger)
0.00%
0 / 1
7.06
1<?php
2/**
3 * After a PSR-0 namespaced class is renamed, its directory structure must be updated to match the required format.
4 *
5 * @see https://www.php-fig.org/psr/psr-0/
6 * @see vendor/composer/composer/res/composer-schema.json
7 * @see vendor/pimple/pimple/composer.json
8 *
9 * @package brianhenryie/strauss
10 */
11
12namespace BrianHenryIE\Strauss\Pipeline\Autoload;
13
14use BrianHenryIE\Strauss\Composer\ComposerPackage;
15use BrianHenryIE\Strauss\Composer\DependenciesCollection;
16use BrianHenryIE\Strauss\Files\DiscoveredFiles;
17use BrianHenryIE\Strauss\Files\FileWithDependency;
18use BrianHenryIE\Strauss\Helpers\Flysystem\FileSystem;
19use BrianHenryIE\Strauss\Types\DiscoveredSymbols;
20use Psr\Log\LoggerAwareTrait;
21use Psr\Log\LoggerInterface;
22
23// We have a PSR-0 key
24// PHP files may be in namespaces
25// They may be global with underscores.
26
27class Psr0
28{
29    use LoggerAwareTrait;
30
31    protected FileSystem $filesystem;
32
33    public function __construct(
34        FileSystem $filesystem,
35        LoggerInterface $logger
36    ) {
37        $this->logger = $logger;
38        $this->filesystem = $filesystem;
39    }
40
41    public function setTargetDirectory(
42        DependenciesCollection $flatDependencyTree,
43        DiscoveredFiles $discoveredFiles,
44        DiscoveredSymbols $discoveredSymbols
45    ): void {
46        /** @var ComposerPackage $package */
47        foreach ($flatDependencyTree as $package) {
48            if (! $package->hasPsr0()) {
49                continue;
50            }
51
52            $composerAutoloadKey = $package->getAutoload();
53
54            /** @var DiscoveredFiles $allPackagesFiles */
55            $allPackagesFiles = $package->getFiles();
56
57            /**
58             * @see ComposerPackage::hasPsr0()
59             * @phpstan-ignore offsetAccess.notFound
60             */
61            foreach ($composerAutoloadKey['psr-0'] as $psrRootNamespace => $packageRelativeNamespacePath) {
62                // TODO: we need to have already run "determine changes" so we can set the target directory based on exclusion rules etc.
63                $namespaceSymbol = $discoveredSymbols->getNamespace($psrRootNamespace);
64
65                if (!$namespaceSymbol) {
66                    throw new \Exception('Namespace symbol not found for ' . $psrRootNamespace);
67                }
68
69                /** @var FileWithDependency $file */
70                foreach ($allPackagesFiles as $file) {
71                    $filePackageRelativePath = $file->getPackageRelativePath();
72
73                    if (! str_starts_with(
74                        $filePackageRelativePath,
75                        $packageRelativeNamespacePath
76                    )) {
77                        continue;
78                    }
79
80                    // It doesn't matter here whether we are using actual namespaces or underscored classnames, the target directory still changes.
81
82                    $originalNamespaceString    = $this->filesystem->normalizePath(
83                        $packageRelativeNamespacePath . '/' . $namespaceSymbol->getOriginalFqdnName()
84                    );
85                    $replacementNamespaceString = $this->filesystem->normalizePath(
86                        $packageRelativeNamespacePath . '/' . $namespaceSymbol->getReplacementFqdnName()
87                    );
88
89                    $updatedRelativePath = preg_replace(
90                        '#^' . $originalNamespaceString . '#',
91                        $replacementNamespaceString,
92                        $filePackageRelativePath
93                    ) ?? (function () {
94                        throw new \Exception(preg_last_error_msg(), preg_last_error());
95                    })();
96
97                    $updatedTargetPath = preg_replace(
98                        '#' . $filePackageRelativePath . '$#',
99                        $updatedRelativePath,
100                        $file->getTargetAbsolutePath()
101                    ) ?? (function () {
102                        throw new \Exception(preg_last_error_msg(), preg_last_error());
103                    })();
104
105                    $file->setTargetAbsolutePath($this->filesystem->normalizePath($updatedTargetPath));
106                    $file->addAutoloader('psr-0');
107                }
108            }
109        }
110        // Has exclude-from-classmap become invalid?
111    }
112}