Completed
Push — master ( 877236...2dc251 )
by ARCANEDEV
05:46
created

SettingsManager   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 359
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 99.17%

Importance

Changes 11
Bugs 0 Features 0
Metric Value
wmc 35
c 11
b 0
f 0
lcom 1
cbo 6
dl 0
loc 359
ccs 120
cts 121
cp 0.9917
rs 9

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getDefaultDomain() 0 4 1
A getCacheKey() 0 4 1
A isCached() 0 4 1
A config() 0 4 1
A get() 0 8 1
A set() 0 15 2
A has() 0 12 2
A all() 0 10 2
A delete() 0 21 3
A reset() 0 10 2
C save() 0 29 7
A getChanges() 0 12 1
A grabDomain() 0 10 2
A checkLoaded() 0 10 2
A loadData() 0 11 2
A getCachedSettings() 0 10 2
A flushCachedSettings() 0 6 2
1
<?php namespace Arcanesoft\Settings;
2
3
use Arcanedev\Support\Collection;
4
use Arcanesoft\Settings\Helpers\Arr;
5
use Arcanesoft\Settings\Models\Setting;
6
use Illuminate\Contracts\Cache\Repository as Cache;
7
8
/**
9
 * Class     SettingsManager
10
 *
11
 * @package  Arcanesoft\Settings
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
class SettingsManager implements Contracts\Settings
15
{
16
    /* ------------------------------------------------------------------------------------------------
17
     |  Properties
18
     | ------------------------------------------------------------------------------------------------
19
     */
20
    /**
21
     * The settings data.
22
     *
23
     * @var \Arcanedev\Support\Collection
24
     */
25
    protected $data;
26
27
    /**
28
     * Whether the store has changed since it was last loaded.
29
     *
30
     * @var bool
31
     */
32
    protected $unsaved = false;
33
34
    /**
35
     * Whether the settings data are loaded.
36
     *
37
     * @var bool
38
     */
39
    protected $loaded = false;
40
41
    /**
42
     * The Setting model.
43
     *
44
     * @var Setting
45
     */
46
    private $model;
47
48
    /**
49
     * The cache repository
50
     *
51
     * @var \Illuminate\Contracts\Cache\Repository
52
     */
53
    private $cache;
54
55
    /* ------------------------------------------------------------------------------------------------
56
     |  Constructor
57
     | ------------------------------------------------------------------------------------------------
58
     */
59
    /**
60
     * SettingsManager constructor.
61
     *
62
     * @param  \Arcanesoft\Settings\Models\Setting     $model
63
     * @param  \Illuminate\Contracts\Cache\Repository  $cache
64
     */
65 40
    public function __construct(Setting $model, Cache $cache)
66
    {
67 40
        $this->model = $model;
68 40
        $this->cache = $cache;
69 40
        $this->data  = new Collection;
70 40
    }
71
72
    /* ------------------------------------------------------------------------------------------------
73
     |  Getters & Setters
74
     | ------------------------------------------------------------------------------------------------
75
     */
76
    /**
77
     * Get the settings default domain.
78
     *
79
     * @return string
80
     */
81 36
    protected function getDefaultDomain()
82
    {
83 36
        return $this->config('default-domain', 'default');
84
    }
85
86
    /**
87
     * Get the cache key.
88
     *
89
     * @return string
90
     */
91 40
    protected function getCacheKey()
92
    {
93 40
        return $this->config('cache.key', 'cached_settings');
94
    }
95
96
    /**
97
     * Check if cache is enabled.
98
     *
99
     * @return bool
100
     */
101 40
    protected function isCached()
102
    {
103 40
        return $this->config('cache.enabled', false);
104
    }
105
106
    /**
107
     * Get the config value by key.
108
     *
109
     * @param  string  $key
110
     * @param  mixed   $default
111
     *
112
     * @return mixed
113
     */
114 40
    private function config($key, $default = null)
115
    {
116 40
        return config("arcanesoft.settings.$key", $default);
117
    }
118
119
    /* ------------------------------------------------------------------------------------------------
120
     |  Main Functions
121
     | ------------------------------------------------------------------------------------------------
122
     */
123
    /**
124
     * Get a setting by key.
125
     *
126
     * @param  string      $key
127
     * @param  mixed|null  $default
128
     *
129
     * @return mixed
130
     */
131 24
    public function get($key, $default = null)
132
    {
133 24
        $this->checkLoaded();
134
135 24
        $domain = $this->grabDomain($key);
136
137 24
        return Arr::get($this->data->get($domain, []), $key, $default);
138
    }
139
140
    /**
141
     * Set a setting.
142
     *
143
     * @param  string  $key
144
     * @param  mixed   $value
145
     */
146 32
    public function set($key, $value)
147
    {
148 32
        $this->checkLoaded();
149
150 32
        $domain = $this->grabDomain($key);
151 32
        $data   = [];
152
153 32
        if ($this->data->has($domain)) {
154 16
            $data = $this->data->get($domain);
155 12
        }
156
157 32
        Arr::set($data, $key, $value);
158
159 32
        $this->data->put($domain, $data);
160 32
    }
161
162
    /**
163
     * Check if a setting exists by the key.
164
     *
165
     * @param  string  $key
166
     *
167
     * @return bool
168
     */
169 24
    public function has($key)
170
    {
171 24
        $this->checkLoaded();
172
173 24
        $domain = $this->grabDomain($key);
174
175 24
        if ( ! $this->data->has($domain)) {
176 12
            return false;
177
        }
178
179 24
        return Arr::has($this->data->get($domain), $key);
180
    }
181
182
    /**
183
     * Get all the setting by a specific domain.
184
     *
185
     * @param  string|null  $domain
186
     *
187
     * @return array
188
     */
189 20
    public function all($domain = null)
190
    {
191 20
        $this->checkLoaded();
192
193 20
        if (is_null($domain)) {
194 16
            $domain = $this->getDefaultDomain();
195 12
        }
196
197 20
        return $this->data->get($domain, []);
198
    }
199
200
    /**
201
     * Delete a setting.
202
     *
203
     * @param  string  $key
204
     */
205 8
    public function delete($key)
206
    {
207 8
        $this->checkLoaded();
208
209 8
        $domain = $this->getDefaultDomain();
210
211 8
        if (str_contains($key, '::')) {
212 4
            list($domain, $key) = explode('::', $key);
213 3
        }
214
215 8
        $data = $this->data->get($domain, []);
216 8
        Arr::forget($data, $key);
217 8
        $data = array_filter($data);
218
219 8
        if (empty($data)) {
220 8
            $this->data->forget($domain);
221 6
        }
222
        else {
223 4
            $this->data->put($domain, $data);
224
        }
225 8
    }
226
227
    /**
228
     * Reset/Delete all the settings.
229
     *
230
     * @param  string|null  $domain
231
     */
232 4
    public function reset($domain = null)
233
    {
234 4
        $this->checkLoaded();
235
236 4
        if (is_null($domain)) {
237 4
            $domain = $this->getDefaultDomain();
238 3
        }
239
240 4
        $this->data->forget($domain);
241 4
    }
242
243
    /**
244
     * Save the settings.
245
     */
246 28
    public function save()
247
    {
248 28
        $saved   = $this->model->all();
249 28
        $changes = $this->getChanges($saved);
250
251 28
        foreach ($changes['inserted'] as $domain => $values) {
252 24
            foreach ($values as $key => $value) {
253 24
                $this->model->createOne($domain, $key, $value);
254 18
            }
255 21
        }
256
257 28
        foreach ($changes['updated'] as $domain => $values) {
258 4
            foreach ($values as $key => $value) {
259
                /** @var Setting $model */
260 4
                $model = $saved->groupBy('domain')->get($domain)->where('key', $key)->first();
261 4
                $model->updateValue($value);
262 4
                $model->save();
263 3
            }
264 21
        }
265
266 28
        foreach ($changes['deleted'] as $domain => $values) {
267 12
            foreach ($values as $key) {
268 12
                $model = $saved->groupBy('domain')->get($domain)->where('key', $key)->first();
269 12
                $model->delete();
270 9
            }
271 21
        }
272
273 28
        $this->flushCachedSettings();
274 28
    }
275
276
    /**
277
     * Get the changes.
278
     *
279
     * @param  \Illuminate\Database\Eloquent\Collection  $saved
280
     *
281
     * @return array
282
     */
283 28
    private function getChanges($saved)
284
    {
285 28
        return Helpers\Comparator::compare(
286
            $this->data->map(function (array $settings) {
287 24
                return Arr::dot($settings);
288 28
            })->toArray(),
289
            $saved->groupBy('domain')->map(function($item) {
290
                /** @var  \Illuminate\Database\Eloquent\Collection  $item */
291 16
                return $item->lists('casted_value', 'key');
292 28
            })->toArray()
293 21
        );
294
    }
295
296
    /**
297
     * Grab the settings domain name from the key.
298
     *
299
     * @param  string  $key
300
     *
301
     * @return string
302
     */
303 32
    private function grabDomain(&$key)
304
    {
305 32
        $domain = $this->getDefaultDomain();
306
307 32
        if (str_contains($key, '::')) {
308 8
            list($domain, $key) = explode('::', $key);
309 6
        }
310
311 32
        return $domain;
312
    }
313
314
    /* ------------------------------------------------------------------------------------------------
315
     |  Other Functions
316
     | ------------------------------------------------------------------------------------------------
317
     */
318
    /**
319
     * Check if the data is loaded
320
     */
321 36
    private function checkLoaded()
322
    {
323 36
        if ($this->loaded) {
324 32
            return;
325
        }
326
327 36
        $this->data->reset();
328 36
        $this->loadData();
329 36
        $this->loaded = true;
330 36
    }
331
332
    /**
333
     * Load the data.
334
     */
335 36
    private function loadData()
336
    {
337 36
        foreach ($this->getCachedSettings() as $setting) {
338
            /** @var Setting $setting */
339 24
            $data = $this->data->get($setting->domain, []);
340
341 24
            Arr::set($data, $setting->key, $setting->casted_value);
342
343 24
            $this->data->put($setting->domain, $data);
344 27
        }
345 36
    }
346
347
    /**
348
     * Get cached settings.
349
     *
350
     * @return \Illuminate\Database\Eloquent\Collection
351
     */
352 36
    private function getCachedSettings()
353
    {
354 36
        if ($this->isCached()) {
355 36
            return $this->cache->rememberForever($this->getCacheKey(), function() {
356 36
                return $this->model->all();
357 36
            });
358
        }
359
360
        return $this->model->all();
361
    }
362
363
    /**
364
     * Flush the cached settings.
365
     */
366 28
    private function flushCachedSettings()
367
    {
368 28
        if ($this->isCached()) {
369 28
            $this->cache->forget($this->getCacheKey());
370 21
        }
371 28
    }
372
}
373