Completed
Pull Request — master (#233)
by De Cramer
11:00
created

ConfigManager::set()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 34
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.5806
c 0
b 0
f 0
ccs 0
cts 26
cp 0
cc 4
eloc 18
nc 3
nop 2
crap 20
1
<?php
2
3
namespace eXpansion\Framework\Config\Services;
4
5
use eXpansion\Framework\Config\Exception\UnhandledConfigurationException;
6
use eXpansion\Framework\Config\Model\ConfigInterface;
7
use eXpansion\Framework\Config\Ui\UiInterface;
8
use eXpansion\Framework\Core\Services\Application\DispatcherInterface;
9
10
use eXpansion\Framework\Core\Storage\GameDataStorage;
11
use League\Flysystem\File;
12
use League\Flysystem\Filesystem;
13
use oliverde8\AssociativeArraySimplified\AssociativeArray;
14
use Psr\Log\LoggerInterface;
15
16
/**
17
 * Class ConfigManager
18
 *
19
 * @author    de Cramer Oliver<[email protected]>
20
 * @copyright 2018 eXpansion
21
 * @package eXpansion\Framework\Config\Services
22
 */
23
class ConfigManager implements ConfigManagerInterface
24
{
25
    /** @var DispatcherInterface */
26
    protected $dispatcher;
27
28
    /** @var GameDataStorage */
29
    protected $gameDataStorage;
30
31
    /** @var Filesystem */
32
    protected $filesystem;
33
34
    /** @var LoggerInterface */
35
    protected $logger;
36
37
    /** @var ConfigInterface */
38
    protected $configurationDefinitions = [];
39
40
    /** @var string[] */
41
    protected $configurationIds = [];
42
43
    /** @var AssociativeArray */
44
    protected $configTree;
45
46
    /** @var AssociativeArray */
47
    protected $globalConfigurations;
48
49
    /** @var AssociativeArray */
50
    protected $keyConfigurations;
51
52
    /** @var AssociativeArray */
53
    protected $serverConfigurations;
54
55
    /** @var bool  */
56
    protected $disableDispatch = false;
57
58
    /**
59
     * ConfigManager constructor.
60
     *
61
     * @param DispatcherInterface $dispatcher
62
     */
63
    public function __construct(
64
        DispatcherInterface $dispatcher,
65
        GameDataStorage $gameDataStorage,
66
        Filesystem $filesystem,
67
        LoggerInterface $logger
68
    ) {
69
        $this->dispatcher = $dispatcher;
70
        $this->gameDataStorage = $gameDataStorage;
71
        $this->filesystem = $filesystem;
72
        $this->logger = $logger;
73
74
        $this->configTree = new AssociativeArray();
75
    }
76
77
    /**
78
     * @inheritdoc
79
     */
80
    public function set($path, $value) : bool
81
    {
82
        /** @var ConfigInterface $configDefinition */
83
        $configDefinition = $this->configTree->get($path);
84
        if (is_null($configDefinition)) {
85
            throw new UnhandledConfigurationException("'{$path}' is not handled by the config manager!");
86
        }
87
88
        // Fetch old value for event.
89
        $oldValue = $this->get($path);
90
91
        // Put new value.
92
        $configs = $this->getAllConfigs($configDefinition->getScope());
93
        $configs->set($path, $value);
94
95
        // Dispatch and save changes.
96
        if ($this->disableDispatch || $oldValue === $value) {
97
            $this->logger->debug(
98
                'New conig was set, but no changes, save and dispatch are canceled!',
99
                ['path' => $path]
100
            );
101
            return true;
102
        }
103
104
        $this->saveConfigValues();
105
        $this->dispatcher->dispatch(
106
            'expansion.config.change',
107
            [
108
                'config' => $configDefinition,
109
                'id' => $this->configurationIds[spl_object_hash($configDefinition)],
110
                'oldValue' => $oldValue
111
            ]
112
        );
113
    }
114
115
    /**
116
     * @inheritdoc
117
     */
118
    public function get($path)
119
    {
120
        /** @var ConfigInterface $configDefinition */
121
        $configDefinition = $this->configTree->get($path);
122
        if (is_null($configDefinition)) {
123
            throw new UnhandledConfigurationException("'{$path}' is not handled by the config manager!");
124
        }
125
126
        $configs = $this->getAllConfigs($configDefinition->getScope());
127
        $value = $configs->get($path);
128
129
        if (is_null($value)) {
130
            return $configDefinition->getDefaultValue();
131
        }
132
133
        return $value;
134
    }
135
136
    /**
137
     * @inheritdoc
138
     */
139
    public function getAllConfigs($scope) : AssociativeArray
140
    {
141
        $this->loadConfigValues();
142
143
        switch ($scope) {
144
            case ConfigInterface::SCOPE_SERVER:
145
                return $this->serverConfigurations;
146
            case ConfigInterface::SCOPE_KEY:
147
                return $this->keyConfigurations;
148
            case ConfigInterface::SCOPE_GLOBAL:
149
            default:
150
                return $this->globalConfigurations;
151
        }
152
    }
153
154
    /**
155
     * Register a config to be handled by the config manager.
156
     *
157
     * @param ConfigInterface $config
158
     * @param $id
159
     */
160
    public function registerConfig(ConfigInterface $config, $id)
161
    {
162
        $this->configurationDefinitions[spl_object_hash($config)] = $config;
163
        $this->configurationIds[spl_object_hash($config)] = $id;
164
        $this->configTree->set($config->getPath(), $config);
165
    }
166
167
    /**
168
     * @inheritdoc
169
     */
170
    public function loadConfigValues()
171
    {
172
        if (!is_null($this->globalConfigurations)) {
173
            return;
174
        }
175
176
        $this->globalConfigurations = new AssociativeArray();
177
        $this->keyConfigurations = new AssociativeArray();
178
        $this->serverConfigurations = new AssociativeArray();
179
180
        /** @var AssociativeArray[] $configs */
181
        $configs = [
182
            'global' => $this->globalConfigurations,
183
            'key' => $this->keyConfigurations,
184
            'server-' . $this->gameDataStorage->getSystemInfo()->serverLogin => $this->serverConfigurations,
185
        ];
186
187
        foreach ($configs as $filekey => $config) {
188
            $this->logger->debug(
189
                'Loading config file',
190
                ['file' => "config-$filekey.json"]
191
            );
192
193
            /** @var File $file */
194
            $file = $this->filesystem->get("config-$filekey.json");
195
196
            if ($file->exists()) {
197
                $values = json_decode($file->read(), true);
198
                $config->setData($values);
199
            }
200
        }
201
    }
202
203
    /**
204
     * @inheritdoc
205
     */
206
    public function saveConfigValues()
207
    {
208
        /** @var AssociativeArray[] $configs */
209
        $configs = [
210
            'global' => $this->globalConfigurations,
211
            'key' => $this->keyConfigurations,
212
            'server-' . $this->gameDataStorage->getSystemInfo()->serverLogin => $this->serverConfigurations,
213
        ];
214
215
        foreach ($configs as $filekey => $config) {
216
            $this->logger->debug(
217
                'Saving config file',
218
                ['file' => "config-$filekey.json"]
219
            );
220
221
            $encoded = json_encode($config->getArray(), JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
222
            $this->filesystem->put("config-$filekey.json", $encoded);
223
        }
224
    }
225
226
    /**
227
     * @inheritdoc
228
     */
229
    public function getConfigDefinitionTree(): AssociativeArray
230
    {
231
        return $this->configTree;
232
    }
233
}
234