1
|
|
|
<?php namespace Cornford\Setter; |
2
|
|
|
|
3
|
|
|
use Cornford\Setter\Exceptions\SettingArgumentException; |
4
|
|
|
use DateTime; |
5
|
|
|
use Illuminate\Database\DatabaseManager as Query; |
6
|
|
|
use Illuminate\Config\Repository; |
7
|
|
|
use Illuminate\Cache\Repository as Cache; |
8
|
|
|
|
9
|
|
|
abstract class SettingBase { |
10
|
|
|
|
11
|
|
|
const LOCATION_DATABASE = 'database'; |
12
|
|
|
const LOCATION_CACHE = 'cache'; |
13
|
|
|
|
14
|
|
|
const CACHE_ENABLED = true; |
15
|
|
|
const CACHE_TAG = 'setter::'; |
16
|
|
|
const CACHE_EXPIRY = true; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Database |
20
|
|
|
* |
21
|
|
|
* @var \Illuminate\Database\DatabaseManager |
22
|
|
|
*/ |
23
|
|
|
protected $databaseInstance; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* Config |
27
|
|
|
* |
28
|
|
|
* @var \Illuminate\Config\Repository |
29
|
|
|
*/ |
30
|
|
|
protected $config; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Cache |
34
|
|
|
* |
35
|
|
|
* @var \Illuminate\Cache\Repository |
36
|
|
|
*/ |
37
|
|
|
protected $cache; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Caching Enabled? |
41
|
|
|
* |
42
|
|
|
* @var boolean |
43
|
|
|
*/ |
44
|
|
|
protected $cacheEnabled = true; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Cache Tag |
48
|
|
|
* |
49
|
|
|
* @var string |
50
|
|
|
*/ |
51
|
|
|
protected $cacheTag; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Cache |
55
|
|
|
* |
56
|
|
|
* @var integer|datetime|boolean |
57
|
|
|
*/ |
58
|
|
|
protected $cacheExpiry; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Un-cached? |
62
|
|
|
* |
63
|
|
|
* @var boolean |
64
|
|
|
*/ |
65
|
|
|
protected $uncached = false; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Construct Setter |
69
|
|
|
* |
70
|
|
|
* @param Query $database |
71
|
|
|
* @param Repository $config |
72
|
|
|
* @param Cache $cache |
73
|
|
|
* @param array $options |
74
|
|
|
* |
75
|
|
|
* @throws SettingArgumentException |
76
|
|
|
*/ |
77
|
|
|
public function __construct(Query $database, Repository $config, Cache $cache, array $options = []) |
78
|
|
|
{ |
79
|
|
|
$this->database = $database; |
|
|
|
|
80
|
|
|
$this->config = $config; |
81
|
|
|
$this->cache = $cache; |
82
|
|
|
|
83
|
|
|
if (!isset($options['cache'])) { |
84
|
|
|
throw new SettingArgumentException('Cache is required in boolean format.'); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if (!isset($options['tag'])) { |
88
|
|
|
throw new SettingArgumentException('Tag is required in string format.'); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
if (!isset($options['expiry'])) { |
92
|
|
|
throw new SettingArgumentException('Expiry is required in boolean, integer or DateTime format.'); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
$this->setCacheEnabled(isset($options['cache']) ? $options['cache'] : self::CACHE_ENABLED); |
96
|
|
|
$this->setCacheTag(isset($options['tag']) ? $options['tag'] : self::CACHE_TAG); |
97
|
|
|
$this->setCacheExpiry(isset($options['expiry']) ? $options['expiry'] : self::CACHE_EXPIRY); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Set caching enabled status. |
102
|
|
|
* |
103
|
|
|
* @param boolean $value |
104
|
|
|
* |
105
|
|
|
* @throws SettingArgumentException |
106
|
|
|
* |
107
|
|
|
* @return void |
108
|
|
|
*/ |
109
|
|
|
protected function setCacheEnabled($value) |
110
|
|
|
{ |
111
|
|
|
if (!is_bool($value)) { |
112
|
|
|
throw new SettingArgumentException('Cache enabled is required in boolean format.'); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
$this->cacheEnabled = $value; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Get the caching enabled status. |
120
|
|
|
* |
121
|
|
|
* @return boolean |
122
|
|
|
*/ |
123
|
|
|
protected function getCacheEnabled() |
124
|
|
|
{ |
125
|
|
|
return $this->cacheEnabled; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Cache enabled? |
130
|
|
|
* |
131
|
|
|
* @return boolean |
132
|
|
|
*/ |
133
|
|
|
public function cacheEnabled() |
134
|
|
|
{ |
135
|
|
|
return ($this->getCacheEnabled() === self::CACHE_ENABLED); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Set the cache tag |
140
|
|
|
* |
141
|
|
|
* @param string $value |
142
|
|
|
* |
143
|
|
|
* @throws SettingArgumentException |
144
|
|
|
* |
145
|
|
|
* @return void |
146
|
|
|
*/ |
147
|
|
|
public function setCacheTag($value) |
148
|
|
|
{ |
149
|
|
|
if (!is_string($value)) { |
150
|
|
|
throw new SettingArgumentException('Cache tag is required in string format.'); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
$this->cacheTag = $value; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Get the cache tag |
158
|
|
|
* |
159
|
|
|
* @return string |
160
|
|
|
*/ |
161
|
|
|
public function getCacheTag() |
162
|
|
|
{ |
163
|
|
|
return $this->cacheTag; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Set the cache expiry |
168
|
|
|
* |
169
|
|
|
* @param boolean|integer|DateTime $value |
170
|
|
|
* |
171
|
|
|
* @throws SettingArgumentException |
172
|
|
|
* |
173
|
|
|
* @return void |
174
|
|
|
*/ |
175
|
|
View Code Duplication |
protected function setCacheExpiry($value) |
|
|
|
|
176
|
|
|
{ |
177
|
|
|
if (!is_bool($value) && !is_integer($value) && !$value instanceof DateTime) { |
178
|
|
|
throw new SettingArgumentException('Expiry is required in boolean, integer or DateTime format.'); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$this->cacheExpiry = $value; |
|
|
|
|
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Get the cache tag |
186
|
|
|
* |
187
|
|
|
* @return string |
188
|
|
|
*/ |
189
|
|
|
protected function getCacheExpiry() |
190
|
|
|
{ |
191
|
|
|
return $this->cacheExpiry; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Set the uncached status. |
196
|
|
|
* |
197
|
|
|
* @param boolean $value |
198
|
|
|
* |
199
|
|
|
* @return void |
200
|
|
|
*/ |
201
|
|
|
protected function setUncached($value) |
202
|
|
|
{ |
203
|
|
|
$this->uncached = $value; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Get the uncached status. |
208
|
|
|
* |
209
|
|
|
* @return boolean |
210
|
|
|
*/ |
211
|
|
|
protected function getUncached() |
212
|
|
|
{ |
213
|
|
|
return $this->uncached; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Return a key with an attached cache tag |
218
|
|
|
* |
219
|
|
|
* @param string $key |
220
|
|
|
* |
221
|
|
|
* @return string |
222
|
|
|
*/ |
223
|
|
|
protected function attachCacheTag($key) |
224
|
|
|
{ |
225
|
|
|
return $this->getCacheTag() . $key; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* Check a setting exists in cache |
230
|
|
|
* |
231
|
|
|
* @param string $key |
232
|
|
|
* |
233
|
|
|
* @return boolean |
234
|
|
|
*/ |
235
|
|
|
public function cacheHas($key) |
236
|
|
|
{ |
237
|
|
|
return $this->cache->has($this->attachCacheTag($key)) ? true : false; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Forget a cached setting by key |
242
|
|
|
* |
243
|
|
|
* @param string $key |
244
|
|
|
* |
245
|
|
|
* @return boolean |
246
|
|
|
*/ |
247
|
|
|
public function cacheForget($key) |
248
|
|
|
{ |
249
|
|
|
$this->cache |
250
|
|
|
->forget($this->attachCacheTag($key)); |
251
|
|
|
|
252
|
|
|
return true; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* Clear all cached settings |
257
|
|
|
* |
258
|
|
|
* @return boolean |
259
|
|
|
*/ |
260
|
|
|
public function cacheClear() |
261
|
|
|
{ |
262
|
|
|
$this->cache |
263
|
|
|
->flush(); |
264
|
|
|
|
265
|
|
|
return true; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* Check a setting exists in config |
270
|
|
|
* |
271
|
|
|
* @param string $key |
272
|
|
|
* |
273
|
|
|
* @return boolean |
274
|
|
|
*/ |
275
|
|
|
public function configHas($key) |
276
|
|
|
{ |
277
|
|
|
return $this->config->has($key) ? true : false; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Arrange results into an associative array |
282
|
|
|
* |
283
|
|
|
* @param array $results |
284
|
|
|
* @param string $key |
285
|
|
|
* |
286
|
|
|
* @return array |
287
|
|
|
*/ |
288
|
|
|
protected function arrangeResults($results, $key = null) |
289
|
|
|
{ |
290
|
|
|
$return = array(); |
291
|
|
|
|
292
|
|
|
foreach ($results as $path => $value) { |
293
|
|
|
$parts = strpos($path, '.') > 0 ? explode('.', trim(preg_replace('/^' . $key . '/', '', $path), '.')) : array($path); |
294
|
|
|
$target =& $return; |
295
|
|
|
|
296
|
|
|
foreach ($parts as $part) { |
297
|
|
|
$target =& $target[$part]; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
$target = $this->decodeJson($value); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
return $return; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* Return result values |
308
|
|
|
* |
309
|
|
|
* @param array $results |
310
|
|
|
* @param string $key |
311
|
|
|
* |
312
|
|
|
* @return string|array |
313
|
|
|
*/ |
314
|
|
|
protected function returnResults($results = array(), $key) |
315
|
|
|
{ |
316
|
|
|
$items = $this->arrangeResults($results, $key); |
317
|
|
|
$return = $this->combineResults($items, $key); |
318
|
|
|
|
319
|
|
|
if ((!is_array($this->returnConfig($key)) || count($this->returnConfig($key)) == 0) && |
320
|
|
|
(array_key_exists($key, $return) || array_key_exists('', $return)) |
321
|
|
|
&& count($return) == 1 |
322
|
|
|
) { |
323
|
|
|
$return = reset($return); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
if ($this->cacheEnabled()) { |
327
|
|
|
$this->cache->forget($this->attachCacheTag($key)); |
328
|
|
|
$this->cache->add($this->attachCacheTag($key), $return, $this->getCacheExpiry()); |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
return $this->decodeJson($return); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Combine result values from the database and configuration |
336
|
|
|
* |
337
|
|
|
* @param array $results |
338
|
|
|
* @param string $key |
339
|
|
|
* |
340
|
|
|
* @return array |
341
|
|
|
*/ |
342
|
|
|
protected function combineResults(array $results = array(), $key) |
343
|
|
|
{ |
344
|
|
|
$config = $this->returnConfig($key); |
345
|
|
|
|
346
|
|
|
if (is_array($config)) { |
347
|
|
|
return array_replace_recursive($config, ((array_key_exists($key, $results) || array_key_exists('', $results)) ? reset($results) : $results)); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
return $results; |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* Re-cache item and its parents |
355
|
|
|
* |
356
|
|
|
* @param string $value |
357
|
|
|
* @param string $key |
358
|
|
|
* |
359
|
|
|
* @return void |
360
|
|
|
*/ |
361
|
|
|
protected function recacheItem($value, $key) |
362
|
|
|
{ |
363
|
|
|
for ($i = 0; $i <= substr_count($key, '.') - 1; $i++) { |
364
|
|
|
$j = $i; |
365
|
|
|
$position = 0; |
366
|
|
|
|
367
|
|
|
while ($j >= 0) { |
368
|
|
|
$position =+ strpos($key, '.', $position) + 1; |
369
|
|
|
$j--; |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
$this->cache |
373
|
|
|
->forget($this->attachCacheTag(rtrim(substr_replace($key, '', $position), '.'))); |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
$this->cache |
377
|
|
|
->forget($this->attachCacheTag($key)); |
378
|
|
|
$this->cache |
379
|
|
|
->add($this->attachCacheTag($key), $value, $this->getCacheExpiry()); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
/** |
383
|
|
|
* Return cache values |
384
|
|
|
* |
385
|
|
|
* @param string $key |
386
|
|
|
* |
387
|
|
|
* @return string|array |
388
|
|
|
*/ |
389
|
|
|
protected function returnCache($key) |
390
|
|
|
{ |
391
|
|
|
$value = $this->cache->get($this->attachCacheTag($key)); |
392
|
|
|
|
393
|
|
|
return $this->decodeJson($value); |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Return config values |
398
|
|
|
* |
399
|
|
|
* @param string $key |
400
|
|
|
* |
401
|
|
|
* @return string|array |
402
|
|
|
*/ |
403
|
|
|
protected function returnConfig($key) |
404
|
|
|
{ |
405
|
|
|
$value = $this->config->get($key); |
406
|
|
|
|
407
|
|
|
return $this->decodeJson($value); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
/** |
411
|
|
|
* Is the string Json encoded. |
412
|
|
|
* |
413
|
|
|
* @param string $string |
414
|
|
|
* @return boolean |
415
|
|
|
*/ |
416
|
|
|
protected function isJson($string) |
417
|
|
|
{ |
418
|
|
|
if (!is_string($string)) { |
419
|
|
|
return false; |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
json_decode($string); |
423
|
|
|
|
424
|
|
|
return (json_last_error() == JSON_ERROR_NONE); |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* Decode a Json item. |
429
|
|
|
* |
430
|
|
|
* @param mixed $value |
431
|
|
|
* |
432
|
|
|
* @return mixed |
433
|
|
|
*/ |
434
|
|
|
protected function decodeJson($value) |
435
|
|
|
{ |
436
|
|
|
if ($this->isJson($value)) { |
437
|
|
|
return ($value === '""' || $value === '' ? '' : json_decode($value)); |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
return $value; |
441
|
|
|
} |
442
|
|
|
|
443
|
|
|
} |
444
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.