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

ConfigManager::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 4
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
        return true;
115
    }
116
117
    /**
118
     * @inheritdoc
119
     */
120
    public function get($path)
121
    {
122
        /** @var ConfigInterface $configDefinition */
123
        $configDefinition = $this->configTree->get($path);
124
        if (is_null($configDefinition)) {
125
            throw new UnhandledConfigurationException("'{$path}' is not handled by the config manager!");
126
        }
127
128
        $configs = $this->getAllConfigs($configDefinition->getScope());
129
        $value = $configs->get($path);
130
131
        if (is_null($value)) {
132
            return $configDefinition->getDefaultValue();
133
        }
134
135
        return $value;
136
    }
137
138
    /**
139
     * @inheritdoc
140
     */
141
    public function getAllConfigs($scope) : AssociativeArray
142
    {
143
        $this->loadConfigValues();
144
145
        switch ($scope) {
146
            case ConfigInterface::SCOPE_SERVER:
147
                return $this->serverConfigurations;
148
            case ConfigInterface::SCOPE_KEY:
149
                return $this->keyConfigurations;
150
            case ConfigInterface::SCOPE_GLOBAL:
151
            default:
152
                return $this->globalConfigurations;
153
        }
154
    }
155
156
    /**
157
     * Register a config to be handled by the config manager.
158
     *
159
     * @param ConfigInterface $config
160
     * @param $id
161
     */
162
    public function registerConfig(ConfigInterface $config, $id)
163
    {
164
        $this->configurationDefinitions[spl_object_hash($config)] = $config;
165
        $this->configurationIds[spl_object_hash($config)] = $id;
166
        $this->configTree->set($config->getPath(), $config);
167
    }
168
169
    /**
170
     * @inheritdoc
171
     */
172
    public function loadConfigValues()
173
    {
174
        if (!is_null($this->globalConfigurations)) {
175
            return;
176
        }
177
178
        $this->globalConfigurations = new AssociativeArray();
179
        $this->keyConfigurations = new AssociativeArray();
180
        $this->serverConfigurations = new AssociativeArray();
181
182
        /** @var AssociativeArray[] $configs */
183
        $configs = [
184
            'global' => $this->globalConfigurations,
185
            'key' => $this->keyConfigurations,
186
            'server-' . $this->gameDataStorage->getSystemInfo()->serverLogin => $this->serverConfigurations,
187
        ];
188
189
        foreach ($configs as $filekey => $config) {
190
            $this->logger->debug(
191
                'Loading config file',
192
                ['file' => "config-$filekey.json"]
193
            );
194
195
            /** @var File $file */
196
            if ($this->filesystem->has("config-$filekey.json")) {
197
                $file = $this->filesystem->get("config-$filekey.json");
198
199
                $values = json_decode($file->read(), true);
200
                $config->setData($values);
201
            }
202
        }
203
    }
204
205
    /**
206
     * @inheritdoc
207
     */
208
    public function saveConfigValues()
209
    {
210
        /** @var AssociativeArray[] $configs */
211
        $configs = [
212
            'global' => $this->globalConfigurations,
213
            'key' => $this->keyConfigurations,
214
            'server-' . $this->gameDataStorage->getSystemInfo()->serverLogin => $this->serverConfigurations,
215
        ];
216
217
        foreach ($configs as $filekey => $config) {
218
            $this->logger->debug(
219
                'Saving config file',
220
                ['file' => "config-$filekey.json"]
221
            );
222
223
            // TODO get only non default values.
224
            $encoded = json_encode($config->getArray(), JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
225
            $this->filesystem->put("config-$filekey.json", $encoded);
226
        }
227
    }
228
229
    /**
230
     * @inheritdoc
231
     */
232
    public function getConfigDefinitionTree(): AssociativeArray
233
    {
234
        return $this->configTree;
235
    }
236
}
237