Completed
Pull Request — master (#88)
by
unknown
03:53
created

Config::replaceParameters()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

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