Config::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 1
c 2
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PublishingKit\Config;
6
7
use PublishingKit\Config\Contracts\ConfigContainer;
8
use PublishingKit\Config\Exceptions\ConfigDoesNotExist;
9
use PublishingKit\Config\Exceptions\UnsupportedConfigFileType;
10
use Symfony\Component\Yaml\Exception\ParseException;
11
use Symfony\Component\Yaml\Yaml;
12
13
/**
14
 * @psalm-consistent-constructor
15
 * @psalm-consistent-templates
16
 * @psalm-immutable
17
 * @template ConfigArray as array<array-key, scalar|array>
18
 */
19
class Config implements ConfigContainer
20
{
21
    /**
22
     * @var array
23
     * @psalm-var ConfigArray
24
     */
25
    private $config;
26 60
27
    /**
28 60
     * @param array $config
29 60
     * @psalm-param ConfigArray $config
30
     */
31 15
    public function __construct(array $config)
32
    {
33 15
        $this->config = $config;
34
    }
35
36 3
    public static function fromFile(string $path): ConfigContainer
37
    {
38 3
        return new static(self::getFile($path));
39 3
    }
40 3
41
    /**
42 3
     * @psalm-param $files array<array-key, string> Array of file paths
43
     */
44
    public static function fromFiles(array $files): ConfigContainer
45 3
    {
46
        $configs = [];
47 3
        /** @var string **/
48
        foreach ($files as $file) {
49
            $configs = array_merge($configs, self::getFile($file));
50 18
        }
51
        return new static($configs);
52 18
    }
53 3
54
    /**
55
     * @param array $config
56 15
     * @psalm-param array<array-key, scalar|array> $config
57 15
     */
58 6
    public static function __set_state(array $config): ConfigContainer
59 6
    {
60 12
        return new static($config);
61 6
    }
62 6
63 9
    /**
64 3
     * @return array
65 6
     * @psalm-return ConfigArray
66 6
     */
67
    private static function getFile(string $path): array
68 15
    {
69
        if (!$path = realpath($path)) {
70 3
            throw new ConfigDoesNotExist();
71 3
        }
72
        try {
73 12
            $ext = pathinfo($path)['extension'] ?? '';
74
            switch ($ext) {
75
                case 'php':
76 6
                    /** @var array<array-key, scalar|array> **/
77
                    $config = self::parseArrayFile($path);
78 6
                    break;
79
                case 'ini':
80
                    /** @var array<array-key, scalar|array> **/
81 6
                    $config = self::parseIniFile($path);
82
                    break;
83 6
                case 'yml':
84
                case 'yaml':
85
                    /** @var array<array-key, scalar|array> **/
86 6
                    $config = self::parseYamlFile($path);
87
                    break;
88 6
                default:
89
                    throw new UnsupportedConfigFileType($ext);
90
            }
91
        } catch (UnsupportedConfigFileType $e) {
92
            throw $e;
93
        }
94
        return $config;
95 30
    }
96
97 30
    private static function parseArrayFile(string $path): array
98 3
    {
99
        if (!file_exists($path)) {
100 27
            throw new ConfigDoesNotExist();
101 18
        }
102
        /** @var array **/
103 24
        return include $path;
104
    }
105
106 24
    private static function parseIniFile(string $path): array
107
    {
108 24
        if (!file_exists($path)) {
109
            throw new ConfigDoesNotExist();
110
        }
111 3
        /** @var array **/
112
        return parse_ini_file($path, true);
113 3
    }
114
115
    private static function parseYamlFile(string $path): array
116
    {
117
        if (!file_exists($path)) {
118
            throw new ConfigDoesNotExist();
119 3
        }
120
        /** @var array **/
121 3
        return Yaml::parseFile($path);
122
    }
123
124
    /**
125
     * @template T of key-of<ConfigArray>
126
     *
127 3
     * @param string $name
128
     * @psalm-param T $name
129 3
     *
130
     * @return null|scalar|static
131
     *
132
     * @psalm-return null|scalar|static<array<array-key, array|scalar>>
133
     */
134
    public function get(string $name)
135 6
    {
136
        if (!isset($this->config[$name])) {
137 6
            return null;
138 3
        }
139
        /** @var array<array-key, array|scalar>|scalar **/
140 6
        $config = $this->config[$name];
141 3
        if (is_array($config)) {
142
            return new static($config);
143 6
        }
144
        return $config;
145
    }
146
147
    public function __get(string $name)
148
    {
149 3
        return $this->get($name);
150
    }
151 3
152
    public function has(string $name): bool
153
    {
154
        return isset($this->config[$name]);
155
    }
156 3
157
    /**
158 3
     * {@inheritDoc}
159
     */
160 3
    public function count()
161
    {
162 3
        return count($this->config);
163
    }
164
165
    /**
166
     * {@inheritDoc}
167
     * @psalm-param array-key $offset
168 6
     */
169
    public function offsetExists($offset)
170 6
    {
171
        return isset($this->config[$offset]);
172
    }
173 2
174
    /**
175
     * {@inheritDoc}
176
     * @param mixed $offset
177
     * @psalm-return Config|scalar|null
178
     */
179
    public function offsetGet($offset)
180
    {
181
        if (!is_scalar($offset)) {
182
            throw new ConfigDoesNotExist();
183
        }
184
        /** @psalm-assert scalar $offset **/
185
        if (!isset($this->config[$offset])) {
186
            return null;
187
        }
188
        if (is_array($this->config[$offset])) {
189
            /** @var array<array-key, scalar|array> **/
190
            $config = $this->config[$offset];
191
            return new static($config);
192
        }
193
        /** @var scalar **/
194
        return $this->config[$offset];
195
    }
196
197
    /**
198
     * {@inheritDoc}
199
     */
200
    public function offsetSet($offset, $value)
201
    {
202
    }
203
204
    /**
205
     * {@inheritDoc}
206
     */
207
    public function offsetUnset($offset)
208
    {
209
    }
210
211
    public function toArray(): array
212
    {
213
        return $this->config;
214
    }
215
216
    /**
217
     * {@inheritDoc}
218
     */
219
    public function getIterator()
220
    {
221
        return new ConfigIterator($this->config);
222
    }
223
}
224