Passed
Pull Request — latest (#598)
by Colin
16:46 queued 13:48
created

Configuration::setByPath()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 17
ccs 10
cts 10
cp 1
rs 9.9666
c 0
b 0
f 0
cc 4
nc 5
nop 2
crap 4

2 Methods

Rating   Name   Duplication   Size   Complexity  
A Configuration::exists() 0 9 3
A Configuration::reader() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the league/commonmark package.
7
 *
8
 * (c) Colin O'Dell <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace League\CommonMark\Configuration;
15
16
use Dflydev\DotAccessData\Data;
17
use Dflydev\DotAccessData\Exception\InvalidPathException;
18
use Dflydev\DotAccessData\Exception\MissingPathException;
19
use League\CommonMark\Exception\InvalidConfigurationException;
20
use Nette\Schema\Elements\Structure;
21
use Nette\Schema\Expect;
22
use Nette\Schema\Processor;
23
use Nette\Schema\Schema;
24
use Nette\Schema\ValidationException;
25
26
final class Configuration implements ConfigurationBuilderInterface, ConfigurationInterface
27
{
28
    /**
29
     * @var Data
30
     *
31
     * @psalm-readonly
32
     */
33
    private $userConfig;
34
35
    /** @var array<string, Schema> */
36
    private $configSchemas = [];
37
38
    /** @var Data|null */
39
    private $finalConfig;
40
41
    /** @var array<string, mixed> */
42
    private $cache = [];
43
44
    /**
45
     * @var ConfigurationInterface
46
     *
47
     * @psalm-readonly
48
     */
49
    private $reader;
50
51
    /**
52
     * @param array<string, Schema> $baseSchemas
53
     */
54 3333
    public function __construct(array $baseSchemas = [])
55
    {
56 3333
        $this->configSchemas = $baseSchemas;
57 3333
        $this->userConfig    = new Data();
58
59 3333
        $this->reader = new ReadOnlyConfiguration($this);
60 3333
    }
61
62
    /**
63
     * Registers a new configuration schema at the given top-level key
64
     */
65 3207
    public function addSchema(string $key, Schema $schema): void
66
    {
67 3207
        $this->invalidate();
68
69 3207
        if ($schema instanceof Structure) {
70 3198
            $schema->castTo('array');
71
        }
72
73 3207
        $this->configSchemas[$key] = $schema;
74 3207
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 3306
    public function merge(array $config = []): void
80
    {
81 3306
        $this->invalidate();
82
83 3306
        $this->userConfig->import($config, Data::REPLACE);
84 3306
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 21
    public function set(string $key, $value): void
90
    {
91 21
        $this->invalidate();
92
93 21
        $this->userConfig->set($key, $value);
94 21
    }
95
96
    /**
97
     * {@inheritDoc}
98
     */
99 3219
    public function get(string $key)
100
    {
101 3219
        if ($this->finalConfig === null) {
102 3219
            $this->finalConfig = $this->build();
103 2997
        } elseif (\array_key_exists($key, $this->cache)) {
104 936
            return $this->cache[$key];
105
        }
106
107
        try {
108 3192
            return $this->cache[$key] = $this->finalConfig->get($key);
109 6
        } catch (InvalidPathException | MissingPathException $ex) {
110 6
            throw InvalidConfigurationException::missingOption($key);
111
        }
112
    }
113
114 3
    public function exists(string $key): bool
115
    {
116 3
        if ($this->finalConfig === null) {
117 3
            $this->finalConfig = $this->build();
118 3
        } elseif (\array_key_exists($key, $this->cache)) {
119
            return true;
120
        }
121
122 3
        return $this->finalConfig->has($key);
123
    }
124
125 3222
    public function reader(): ConfigurationInterface
126
    {
127 3222
        return $this->reader;
128
    }
129
130 3327
    private function invalidate(): void
131
    {
132 3327
        $this->cache       = [];
133 3327
        $this->finalConfig = null;
134 3327
    }
135
136
    /**
137
     * Applies the schema against the configuration to return the final configuration
138
     */
139 3222
    private function build(): Data
140
    {
141
        try {
142 3222
            $schema    = Expect::structure($this->configSchemas)->castTo('array');
143 3222
            $processor = new Processor();
144 3222
            $config    = new Data($processor->process($schema, $this->userConfig->export()));
0 ignored issues
show
Bug introduced by
It seems like $processor->process($sch...->userConfig->export()) can also be of type null; however, parameter $data of Dflydev\DotAccessData\Data::__construct() does only seem to accept array, 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

144
            $config    = new Data(/** @scrutinizer ignore-type */ $processor->process($schema, $this->userConfig->export()));
Loading history...
145
146 3195
            return $this->finalConfig = $config;
147 33
        } catch (ValidationException $ex) {
148 33
            throw InvalidConfigurationException::fromValidation($ex);
149
        }
150
    }
151
}
152