Completed
Push — master ( adf7fc...68b7f3 )
by Xeriab
03:51
created

Konfig::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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