Completed
Push — master ( 15cddd...ae2a0d )
by Bradley
06:08 queued 03:34
created

SettingBase::getUncached()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
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;
0 ignored issues
show
Bug introduced by
The property database does not seem to exist. Did you mean databaseInstance?

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.

Loading history...
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value can also be of type object<DateTime>. However, the property $cacheExpiry is declared as type integer|object<Cornford\Setter\Datetime>|boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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