Completed
Push — master ( b06bec...8d39d6 )
by Xeriab
03:49
created

Konfig::setFileParsers()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 0
cts 16
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 13
nc 4
nop 1
crap 12
1
<?php
2
3
/**
4
 * Konfig
5
 *
6
 * Yet another simple configuration loader library.
7
 *
8
 * @author  Xeriab Nabil (aka KodeBurner) <[email protected]>
9
 * @license https://raw.github.com/xeriab/konfig/master/LICENSE MIT
10
 * @link    https://xeriab.github.io/projects/konfig
11
 */
12
13
namespace Exen\Konfig;
14
15
use Exen\Konfig\Exception\Exception;
16
use Exen\Konfig\Exception\EmptyDirectoryException;
17
use Exen\Konfig\Exception\FileNotFoundException;
18
use Exen\Konfig\Exception\UnsupportedFileFormatException;
19
20
use Exen\Konfig\Arr;
21
22
final class Konfig extends AbstractKonfig
23
{
24
    /**
25
     * @var FileParser[] $fileParsers Array of file parsers objects
26
     * @since 0.1.0
27
     */
28
    protected $fileParsers;
29
30
    /**
31
     * Stores loaded configuration files
32
     *
33
     * @var array $loadedFiles Array of loaded configuration files
34
     * @since 0.1.0
35
     */
36
    protected static $loadedFiles = [];
37
    
38
    static protected $loadedData = null;
39
40
    /**
41
     * Loads a supported configuration file format.
42
     *
43
     * @param  string|array|mixed $path String file | configuration array | Konfig instance
44
     * @throws EmptyDirectoryException If `$path` is an empty directory
45
     */
46 33
    public function __construct($path = null, array $parsers = [])
47
    {
48 33
        $this->setFileParsers($parsers);
49
50 33
        $paths = $this->getValidPath($path);
51
52 24
        $this->data = [];
53
54 24
        foreach ($paths as $path) {
55
            // Get file information
56 24
            $info = pathinfo($path);
57
            // $info  = pathinfo($path, PATHINFO_EXTENSION);
58 24
            $parts = explode('.', $info['basename']);
59 24
            $ext = array_pop($parts);
60
61 24
            if ($ext === 'dist') {
62 3
                $ext = array_pop($parts);
63 2
            }
64
65 24
            $parser = $this->getParser($ext);
66
67
            // Try and load file
68 21
            $this->data = array_replace_recursive($this->data, (array) $parser->parse($path));
69
70 21
            self::$loadedFiles[$path] = true;
71 14
        }
72
        
73 21
        self::$loadedData = $this->data;
74
75 21
        parent::__construct($this->data);
76 21
    }
77
78
    /**
79
     * Static method for loading a Konfig instance.
80
     *
81
     * @param  string|array|mixed $path string file | configuration array | Konfig instance
82
     * @param  array $parsers Parsers to use with Konfig
83
     * @return Konfig
84
     */
85 3
    public static function load($path = null, array $parsers = [])
86
    {
87 3
        return new static($path, $parsers);
88
    }
89
90
    /**
91
     * Static method for getting loaded Konfig files.
92
     *
93
     * @return array
94
     */
95
    public static function loaded()
96
    {
97
        return self::$loadedFiles;
98
    }
99
100
    /**
101
     * Static method for getting all Konfig keys.
102
     *
103
     * @codeCoverageIgnore
104
     * @return array
105
     */
106
    public static function keys()
107
    {
108
        return Arr::recursiveKeys(self::$loadedData);
109
    }
110
111
    /**
112
     * @return FileParser[]
113
     * @since 0.1.0
114
     */
115
    public function getFileParsers()
116
    {
117
        return $this->fileParsers;
118
    }
119
120
    /**
121
     * @return void
122
     * @since 0.1.0
123
     */
124
    protected function addFileParser(FileParser $fileParser)
125
    {
126
        $this->fileParsers[] = $fileParser;
127
    }
128
129
    /**
130
     * @return void
131
     * @since 0.1.0
132
     */
133
    protected function setFileParsers(array $fileParsers = [])
134
    {
135
        if (empty($fileParsers)) {
136
            $fileParsers = [
137
                new FileParser\Xml(),
138
                new FileParser\Ini(),
139
                new FileParser\Json(),
140
                new FileParser\Yaml(),
141
                new FileParser\Neon(),
142
                new FileParser\Toml(),
143
                new FileParser\Php(),
144
            ];
145
        }
146
147
        $this->fileParsers = [];
148
149
        foreach ($fileParsers as $fileParser) {
150
            $this->addFileParser($fileParser);
151
        }
152
    }
153
154
    /**
155
     * Gets a parser for a given file extension
156
     *
157
     * @param  string $ext File extension
158
     * @return Konfig\FileParser
159
     * @throws Exception If `$ext` is empty
160
     * @throws UnsupportedFileFormatException If `$path` is an unsupported file format
161
     */
162 27
    private function getParser($ext = null)
163
    {
164 27
        $parser = null;
165
166 27
        if (empty($ext)) {
167
            throw new Exception('Files with empty extensions are not allowed');
168
        }
169
170 27
        $fileParsers = $this->getFileParsers();
171
172 27
        foreach ($fileParsers as $fileParser) {
173 27
            if (in_array($ext, $fileParser->getSupportedFileExtensions(), true)) {
174 21
                $parser = $fileParser;
175 23
                break;
176
            }
177 18
        }
178
179
        // If none exist, then throw an exception
180 27
        if (is_null($parser)) {
181 6
            throw new UnsupportedFileFormatException('Unsupported configuration format');
182
        }
183
184 21
        return $parser;
185
    }
186
187
    /**
188
     * Gets an array of paths
189
     *
190
     * @param array $path Path to analyze and handle
191
     * @return array
192
     * @throws FileNotFoundException If a file is not found in `$path`
193
     */
194
    private function pathFromArray($path)
195
    {
196
        $paths = [];
197
198
        foreach ($path as $unverifiedPath) {
199
            try {
200
                // Check if `$unverifiedPath` is optional
201
                // If it exists, then it's added to the list
202
                // If it doesn't, it throws an exception which we catch
203
                if ($unverifiedPath[0] !== '?') {
204
                    $paths = array_merge($paths, $this->getValidPath($unverifiedPath));
205
                    continue;
206
                }
207
208
                $optionalPath = ltrim($unverifiedPath, '?');
209
210
                $paths = array_merge($paths, $this->getValidPath($optionalPath));
211
            } catch (FileNotFoundException $e) {
212
                // If `$unverifiedPath` is optional, then skip it
213
                if ($unverifiedPath[0] === '?') {
214
                    continue;
215
                }
216
217
                // Otherwise rethrow the exception
218
                throw $e;
219
            }
220
        }
221
222
        return $paths;
223
    }
224
225
    /**
226
     * Checks `$path` to see if it is either an array, a directory, or a file
227
     *
228
     * @param  string|array $path Path to analyze and handle
229
     * @return array
230
     * @throws EmptyDirectoryException If `$path` is an empty directory
231
     * @throws FileNotFoundException If a file is not found at `$path`
232
     */
233 30
    private function getValidPath($path)
234
    {
235
        // If `$path` is array
236 30
        if (is_array($path)) {
237 12
            return $this->pathFromArray($path);
238
        }
239
240
        // If `$path` is a directory
241 30
        if (is_dir($path)) {
242 6
            $paths = glob($path . '/*.*');
243
244 6
            if (empty($paths)) {
245 3
                throw new EmptyDirectoryException("Configuration directory: [$path] is empty");
246
            }
247
248 3
            return $paths;
249
        }
250
251
        // If `$path` is not a file, throw an exception
252 24
        if (!file_exists($path)) {
253 9
            throw new FileNotFoundException("Configuration file: [$path] cannot be found");
254
        }
255
256 21
        return [$path];
257
    }
258
259
    /**
260
     * @return string
261
     * @codeCoverageIgnore
262
     * @since 0.1.2
263
     */
264
    public function __toString()
265
    {
266
        return 'Exen\Konfig\Konfig' . PHP_EOL;
267
    }
268
}
269
270
// END OF ./src/Konfig.php FILE
271