1<?php
2
3/*
4 * This file is part of the league/commonmark package.
5 *
6 * (c) Colin O'Dell <colinodell@gmail.com>
7 *
8 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
9 *  - (c) John MacFarlane
10 *
11 * For the full copyright and license information, please view the LICENSE
12 * file that was distributed with this source code.
13 */
14
15namespace League\CommonMark\Util;
16
17final class Configuration implements ConfigurationInterface
18{
19    /** @var array<string, mixed> */
20    private $config;
21
22    /**
23     * @param array<string, mixed> $config
24     */
25    public function __construct(array $config = [])
26    {
27        $this->config = $config;
28    }
29
30    public function merge(array $config = [])
31    {
32        $this->config = \array_replace_recursive($this->config, $config);
33    }
34
35    public function replace(array $config = [])
36    {
37        $this->config = $config;
38    }
39
40    public function get(?string $key = null, $default = null)
41    {
42        if ($key === null) {
43            @\trigger_error('Calling Configuration::get() without a $key is deprecated in league/commonmark 1.6 and will not be allowed in 2.0', \E_USER_DEPRECATED);
44
45            return $this->config;
46        }
47
48        // accept a/b/c as ['a']['b']['c']
49        if (\strpos($key, '/')) {
50            return $this->getConfigByPath($key, $default);
51        }
52
53        if (!isset($this->config[$key])) {
54            return $default;
55        }
56
57        return $this->config[$key];
58    }
59
60    public function set(string $key, $value = null)
61    {
62        if (\func_num_args() === 1) {
63            @\trigger_error('Calling Configuration::set() without a $value is deprecated in league/commonmark 1.6 and will not be allowed in 2.0', \E_USER_DEPRECATED);
64        }
65
66        // accept a/b/c as ['a']['b']['c']
67        if (\strpos($key, '/')) {
68            $this->setByPath($key, $value);
69        }
70
71        $this->config[$key] = $value;
72    }
73
74    public function exists(string $key): bool
75    {
76        return $this->getConfigByPath($key, self::MISSING) !== self::MISSING;
77    }
78
79    /**
80     * @param string      $keyPath
81     * @param string|null $default
82     *
83     * @return mixed|null
84     */
85    private function getConfigByPath(string $keyPath, $default = null)
86    {
87        $keyArr = \explode('/', $keyPath);
88        $data = $this->config;
89        foreach ($keyArr as $k) {
90            if (!\is_array($data) || !isset($data[$k])) {
91                return $default;
92            }
93
94            $data = $data[$k];
95        }
96
97        return $data;
98    }
99
100    /**
101     * @param string      $keyPath
102     * @param string|null $value
103     */
104    private function setByPath(string $keyPath, $value = null): void
105    {
106        $keyArr = \explode('/', $keyPath);
107        $pointer = &$this->config;
108        while (($k = \array_shift($keyArr)) !== null) {
109            if (!\is_array($pointer)) {
110                $pointer = [];
111            }
112
113            if (!isset($pointer[$k])) {
114                $pointer[$k] = null;
115            }
116
117            $pointer = &$pointer[$k];
118        }
119
120        $pointer = $value;
121    }
122}
123