Passed
Pull Request — master (#16)
by Dmitry
14:13
created

Builder::getBaseDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Yiisoft\Composer\Config;
4
5
use JsonException;
6
use Yiisoft\Composer\Config\Configs\Config;
7
use Yiisoft\Composer\Config\Configs\ConfigFactory;
8
use Yiisoft\Composer\Config\Utils\Resolver;
9
10
use function dirname;
11
12
/**
13
 * Builder assembles config files.
14
 */
15
class Builder
16
{
17
    private const OUTPUT_DIR_SUFFIX = '-output';
18
19
    /**
20
     * @var string path to the composer project root
21
     */
22
    private string $baseDir;
23
24
    /**
25
     * @var string path to output assembled configs
26
     */
27
    private string $outputDir;
28
29
    /**
30
     * @var Config[] configurations
31
     */
32
    private array $configs = [];
33
34
    private ConfigFactory $configFactory;
35
36
    public function __construct(ConfigFactory $configFactory, string $baseDir = null)
37
    {
38
        $this->configFactory = $configFactory;
39
        $this->setBaseDir($baseDir);
0 ignored issues
show
Bug introduced by
It seems like $baseDir can also be of type null; however, parameter $baseDir of Yiisoft\Composer\Config\Builder::setBaseDir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
        $this->setBaseDir(/** @scrutinizer ignore-type */ $baseDir);
Loading history...
40
        $this->outputDir = self::findOutputDir($baseDir);
41
    }
42
43
    public function createAlternative($name): Builder
44
    {
45
        $alt = new static($this->configFactory, $this->baseDir);
46
        $alt->setOutputDir($this->outputDir . DIRECTORY_SEPARATOR . $name);
47
        foreach (['aliases', 'packages'] as $key) {
48
            $alt->configs[$key] = $this->getConfig($key)->clone($alt);
49
        }
50
51
        return $alt;
52
    }
53
54
    public function setOutputDir(?string $outputDir): void
55
    {
56
        $this->outputDir = $outputDir
57
            ? static::buildAbsPath($this->getBaseDir(), $outputDir)
58
            : static::findOutputDir();
59
    }
60
61
    public static function rebuild(string $outputDir = null): void
62
    {
63
        $builder = new self(new ConfigFactory(), $outputDir);
64
        $files = $builder->getConfig('__files')->load();
65
        $builder->buildUserConfigs($files->getValues());
66
    }
67
68
    /**
69
     * Returns default output dir.
70
     *
71
     * @param string $baseDir path to project base dir
72
     * @return string
73
     * @throws JsonException
74
     */
75
    private static function findOutputDir(string $baseDir = null): string
76
    {
77
        $baseDir = $baseDir ?: static::findBaseDir();
78
        $path = $baseDir . DIRECTORY_SEPARATOR . 'composer.json';
79
        $data = @json_decode(file_get_contents($path), true);
80
        $dir = $data['extra'][Package::EXTRA_OUTPUT_DIR_OPTION_NAME] ?? null;
81
82
        return $dir ? static::buildAbsPath($baseDir, $dir) : static::defaultOutputDir($baseDir);
83
    }
84
85
    private static function findBaseDir(): string
86
    {
87
        return dirname(__DIR__, 4);
88
    }
89
90
    /**
91
     * Returns default output dir.
92
     *
93
     * @param string $baseDir path to base directory
94
     * @return string
95
     */
96
    private static function defaultOutputDir(string $baseDir = null): string
97
    {
98
        if ($baseDir) {
99
            $dir = $baseDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'yiisoft' . DIRECTORY_SEPARATOR . basename(dirname(__DIR__));
100
        } else {
101
            $dir = dirname(__DIR__);
102
        }
103
104
        return $dir . static::OUTPUT_DIR_SUFFIX;
105
    }
106
107
    /**
108
     * Returns full path to assembled config file.
109
     *
110
     * @param string $filename name of config
111
     * @param string $baseDir path to base dir
112
     * @return string absolute path
113
     * @throws JsonException
114
     */
115
    public static function path(string $filename, string $baseDir = null): string
116
    {
117
        return static::buildAbsPath(static::findOutputDir($baseDir), $filename . '.php');
118
    }
119
120
    private static function buildAbsPath(string $dir, string $file): string
121
    {
122
        return strncmp($file, DIRECTORY_SEPARATOR, 1) === 0 ? $file : $dir . DIRECTORY_SEPARATOR . $file;
123
    }
124
125
    /**
126
     * Builds all (user and system) configs by given files list.
127
     *
128
     * @param null|array $files files to process: config name => list of files
129
     */
130
    public function buildAllConfigs(array $files): void
131
    {
132
        $this->buildUserConfigs($files);
133
        $this->buildSystemConfigs($files);
134
    }
135
136
    /**
137
     * Builds configs by given files list.
138
     *
139
     * @param null|array $files files to process: config name => list of files
140
     * @return array
141
     */
142
    private function buildUserConfigs(array $files): array
143
    {
144
        $resolver = new Resolver($files);
145
        $files = $resolver->get();
146
        foreach ($files as $name => $paths) {
147
            $this->getConfig($name)->load($paths)->build()->write();
148
        }
149
150
        return $files;
151
    }
152
153
    private function buildSystemConfigs(array $files): void
154
    {
155
        $this->getConfig('__files')->setValues($files);
156
        foreach (['__rebuild', '__files', 'aliases', 'packages'] as $name) {
157
            $this->getConfig($name)->build()->write();
158
        }
159
    }
160
161
    public function getOutputPath($name): string
162
    {
163
        return $this->outputDir . DIRECTORY_SEPARATOR . $name . '.php';
164
    }
165
166
    private function createConfig($name): Config
167
    {
168
        $config = $this->configFactory->create($this, $name);
169
        $this->configs[$name] = $config;
170
171
        return $config;
172
    }
173
174
    public function getConfig(string $name)
175
    {
176
        if (!isset($this->configs[$name])) {
177
            $this->configs[$name] = $this->createConfig($name);
178
        }
179
180
        return $this->configs[$name];
181
    }
182
183
    public function getVars(): array
184
    {
185
        $vars = [];
186
        foreach ($this->configs as $name => $config) {
187
            $vars[$name] = $config->getValues();
188
        }
189
190
        return $vars;
191
    }
192
193
    public function mergeAliases(array $aliases): void
194
    {
195
        $this->getConfig('aliases')->mergeValues($aliases);
196
    }
197
198
    public function setPackage(string $name, array $data): void
199
    {
200
        $this->getConfig('packages')->setValue($name, $data);
201
    }
202
203
    /**
204
     * @return string a full path to the project root
205
     */
206
    public function getBaseDir(): string
207
    {
208
        return $this->baseDir;
209
    }
210
211
    /**
212
     * @param string $baseDir
213
     */
214
    private function setBaseDir(string $baseDir): void
215
    {
216
        $this->baseDir = $baseDir;
217
    }
218
}
219