Completed
Push — master ( 672a26...911627 )
by Sergey
03:19
created

Loader::resolveFiles()   C

Complexity

Conditions 8
Paths 11

Size

Total Lines 36
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 36
ccs 26
cts 26
cp 1
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 23
nc 11
nop 0
crap 8
1
<?php
2
/**
3
 * Yii 2 config loader
4
 *
5
 * @see       https://github.com/sergeymakinen/yii2-config
6
 * @copyright Copyright (c) 2016-2017 Sergey Makinen (https://makinen.ru)
7
 * @license   https://github.com/sergeymakinen/yii2-config/blob/master/LICENSE The MIT License
8
 */
9
10
namespace sergeymakinen\yii\config;
11
12
use yii\base\Object;
13
14
/**
15
 * Base config loader.
16
 */
17
abstract class Loader extends Object
18
{
19
    /**
20
     * @var string|string[]|null a tier name or an array of tier names to match a tier name specified in [[Config]].
21
     *
22
     * If there're an array it will match *any of* specified values.
23
     * You can also use an exclamation mark (`!`) before a name to use a `not` match. Example:
24
     *
25
     * ```php
26
     * [
27
     *     'tier1',
28
     *     '!tier2',
29
     * ]
30
     * ```
31
     *
32
     * It matches if the tier name is `tier1` *or* **not** `tier2`.
33
     */
34
    public $tier;
35
36
    /**
37
     * @var string|string[]|null an environment name or an array of environment names to match an environment name specified in [[Config]].
38
     *
39
     * If there're an array it will match *any of* specified values.
40
     * You can also use an exclamation mark (`!`) before a name to use a `not` match. Example:
41
     *
42
     * ```php
43
     * [
44
     *     'env1',
45
     *     '!env2',
46
     * ]
47
     * ```
48
     *
49
     * It matches if the environment name is `env1` *or* **not** `env2`.
50
     */
51
    public $env;
52
53
    /**
54
     * @var string full path to a directory where [[Config]] will store its cached configs.
55
     */
56
    public $path;
57
58
    /**
59
     * @var bool whether the file is required.
60
     */
61
    public $required = true;
62
63
    /**
64
     * @var bool whether to look for a local config in addition to a main one.
65
     *
66
     * For example, if [[$enableLocal]] is `true` and a main config file name is `NAME.EXT`,
67
     * [[Config]] will also look for the `NAME-local.EXT` file.
68
     */
69
    public $enableLocal = true;
70
71
    /**
72
     * @var Config [[Config]] instance.
73
     */
74
    protected $config;
75
76
    /**
77
     * @var Storage internal config object instance.
78
     */
79
    protected $storage;
80
81
    /**
82
     * Creates a new Loader object.
83
     * @param Config $configObject current [[Config]] instance.
84
     * @param Storage $storage internal config object instance.
85
     * @param array $config name-value pairs that will be used to initialize the object properties.
86
     */
87 62
    public function __construct(Config $configObject, Storage $storage, $config = [])
88
    {
89 62
        $this->config = $configObject;
90 62
        $this->storage = $storage;
91 62
        parent::__construct($config);
92 62
    }
93
94
    /**
95
     * Compiles resolved files into the internal config object.
96
     */
97
    abstract public function compile();
98
99
    /**
100
     * Loads resolved files into the internal config object.
101
     */
102
    abstract public function load();
103
104
    /**
105
     * Resolves the current configuration into config file pathes.
106
     * @return string[] config file pathes.
107
     * @throws ConfigNotFoundException
108
     */
109 49
    public function resolveFiles()
110
    {
111 49
        if (!$this->isAllowed()) {
112 44
            return [];
113
        }
114
115 49
        $nonLocalFileCount = 0;
116 49
        $files = [];
117 49
        foreach ($this->config->dirs as $path) {
118 49
            $filePath = $this->config->configDir . '/' . strtr($path . '/' . $this->path, [
119 49
                '{tier}' => $this->config->tier,
120 49
                '{env}' => $this->config->env,
121 49
            ]);
122 49
            if (!is_file($filePath)) {
123 46
                continue;
124
            }
125
126 47
            $files[] = $filePath;
127 47
            \Yii::trace("Loaded config file: '{$filePath}'", __METHOD__);
128 47
            $nonLocalFileCount++;
129 47
            if (!$this->enableLocal) {
130 4
                continue;
131
            }
132
133 44
            $filePath = $this->makeLocalPath($filePath);
134 44
            if (is_file($filePath)) {
135 38
                $files[] = $filePath;
136 38
                \Yii::trace("Loaded config file: '{$filePath}'", __METHOD__);
137 38
            }
138 49
        }
139 49
        if ($this->required && $nonLocalFileCount === 0) {
140 2
            throw new ConfigNotFoundException("The '{$this->path}' config file is required but not available.");
141
        }
142
143 47
        return $files;
144
    }
145
146
    /**
147
     * Returns a file path with a "-local" suffix.
148
     * @param string $path the file path.
149
     * @return string file path with a "-local" suffix.
150
     */
151 44
    protected function makeLocalPath($path)
152
    {
153 44
        $extension = '.' . pathinfo($path, PATHINFO_EXTENSION);
154 44
        if ($extension !== '.') {
155 44
            $path = mb_substr($path, 0, -1 * mb_strlen($extension, 'UTF-8'), 'UTF-8');
156 44
        }
157 44
        $path .= '-local';
158 44
        if ($extension !== '.') {
159 44
            $path .= $extension;
160 44
        }
161 44
        return $path;
162
    }
163
164
    /**
165
     * Returns whether the configuration allows to load this config.
166
     * @return bool whether the configuration allows to load this config.
167
     */
168 49
    protected function isAllowed()
169
    {
170 49
        if (!$this->isValueAllowed($this->config->tier, $this->tier)) {
171 1
            return false;
172
        }
173
174 49
        if (!$this->isValueAllowed($this->config->env, $this->env)) {
175 44
            return false;
176
        }
177
178 49
        return true;
179
    }
180
181
    /**
182
     * Returns whether the value is in the list of allowed values.
183
     * @param mixed $value the value to be tested.
184
     * @param mixed $allowedValues the list of allowed values.
185
     * @return bool whether the value is in the list of allowed values.
186
     */
187 49
    protected function isValueAllowed($value, $allowedValues)
188
    {
189 49
        if ($allowedValues === null) {
190 47
            return true;
191
        }
192
193 46
        foreach ((array) $allowedValues as $allowedValue) {
194 46
            if (strpos($allowedValue, '!') === 0) {
195 44
                if (substr($allowedValue, 1) !== $value) {
196 1
                    return true;
197
                }
198 43
            } else {
199 46
                if ($allowedValue === $value) {
200 45
                    return true;
201
                }
202
            }
203 44
        }
204 44
        return false;
205
    }
206
}
207