Passed
Push — master ( 4d5c22...b892ad )
by Alexis
01:54
created

ConfigurationLoader::parseParameters()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 3
eloc 5
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the awurth/config package.
5
 *
6
 * (c) Alexis Wurth <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace AWurth\Config;
13
14
use AWurth\Config\Loader\JsonFileLoader;
15
use AWurth\Config\Loader\PhpFileLoader;
16
use AWurth\Config\Loader\YamlFileLoader;
17
use Symfony\Component\Config\ConfigCache;
18
use Symfony\Component\Config\FileLocator;
19
use Symfony\Component\Config\Loader\DelegatingLoader;
20
use Symfony\Component\Config\Loader\LoaderInterface;
21
use Symfony\Component\Config\Loader\LoaderResolver;
22
use Symfony\Component\Config\Resource\FileResource;
23
24
/**
25
 * Configuration Loader.
26
 *
27
 * @author Alexis Wurth <[email protected]>
28
 */
29
class ConfigurationLoader
30
{
31
    /**
32
     * @var array
33
     */
34
    protected $configurations;
35
36
    /**
37
     * @var LoaderInterface
38
     */
39
    protected $loader;
40
41
    /**
42
     * @var array
43
     */
44
    protected $parameters;
45
46
    /**
47
     * @var FileResource[]
48
     */
49
    protected $resources;
50
51
    /**
52
     * Constructor.
53
     *
54
     * @param array $parameters
55
     */
56
    public function __construct(array $parameters = [])
57
    {
58
        $this->configurations = [];
59
        $this->resources = [];
60
        $this->parameters = $parameters;
61
    }
62
63
    /**
64
     * Loads the configuration from a cache file if it exists, or parses a configuration file if not.
65
     *
66
     * @param string $file
67
     * @param string $cachePath
68
     * @param bool   $debug
69
     *
70
     * @return array|mixed
71
     */
72
    public function load($file, $cachePath = null, $debug = false)
73
    {
74
        if (null !== $cachePath) {
75
            $cache = new ConfigCache($cachePath, $debug);
76
            if (!$cache->isFresh()) {
77
                $configuration = $this->loadFile($file);
78
                $this->export($cache, $configuration);
79
80
                return $configuration;
81
            }
82
83
            return self::requireFile($cachePath);
84
        }
85
86
        return $this->loadFile($file);
87
    }
88
89
    /**
90
     * Loads the configuration from a file.
91
     *
92
     * @param string $file
93
     *
94
     * @return array
95
     */
96
    public function loadFile($file)
97
    {
98
        $this->initLoader();
99
100
        $this->parseFile($file);
101
102
        $configuration = $this->mergeConfiguration();
103
        if (isset($configuration['parameters'])) {
104
            $this->mergeParameters($configuration['parameters']);
105
        }
106
107
        $this->parseParameters($configuration);
108
109
        return $configuration;
110
    }
111
112
    /**
113
     * Gets the parameters.
114
     *
115
     * @return array
116
     */
117
    public function getParameters()
118
    {
119
        return $this->parameters;
120
    }
121
122
    /**
123
     * Sets the parameters.
124
     *
125
     * @param array $parameters
126
     */
127
    public function setParameters(array $parameters)
128
    {
129
        $this->parameters = $parameters;
130
    }
131
132
    /**
133
     * Exports the configuration to a cache file.
134
     *
135
     * @param ConfigCache $cache
136
     * @param array       $configuration
137
     */
138
    protected function export(ConfigCache $cache, array $configuration)
139
    {
140
        $content = '<?php'.PHP_EOL.PHP_EOL.'return '.var_export($configuration, true).';'.PHP_EOL;
141
142
        $cache->write($content, $this->resources);
143
    }
144
145
    /**
146
     * Initializes the file loader.
147
     */
148
    protected function initLoader()
149
    {
150
        if (null === $this->loader) {
151
            $locator = new FileLocator();
152
153
            $loaderResolver = new LoaderResolver([
154
                new JsonFileLoader($locator),
155
                new PhpFileLoader($locator),
156
                new YamlFileLoader($locator)
157
            ]);
158
159
            $this->loader = new DelegatingLoader($loaderResolver);
160
        }
161
    }
162
163
    /**
164
     * Loads file imports recursively.
165
     *
166
     * @param array  $values
167
     * @param string $directory
168
     */
169
    protected function loadImports(&$values, $directory)
170
    {
171
        if (isset($values['imports'])) {
172
            $imports = $values['imports'];
173
            if (is_string($imports)) {
174
                $this->parseFile($directory.DIRECTORY_SEPARATOR.$imports);
175
            } elseif (is_array($imports)) {
176
                foreach ($imports as $key => $file) {
177
                    $this->parseFile($directory.DIRECTORY_SEPARATOR.$file, is_string($key) ? $key : null);
178
                }
179
            }
180
        }
181
182
        unset($values['imports']);
183
    }
184
185
    /**
186
     * Merges all loaded configurations into a single array.
187
     *
188
     * @return array
189
     */
190
    protected function mergeConfiguration()
191
    {
192
        if (count($this->configurations) > 1) {
193
            return call_user_func_array('array_replace_recursive', $this->configurations);
194
        }
195
196
        return $this->configurations[0];
197
    }
198
199
    /**
200
     * Merges new parameters with existing ones.
201
     *
202
     * @param array $parameters
203
     */
204
    protected function mergeParameters(array $parameters)
205
    {
206
        $this->parameters = array_replace_recursive($this->parameters, $parameters);
207
    }
208
209
    /**
210
     * Parses a configuration file.
211
     *
212
     * @param string $file
213
     * @param string $key
214
     */
215
    protected function parseFile($file, $key = null)
216
    {
217
        $values = $this->loader->load($file);
218
219
        if ($values) {
220
            $this->loadImports($values, dirname($file));
221
222
            $this->configurations[] = null !== $key ? [$key => $values] : $values;
223
            $this->resources[] = new FileResource($file);
224
        }
225
    }
226
227
    /**
228
     * Parses the configuration and replaces placeholders with parameters values.
229
     *
230
     * @param array $configuration
231
     */
232
    protected function parseParameters(array &$configuration)
233
    {
234
        array_walk_recursive($configuration, function (&$item) {
235
            if (is_string($item)) {
236
                $item = preg_replace_callback('/%([0-9A-Za-z._-]+)%/', function ($matches) {
237
                    return isset($this->parameters[$matches[1]]) ? $this->parameters[$matches[1]] : null;
238
                }, $item);
239
            }
240
        });
241
    }
242
243
    /**
244
     * Includes a PHP file.
245
     *
246
     * @param string $file
247
     *
248
     * @return mixed
249
     */
250
    private static function requireFile($file)
251
    {
252
        return require $file;
253
    }
254
}
255