Config::internalMerge()   A
last analyzed

Complexity

Conditions 6
Paths 4

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 7.8984

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 17
ccs 10
cts 16
cp 0.625
rs 9.2222
c 0
b 0
f 0
cc 6
nc 4
nop 2
crap 7.8984
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 24
    public function getPathDelimiter(): string
45
    {
46 24
        if (null === $this->pathDelimiter) {
47 24
            $this->pathDelimiter = self::DEFAULT_PATH_DELIMITER;
48
        }
49
50 24
        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 26
    public function merge($toMerge): Config
62
    {
63 26
        if (is_array($toMerge)) {
64 1
            $config = new Config($toMerge);
65 25
        } elseif (is_object($toMerge) && $toMerge instanceof Config) {
66 21
            $config = $toMerge;
67
        } else {
68 5
            throw new ConfigException(
69 5
                "Invalid data type for merge."
70
            );
71
        }
72
73 22
        $source = $this->toArray();
74 22
        $target = $config->toArray();
75 22
        $result = $this->internalMerge($source, $target);
76
77 22
        $this->clear();
78 22
        $this->init($result);
79
80 22
        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 18
    public function path(string $path, $defaultValue = null, string $delimiter = null)
93
    {
94 18
        if ($this->has($path)) {
95 6
            return $this->get($path);
96
        }
97
98 18
        $delimiter = $this->checkDelimiter($delimiter);
99 18
        $keys      = explode($delimiter, $path);
100 18
        $config    = clone $this;
101
102 18
        while (!empty($keys)) {
103 18
            $key = array_shift($keys);
104
105 18
            if (!$config->has($key)) {
106 12
                break;
107
            }
108
109 18
            if (empty($keys)) {
110 12
                return $config->get($key);
111
            }
112
113 18
            $config = $config->get($key);
114 18
            if (empty($config)) {
115
                break;
116
            }
117
        }
118
119 12
        return $defaultValue;
120
    }
121
122
    /**
123
     * Sets the default path delimiter
124
     *
125
     * @param string|null $delimiter
126
     *
127
     * @return Config
128
     */
129 12
    public function setPathDelimiter(string $delimiter = null): Config
130
    {
131 12
        $this->pathDelimiter = $delimiter;
132
133 12
        return $this;
134
    }
135
136
    /**
137
     * Converts recursively the object to an array
138
     *
139
     * @return array
140
     */
141 39
    public function toArray(): array
142
    {
143 39
        $results = [];
144 39
        $data    = parent::toArray();
145
146 39
        foreach ($data as $key => $value) {
147
            if (
148 39
                is_object($value) &&
149 39
                method_exists($value, "toArray")
150
            ) {
151 39
                $value = $value->toArray();
152
            }
153
154 39
            $results[$key] = $value;
155
        }
156
157 39
        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 22
    final protected function internalMerge(array $source, array $target): array
169
    {
170 22
        foreach ($target as $key => $value) {
171
            if (
172 22
                is_array($value) &&
173 22
                isset($source[$key]) &&
174 22
                is_array($source[$key])
175
            ) {
176 20
                $source[$key] = $this->internalMerge($source[$key], $value);
177 22
            } elseif (is_int($key)) {
178 4
                $source[] = $value;
179
            } else {
180 19
                $source[$key] = $value;
181
            }
182
        }
183
184 22
        return $source;
185
    }
186
187
    /**
188
     * Sets the collection data
189
     *
190
     * @param mixed $element
191
     * @param mixed $value
192
     */
193 99
    protected function setData($element, $value): void
194
    {
195 99
        $element = (string) $element;
196 99
        $key     = ($this->insensitive) ? mb_strtolower($element) : $element;
197
198 99
        $this->lowerKeys[$key] = $element;
199
200 99
        if (is_array($value)) {
201 98
            $data = new Config($value);
202
        } else {
203 99
            $data = $value;
204
        }
205
206 99
        $this->data[$element] = $data;
207 99
    }
208
209
    /**
210
     * @param mixed $delimiter
211
     *
212
     * @return string
213
     */
214 18
    private function checkDelimiter($delimiter): string
215
    {
216 18
        if (empty($delimiter)) {
217 18
            return $this->getPathDelimiter();
218
        }
219
220
        return $delimiter;
221
    }
222
}
223