Passed
Pull Request — master (#6)
by Dmitriy
17:30 queued 02:25
created

Builder::rebuild()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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