Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
DumpAutoload
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 3
30
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 generatedPrefixedAutoloader
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
6
 getSuffix
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace BrianHenryIE\Strauss\Pipeline\Autoload;
4
5use BrianHenryIE\Strauss\Config\AutoloadConfigInterace;
6use BrianHenryIE\Strauss\Helpers\FileSystem;
7use Composer\Autoload\AutoloadGenerator;
8use Composer\Config;
9use Composer\Factory;
10use Composer\IO\NullIO;
11use Composer\Json\JsonFile;
12use Composer\Repository\InstalledFilesystemRepository;
13use Psr\Log\LoggerAwareTrait;
14use Psr\Log\LoggerInterface;
15use Psr\Log\NullLogger;
16
17class DumpAutoload
18{
19    use LoggerAwareTrait;
20
21    protected AutoloadConfigInterace $config;
22
23    protected FileSystem $filesystem;
24
25    public function __construct(
26        AutoloadConfigInterace $config,
27        Filesystem $filesystem,
28        ?LoggerInterface $logger = null
29    ) {
30        $this->config = $config;
31        $this->filesystem = $filesystem;
32        $this->setLogger($logger ?? new NullLogger());
33    }
34
35    /**
36     * Uses `vendor/composer/installed.json` to output autoload files to `vendor-prefixed/composer`.
37     */
38    public function generatedPrefixedAutoloader(): void
39    {
40        /**
41         * Unfortunately, `::dump()` creates the target directories if they don't exist, even though it otherwise respects `::setDryRun()`.
42         */
43        if ($this->config->isDryRun()) {
44            return;
45        }
46
47        $relativeTargetDir = $this->filesystem->getRelativePath(
48            $this->config->getProjectDirectory(),
49            $this->config->getTargetDirectory()
50        );
51
52        $defaultVendorDirBefore = Config::$defaultConfig['vendor-dir'];
53
54        Config::$defaultConfig['vendor-dir'] = $relativeTargetDir;
55
56        $composer = Factory::create(new NullIO(), $this->config->getProjectDirectory() . 'composer.json');
57        $installationManager = $composer->getInstallationManager();
58        $package = $composer->getPackage();
59
60        /**
61         * Cannot use `$composer->getConfig()`, need to create a new one so the vendor-dir is correct.
62         */
63        $config = new \Composer\Config(false, $this->config->getProjectDirectory());
64
65        $generator = $composer->getAutoloadGenerator();
66        $generator->setDryRun($this->config->isDryRun());
67
68        //        $generator->setClassMapAuthoritative($authoritative);
69        $generator->setClassMapAuthoritative(true);
70
71        $generator->setRunScripts(false);
72//        $generator->setApcu($apcu, $apcuPrefix);
73//        $generator->setPlatformRequirementFilter($this->getPlatformRequirementFilter($input));
74        $optimize = false; // $input->getOption('optimize') || $config->get('optimize-autoloader');
75        $generator->setDevMode(false);
76
77        $localRepo = new InstalledFilesystemRepository(new JsonFile($this->config->getTargetDirectory() . 'composer/installed.json'));
78
79        // This will output the autoload_static.php etc. files to `vendor-prefixed/composer`.
80        $generator->dump(
81            $config,
82            $localRepo,
83            $package,
84            $installationManager,
85            'composer',
86            $optimize,
87            $this->getSuffix(),
88            $composer->getLocker(),
89            false, // $input->getOption('strict-ambiguous')
90        );
91
92        /**
93         * Tests fail if this is absent.
94         *
95         * Arguably this should be in ::setUp() and tearDown() in the test classes, but if other tools run after Strauss
96         * then they might expect it to be unmodified.
97         */
98        Config::$defaultConfig['vendor-dir'] = $defaultVendorDirBefore;
99    }
100
101    /**
102     * If there is an existing autoloader, it will use the same suffix. If there is not, it pulls the suffix from
103     * {Composer::getLocker()} and clashes with the existing autoloader.
104     *
105     * @see AutoloadGenerator::dump() 412:431
106     * @see https://github.com/composer/composer/blob/ae208dc1e182bd45d99fcecb956501da212454a1/src/Composer/Autoload/AutoloadGenerator.php#L429
107     */
108    protected function getSuffix(): ?string
109    {
110        return !$this->filesystem->fileExists($this->config->getTargetDirectory() . 'autoload.php')
111            ? bin2hex(random_bytes(16))
112            : null;
113    }
114}