Completed
Push — master ( 2dc251...31fd01 )
by ARCANEDEV
05:57
created

SettingsManager::save()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 8
Bugs 0 Features 0
Metric Value
c 8
b 0
f 0
dl 0
loc 14
ccs 11
cts 11
cp 1
rs 9.4286
cc 2
eloc 8
nc 2
nop 0
crap 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 \Arcanesoft\Settings\Models\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
        $changes = $this->getChanges(
249 28
            $saved = $this->model->all()
250 21
        );
251
252 28
        $this->saveInserted($changes['inserted']);
253 28
        $this->saveUpdated($saved, $changes['updated']);
254 28
        $this->saveDeleted($saved, $changes['deleted']);
255
256 28
        if ($this->isCached()) {
257 28
            $this->cache->forget($this->getCacheKey());
258 21
        }
259 28
    }
260
261
    /**
262
     * Get the changes.
263
     *
264
     * @param  \Illuminate\Database\Eloquent\Collection  $saved
265
     *
266
     * @return array
267
     */
268 28
    private function getChanges($saved)
269
    {
270 28
        return Helpers\Comparator::compare(
271
            $this->data->map(function (array $settings) {
272 24
                return Arr::dot($settings);
273 28
            })->toArray(),
274
            $saved->groupBy('domain')->map(function($item) {
275
                /** @var  \Illuminate\Database\Eloquent\Collection  $item */
276 16
                return $item->lists('casted_value', 'key');
277 28
            })->toArray()
278 21
        );
279
    }
280
281
    /**
282
     * Save the inserted entries.
283
     *
284
     * @param  array  $inserted
285
     */
286 28
    private function saveInserted(array $inserted)
287
    {
288 28
        foreach ($inserted as $domain => $values) {
289 24
            foreach ($values as $key => $value) {
290 24
                $this->model->createOne($domain, $key, $value);
291 18
            }
292 21
        }
293 28
    }
294
295
    /**
296
     * Save the updated entries.
297
     *
298
     * @param  \Illuminate\Database\Eloquent\Collection  $saved
299
     * @param  array                                     $updated
300
     */
301 28
    private function saveUpdated($saved, array $updated)
302
    {
303 28
        foreach ($updated as $domain => $values) {
304 4
            foreach ($values as $key => $value) {
305
                /** @var  \Arcanesoft\Settings\Models\Setting  $model */
306 4
                $model = $saved->groupBy('domain')->get($domain)->where('key', $key)->first();
307 4
                $model->updateValue($value);
308 4
                $model->save();
309 3
            }
310 21
        }
311 28
    }
312
313
    /**
314
     * Save the deleted entries.
315
     *
316
     * @param  \Illuminate\Database\Eloquent\Collection  $saved
317
     * @param  array                                     $deleted
318
     */
319 28
    private function saveDeleted($saved, array $deleted)
320
    {
321 28
        foreach ($deleted as $domain => $values) {
322 12
            foreach ($values as $key) {
323
                /** @var  \Arcanesoft\Settings\Models\Setting  $model */
324 12
                $model = $saved->groupBy('domain')->get($domain)->where('key', $key)->first();
325 12
                $model->delete();
326 9
            }
327 21
        }
328 28
    }
329
330
    /**
331
     * Grab the settings domain name from the key.
332
     *
333
     * @param  string  $key
334
     *
335
     * @return string
336
     */
337 32
    private function grabDomain(&$key)
338
    {
339 32
        $domain = $this->getDefaultDomain();
340
341 32
        if (str_contains($key, '::')) {
342 8
            list($domain, $key) = explode('::', $key);
343 6
        }
344
345 32
        return $domain;
346
    }
347
348
    /* ------------------------------------------------------------------------------------------------
349
     |  Other Functions
350
     | ------------------------------------------------------------------------------------------------
351
     */
352
    /**
353
     * Check if the data is loaded
354
     */
355 36
    private function checkLoaded()
356
    {
357 36
        if ($this->loaded) {
358 32
            return;
359
        }
360
361 36
        $this->data->reset();
362 36
        $this->loadData();
363 36
        $this->loaded = true;
364 36
    }
365
366
    /**
367
     * Load the data.
368
     */
369 36
    private function loadData()
370
    {
371 36
        foreach ($this->getCachedSettings() as $setting) {
372
            /** @var  \Arcanesoft\Settings\Models\Setting  $setting */
373 24
            $data = $this->data->get($setting->domain, []);
374
375 24
            Arr::set($data, $setting->key, $setting->casted_value);
376
377 24
            $this->data->put($setting->domain, $data);
378 27
        }
379 36
    }
380
381
    /**
382
     * Get cached settings.
383
     *
384
     * @return \Illuminate\Database\Eloquent\Collection
385
     */
386 36
    private function getCachedSettings()
387
    {
388 36
        return ! $this->isCached()
389 27
            ? $this->model->all()
390 36
            : $this->cache->rememberForever($this->getCacheKey(), function() {
391 36
                return $this->model->all();
392 36
            });
393
    }
394
}
395