Passed
Push — master ( abee1f...edc958 )
by Kirill
03:08
created

ConfigManager::setDefaults()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Config;
13
14
use Spiral\Config\Exception\ConfigDeliveredException;
15
use Spiral\Config\Exception\PatchException;
16
use Spiral\Core\Container\SingletonInterface;
17
use Spiral\Core\Exception\ConfiguratorException;
18
19
/**
20
 * Load config files, provides container injection and modifies config data on bootloading.
21
 */
22
final class ConfigManager implements ConfiguratorInterface, SingletonInterface
23
{
24
    /** @var LoaderInterface */
25
    private $loader;
26
27
    /** @var bool */
28
    private $strict;
29
30
    /** @var array */
31
    private $data = [];
32
33
    /** @var array */
34
    private $defaults = [];
35
36
    /** @var array */
37
    private $instances = [];
38
39
    /**
40
     * @param LoaderInterface $loader
41
     * @param bool            $strict
42
     */
43
    public function __construct(LoaderInterface $loader, bool $strict = true)
44
    {
45
        $this->loader = $loader;
46
        $this->strict = $strict;
47
    }
48
49
    /**
50
     * Clone state will reset both data and instance cache.
51
     */
52
    public function __clone()
53
    {
54
        $this->data = [];
55
        $this->defaults = [];
56
        $this->instances = [];
57
    }
58
59
    /**
60
     * @inheritdoc
61
     */
62
    public function exists(string $section): bool
63
    {
64
        return isset($this->defaults[$section]) || isset($this->data[$section]) || $this->loader->has($section);
65
    }
66
67
    /**
68
     * @inheritdoc
69
     */
70
    public function setDefaults(string $section, array $data): void
71
    {
72
        if (isset($this->defaults[$section])) {
73
            throw new ConfiguratorException("Unable to set default config `{$section}` more than once.");
74
        }
75
76
        if (isset($this->data[$section])) {
77
            throw new ConfigDeliveredException("Unable to set default config `{$section}`, config has been loaded.");
78
        }
79
80
        $this->defaults[$section] = $data;
81
    }
82
83
    /**
84
     * @inheritdoc
85
     */
86
    public function modify(string $section, PatchInterface $patch): array
87
    {
88
        if (isset($this->instances[$section])) {
89
            if ($this->strict) {
90
                throw new ConfigDeliveredException(
91
                    "Unable to patch config `{$section}`, config object has already been delivered."
92
                );
93
            }
94
95
            unset($this->instances[$section]);
96
        }
97
98
        $data = $this->getConfig($section);
99
100
        try {
101
            return $this->data[$section] = $patch->patch($data);
102
        } catch (PatchException $e) {
103
            throw new PatchException("Unable to modify config `{$section}`.", $e->getCode(), $e);
104
        }
105
    }
106
107
    /**
108
     * @inheritdoc
109
     */
110
    public function getConfig(string $section = null): array
111
    {
112
        if (isset($this->data[$section])) {
113
            return $this->data[$section];
114
        }
115
116
        if (isset($this->defaults[$section])) {
117
            $data = [];
118
            if ($this->loader->has($section)) {
0 ignored issues
show
Bug introduced by
It seems like $section can also be of type null; however, parameter $section of Spiral\Config\LoaderInterface::has() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

118
            if ($this->loader->has(/** @scrutinizer ignore-type */ $section)) {
Loading history...
119
                $data = $this->loader->load($section);
0 ignored issues
show
Bug introduced by
It seems like $section can also be of type null; however, parameter $section of Spiral\Config\LoaderInterface::load() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

119
                $data = $this->loader->load(/** @scrutinizer ignore-type */ $section);
Loading history...
120
            }
121
122
            $data = array_merge($this->defaults[$section], $data);
123
        } else {
124
            $data = $this->loader->load($section);
125
        }
126
127
        return $this->data[$section] = $data;
128
    }
129
130
    /**
131
     * @inheritdoc
132
     */
133
    public function createInjection(\ReflectionClass $class, string $context = null)
134
    {
135
        $config = $class->getConstant('CONFIG');
136
        if (isset($this->instances[$config])) {
137
            return $this->instances[$config];
138
        }
139
140
        return $this->instances[$config] = $class->newInstance($this->getConfig($config));
141
    }
142
}
143