Completed
Pull Request — master (#88)
by
unknown
04:02
created

Config::__construct()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4.0218

Importance

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