Issues (224)

src/Composer/ComposerProcessFactory.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box\Composer;
16
17
use Closure;
18
use Fidry\Console\IO;
0 ignored issues
show
The type Fidry\Console\IO was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use KevinGH\Box\Constants;
20
use RuntimeException;
21
use Symfony\Component\Process\ExecutableFinder;
22
use Symfony\Component\Process\Process;
23
24
/**
25
 * @final
26
 * @private
27
 */
28
class ComposerProcessFactory
29
{
30
    private string $composerExecutable;
31
32
    public static function create(
33
        ?string $composerExecutable = null,
34
        ?IO $io = null,
35
    ): self {
36
        $io ??= IO::createNull();
37
38
        return new self(
39
            null === $composerExecutable
40
                ? self::retrieveComposerExecutable(...)
41
                : static fn () => $composerExecutable,
42
            self::retrieveSubProcessVerbosity($io),
43
            $io->isDecorated(),
44
            self::getDefaultEnvVars(),
45
        );
46
    }
47
48
    /**
49
     * @param Closure():string $composerExecutableFactory
50
     */
51
    public function __construct(
52
        private readonly Closure $composerExecutableFactory,
53
        private ?string $verbosity,
54
        private readonly bool $ansi,
55
        private readonly array $defaultEnvironmentVariables,
56
    ) {
57
    }
58
59
    public function getVersionProcess(): Process
60
    {
61
        return $this->createProcess(
62
            [
63
                $this->getComposerExecutable(),
64
                '--version',
65
                // Never use ANSI support here as we want to parse the raw output.
66
                '--no-ansi',
67
            ],
68
            // Ensure that even if this command gets executed within the app with --quiet it still
69
            // works.
70
            ['SHELL_VERBOSITY' => 0],
71
        );
72
    }
73
74
    public function getDumpAutoloaderProcess(bool $noDev): Process
75
    {
76
        $composerCommand = [$this->getComposerExecutable(), 'dump-autoload', '--classmap-authoritative'];
77
78
        if (true === $noDev) {
79
            $composerCommand[] = '--no-dev';
80
        }
81
82
        if (null !== $this->verbosity) {
83
            $composerCommand[] = $this->verbosity;
84
        }
85
86
        if ($this->ansi) {
87
            $composerCommand[] = '--ansi';
88
        }
89
90
        return $this->createProcess($composerCommand);
91
    }
92
93
    public function getVendorDirProcess(): Process
94
    {
95
        return $this->createProcess(
96
            [
97
                $this->getComposerExecutable(),
98
                'config',
99
                'vendor-dir',
100
                // Never use ANSI support here as we want to parse the raw output.
101
                '--no-ansi',
102
            ],
103
            // Ensure that even if this command gets executed within the app with --quiet it still
104
            // works.
105
            ['SHELL_VERBOSITY' => 0],
106
        );
107
    }
108
109
    private function createProcess(array $command, array $environmentVariables = []): Process
110
    {
111
        return new Process(
112
            $command,
113
            env: [
114
                ...$this->defaultEnvironmentVariables,
115
                ...$environmentVariables,
116
            ],
117
        );
118
    }
119
120
    private function getComposerExecutable(): string
121
    {
122
        if (!isset($this->composerExecutable)) {
123
            $this->composerExecutable = ($this->composerExecutableFactory)();
124
        }
125
126
        return $this->composerExecutable;
127
    }
128
129
    private static function retrieveSubProcessVerbosity(IO $io): ?string
130
    {
131
        if ($io->isDebug()) {
132
            return '-vvv';
133
        }
134
135
        if ($io->isVeryVerbose()) {
136
            return '-v';
137
        }
138
139
        return null;
140
    }
141
142
    private static function getDefaultEnvVars(): array
143
    {
144
        $vars = ['COMPOSER_ORIGINAL_INIS' => ''];
145
146
        if ('1' === (string) getenv(Constants::ALLOW_XDEBUG)) {
147
            $vars['COMPOSER_ALLOW_XDEBUG'] = '1';
148
        }
149
150
        return $vars;
151
    }
152
153
    private static function retrieveComposerExecutable(): string
0 ignored issues
show
The method retrieveComposerExecutable() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
154
    {
155
        $executableFinder = new ExecutableFinder();
156
        $executableFinder->addSuffix('.phar');
157
158
        if (null === $composer = $executableFinder->find('composer')) {
159
            throw new RuntimeException('Could not find a Composer executable.');
160
        }
161
162
        return $composer;
163
    }
164
}
165