Completed
Push — 7.4 ( abf332 )
by Nikolaos
16:13
created

Config::path()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 0
cts 23
cp 0
rs 8.8337
c 0
b 0
f 0
cc 6
nc 6
nop 3
crap 42
1
<?php
2
3
/**
4
 * This file is part of the Phalcon Framework.
5
 *
6
 * (c) Phalcon Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Phalcon;
15
16
use Phalcon\Config\Exception as ConfigException;
17
18
use function array_shift;
19
use function explode;
20
use function is_array;
21
use function is_int;
22
use function is_object;
23
use function method_exists;
24
25
/**
26
 * Class Config
27
 *
28
 * @property string|null $pathDelimiter
29
 */
30
class Config extends Collection
31
{
32
    public const DEFAULT_PATH_DELIMITER = ".";
33
34
    /**
35
     * @var string|null
36
     */
37
    protected $pathDelimiter = null;
38
39
    /**
40
     * Gets the default path delimiter
41
     *
42
     * @return string
43
     */
44
    public function getPathDelimiter(): string
45
    {
46
        if (null === $this->pathDelimiter) {
47
            $this->pathDelimiter = self::DEFAULT_PATH_DELIMITER;
48
        }
49
50
        return $this->pathDelimiter;
51
    }
52
53
    /**
54
     * Merges a configuration into the current one
55
     *
56
     * @param array|object|Config $toMerge
57
     *
58
     * @return Config
59
     * @throws ConfigException
60
     */
61
    public function merge($toMerge): Config
62
    {
63
        if (is_array($toMerge)) {
64
            $config = new Config($toMerge);
65
        } elseif (is_object($toMerge) && $toMerge instanceof Config) {
66
            $config = $toMerge;
67
        } else {
68
            throw new ConfigException(
69
                "Invalid data type for merge."
70
            );
71
        }
72
73
        $source = $this->toArray();
74
        $target = $config->toArray();
75
        $result = $this->internalMerge($source, $target);
76
77
        $this->clear();
78
        $this->init($result);
79
80
        return $this;
81
    }
82
83
    /**
84
     * Returns a value from current config using a dot separated path.
85
     *
86
     * @param string      $path
87
     * @param mixed|null  $defaultValue
88
     * @param string|null $delimiter
89
     *
90
     * @return mixed|null
91
     */
92
    public function path(string $path, $defaultValue = null, string $delimiter = null)
93
    {
94
        if ($this->has($path)) {
95
            return $this->get($path);
96
        }
97
98
        $delimiter = $this->checkDelimiter($delimiter);
99
        $keys      = explode($delimiter, $path);
100
        $config    = clone $this;
101
102
        while (!empty($keys)) {
103
            $key = array_shift($keys);
104
105
            if (!$config->has($key)) {
106
                break;
107
            }
108
109
            if (empty($keys)) {
110
                return $config->get($key);
111
            }
112
113
            $config = $config->get($key);
114
            if (empty($config)) {
115
                break;
116
            }
117
        }
118
119
        return $defaultValue;
120
    }
121
122
    /**
123
     * Sets the default path delimiter
124
     *
125
     * @param string|null $delimiter
126
     *
127
     * @return Config
128
     */
129
    public function setPathDelimiter(string $delimiter = null): Config
130
    {
131
        $this->pathDelimiter = $delimiter;
132
133
        return $this;
134
    }
135
136
    /**
137
     * Converts recursively the object to an array
138
     *
139
     * @return array
140
     */
141
    public function toArray(): array
142
    {
143
        $results = [];
144
        $data    = parent::toArray();
145
146
        foreach ($data as $key => $value) {
147
            if (
148
                is_object($value) &&
149
                method_exists($value, "toArray")
150
            ) {
151
                $value = $value->toArray();
152
            }
153
154
            $results[$key] = $value;
155
        }
156
157
        return $results;
158
    }
159
160
    /**
161
     * Performs a merge recursively
162
     *
163
     * @param array $source
164
     * @param array $target
165
     *
166
     * @return array
167
     */
168
    final protected function internalMerge(array $source, array $target): array
169
    {
170
        foreach ($target as $key => $value) {
171
            if (
172
                is_array($value) &&
173
                isset($source[$key]) &&
174
                is_array($source[$key])
175
            ) {
176
                $source[$key] = $this->internalMerge($source[$key], $value);
177
            } elseif (is_int($key)) {
178
                $source[] = $value;
179
            } else {
180
                $source[$key] = $value;
181
            }
182
        }
183
184
        return $source;
185
    }
186
187
    /**
188
     * Sets the collection data
189
     *
190
     * @param mixed $element
191
     * @param mixed $value
192
     */
193
    protected function setData($element, $value): void
194
    {
195
        $element = (string) $element;
196
        $key     = ($this->insensitive) ? mb_strtolower($element) : $element;
197
198
        $this->lowerKeys[$key] = $element;
199
200
        if (is_array($value)) {
201
            $data = new Config($value);
202
        } else {
203
            $data = $value;
204
        }
205
206
        $this->data[$element] = $data;
207
    }
208
209
    /**
210
     * @param mixed $delimiter
211
     *
212
     * @return string
213
     */
214
    private function checkDelimiter($delimiter): string
215
    {
216
        if (empty($delimiter)) {
217
            return $this->getPathDelimiter();
218
        }
219
220
        return $delimiter;
221
    }
222
}
223