Completed
Push — master ( 1f7d3f...49921e )
by ANTHONIUS
12s
created

Config::setCachePath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the dotfiles project.
7
 *
8
 *     (c) Anthonius Munthi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Dotfiles\Core\Config;
15
16
use Dotfiles\Core\Util\Toolkit;
17
use Symfony\Component\Config\ConfigCache;
18
use Symfony\Component\Config\Definition\ConfigurationInterface;
19
use Symfony\Component\Config\Definition\Processor;
20
use Symfony\Component\Config\Resource\FileResource;
21
use Symfony\Component\Finder\Finder;
22
use Symfony\Component\Yaml\Yaml;
23
24
/**
25
 * Class Config.
26
 *
27
 * @covers \Dotfiles\Core\Config\Config
28
 */
29
class Config implements \ArrayAccess
30
{
31
    /**
32
     * @var null|string
33
     */
34
    private $cachePath = null;
0 ignored issues
show
introduced by
The private property $cachePath is not used, and could be removed.
Loading history...
35
36
    private $configDirs = array();
37
38
    private $configs = array();
39
40
    private $defaults = array();
41
42
    /**
43
     * @var ConfigurationInterface[]
44
     */
45
    private $definitions = array();
46
47
    private $files = array();
48
49
    private $flattened = array();
50
51
    /**
52
     * @param $directory
53
     *
54
     * @return Config
55
     */
56
    public function addConfigDir($directory): self
57
    {
58
        if (!is_dir($directory)) {
59
            throw new \InvalidArgumentException("Directory ${directory} not exists");
60
        }
61
        if (!in_array($directory, $this->configDirs)) {
62
            $this->configDirs[] = $directory;
63
        }
64
65
        return $this;
66
    }
67
68
    public function addDefinition(ConfigurationInterface $config): self
69
    {
70
        $builder = $config->getConfigTreeBuilder();
71
        $name = $builder->buildTree()->getName();
72
        $this->definitions[$name] = $config;
73
        $this->defaults[$name] = array();
74
75
        return $this;
76
    }
77
78
    public function get($name)
79
    {
80
        if (array_key_exists($name, $this->configs)) {
81
            return $this->configs[$name];
82
        } elseif (array_key_exists($name, $this->flattened)) {
83
            return $this->flattened[$name];
84
        } else {
85
            throw new \InvalidArgumentException('Unknown config key: "'.$name.'"');
86
        }
87
    }
88
89
    public function getAll($flattened = false)
90
    {
91
        return $flattened ? $this->flattened : $this->configs;
92
    }
93
94
    /**
95
     * @return array
96
     */
97
    public function getConfigDirs(): array
98
    {
99
        return $this->configDirs;
100
    }
101
102
    /**
103
     * Load configuration from files and default value.
104
     */
105
    public function loadConfiguration(): void
106
    {
107
        $cachePath = Toolkit::getCachePathPrefix().'/config.php';
108
        $cache = new ConfigCache($cachePath, true);
109
        $env = getenv('DOTFILES_ENV');
110
        if (!$cache->isFresh() || 'dev' === $env) {
111
            $processor = new Processor();
112
            $configs = $this->processFiles();
113
            $generated = array();
114
            foreach ($configs as $rootKey => $values) {
115
                if (!isset($this->definitions[$rootKey])) {
116
                    continue;
117
                }
118
                $temp = array();
119
                $config = $this->definitions[$rootKey];
120
                $temp[$rootKey] = $values;
121
                $processed = $processor->processConfiguration($config, $temp);
122
                if (!isset($generated[$rootKey])) {
123
                    $generated[$rootKey] = array();
124
                }
125
                $generated[$rootKey] = array_merge_recursive($generated[$rootKey], $processed);
126
            }
127
            $expConfig = var_export($generated, true);
128
            $flattened = $generated;
129
            Toolkit::flattenArray($flattened);
130
            $expFlattened = var_export($flattened, true);
131
132
            /* provide a way to handle normalize config */
133
            $this->normalizeConfig($flattened, $expConfig);
134
            $this->normalizeConfig($flattened, $expConfig);
135
            $this->normalizeConfig($flattened, $expFlattened);
136
            $this->normalizeConfig($flattened, $expFlattened);
137
138
            $code = <<<EOC
139
<?php
140
\$this->configs = ${expConfig};
141
\$this->flattened = ${expFlattened};
142
EOC;
143
            $cache->write($code, $this->files);
144
        }
145
        require $cachePath;
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151
    public function offsetExists($offset)
152
    {
153
        return isset($this->configs[$offset]);
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159
    public function offsetGet($offset)
160
    {
161
        return $this->configs[$offset];
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function offsetSet($offset, $value): void
168
    {
169
        $this->configs[$offset] = $value;
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function offsetUnset($offset): void
176
    {
177
        unset($this->configs[$offset]);
178
    }
179
180
    public function set($name, $value): void
181
    {
182
        $this->flattened[$name] = $value;
183
    }
184
185
    private function normalizeConfig($flattened, &$config): void
186
    {
187
        foreach ($flattened as $name => $value) {
188
            $format = '%'.$name.'%';
189
            $config = strtr($config, array($format => $value));
190
        }
191
    }
192
193
    private function processFiles()
194
    {
195
        $configs = $this->defaults;
196
        if (!count($this->configDirs) > 0) {
197
            return $configs;
198
        }
199
        $finder = Finder::create()
200
            ->name('*.yaml')
201
            ->name('*.yml')
202
        ;
203
        foreach ($this->configDirs as $dir) {
204
            $finder->in($dir);
205
        }
206
        /* @var \Symfony\Component\Finder\SplFileInfo $file */
207
        foreach ($finder->files() as $file) {
208
            $parsed = Yaml::parseFile($file->getRealPath());
209
            if (is_array($parsed)) {
210
                $configs = array_merge_recursive($configs, $parsed);
211
            }
212
            $this->files[] = new FileResource($file->getRealPath());
213
        }
214
215
        return $configs;
216
    }
217
}
218