Completed
Pull Request — develop (#79)
by
unknown
44:24 queued 32:59
created

Config::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 3

Importance

Changes 24
Bugs 3 Features 9
Metric Value
c 24
b 3
f 9
dl 0
loc 22
ccs 14
cts 14
cp 1
rs 9.2
cc 3
eloc 12
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Noodlehaus;
4
5
use Noodlehaus\Exception\FileNotFoundException;
6
use Noodlehaus\Exception\UnsupportedFormatException;
7
use Noodlehaus\Exception\EmptyDirectoryException;
8
9
/**
10
 * Config
11
 *
12
 * @package    Config
13
 * @author     Jesus A. Domingo <[email protected]>
14
 * @author     Hassan Khan <[email protected]>
15
 * @link       https://github.com/noodlehaus/config
16
 * @license    MIT
17
 */
18
class Config extends AbstractConfig
19
{
20
    /**
21
     * All file formats supported by Config
22
     *
23
     * @var array
24
     */
25
    private $supportedFileParsers = array(
26
        'Noodlehaus\FileParser\Php',
27
        'Noodlehaus\FileParser\Ini',
28
        'Noodlehaus\FileParser\Json',
29
        'Noodlehaus\FileParser\Xml',
30
        'Noodlehaus\FileParser\Yaml',
31
        'Noodlehaus\FileParser\Neon'
32
    );
33
34
    /**
35
     * Static method for loading a Config instance.
36
     *
37
     * @param  string|array $path
38
     *
39
     * @return Config
40 3
     */
41
    public static function load($path)
42 3
    {
43
        return new static($path);
44
    }
45
46
    /**
47
     * Loads a supported configuration file format.
48
     *
49
     * @param  string|array $path
50
     *
51
     * @throws EmptyDirectoryException    If `$path` is an empty directory
52 33
     */
53
    public function __construct($path)
54 33
    {
55 24
        $paths      = $this->getValidPath($path);
56
        $this->data = array();
57 24
58
        foreach ($paths as $path) {
59
60 24
            // Get file information
61 24
            $info      = pathinfo($path);
62 24
            $parts = explode('.', $info['basename']);
63 24
            $extension = array_pop($parts);
64 3
            if ($extension === 'dist') {
65 3
                $extension = array_pop($parts);
66 24
            }
67
            $parser    = $this->getParser($extension);
68
69 21
            // Try and load file
70 21
            $this->data = array_replace_recursive($this->data, (array) $parser->parse($path));
71
        }
72 21
73 21
        parent::__construct($this->data);
74
    }
75
76
    /**
77
     * Gets a parser for a given file extension
78
     *
79
     * @param  string $extension
80
     *
81
     * @return Noodlehaus\FileParser\FileParserInterface
82
     *
83
     * @throws UnsupportedFormatException If `$path` is an unsupported file format
84 27
     */
85
    private function getParser($extension)
86 27
    {
87
        $parser = null;
88 27
89 27
        foreach ($this->supportedFileParsers as $fileParser) {
90
            $tempParser = new $fileParser;
91 27
92 21
            if (in_array($extension, $tempParser->getSupportedExtensions($extension))) {
93 21
                $parser = $tempParser;
94
                continue;
95
            }
96 27
97
        }
98
99 27
        // If none exist, then throw an exception
100 6
        if ($parser === null) {
101
            throw new UnsupportedFormatException('Unsupported configuration format');
102
        }
103 21
104
        return $parser;
105
    }
106
107
    /**
108
     * Gets an array of paths
109
     *
110
     * @param  array $path
111
     *
112
     * @return array
113
     *
114
     * @throws FileNotFoundException   If a file is not found at `$path`
115 12
     */
116
    private function getPathFromArray($path)
117 12
    {
118
        $paths = array();
119 12
120
        foreach ($path as $unverifiedPath) {
121
            try {
122
                // Check if `$unverifiedPath` is optional
123
                // If it exists, then it's added to the list
124 12
                // If it doesn't, it throws an exception which we catch
125 12
                if ($unverifiedPath[0] !== '?') {
126 12
                    $paths = array_merge($paths, $this->getValidPath($unverifiedPath));
127
                    continue;
128 6
                }
129 6
                $optionalPath = ltrim($unverifiedPath, '?');
130
                $paths = array_merge($paths, $this->getValidPath($optionalPath));
131 9
132
            } catch (FileNotFoundException $e) {
133 6
                // If `$unverifiedPath` is optional, then skip it
134 3
                if ($unverifiedPath[0] === '?') {
135
                    continue;
136
                }
137 3
                // Otherwise rethrow the exception
138
                throw $e;
139 9
            }
140
        }
141 9
142
        return $paths;
143
    }
144
145
    /**
146
     * Checks `$path` to see if it is either an array, a directory, or a file
147
     *
148
     * @param  string|array $path
149
     *
150
     * @return array
151
     *
152
     * @throws EmptyDirectoryException If `$path` is an empty directory
153
     *
154
     * @throws FileNotFoundException   If a file is not found at `$path`
155 30
     */
156
    private function getValidPath($path)
157
    {
158 30
        // If `$path` is array
159 12
        if (is_array($path)) {
160
            return $this->getPathFromArray($path);
161
        }
162
163 30
        // If `$path` is a directory
164 6
        if (is_dir($path)) {
165 6
            $paths = glob($path . '/*.*');
166 3
            if (empty($paths)) {
167
                throw new EmptyDirectoryException("Configuration directory: [$path] is empty");
168 3
            }
169
            return $paths;
170
        }
171
172 24
        // If `$path` is not a file, throw an exception
173 9
        if (!file_exists($path)) {
174
            throw new FileNotFoundException("Configuration file: [$path] cannot be found");
175 21
        }
176
        return array($path);
177
    }
178
}
179