Completed
Push — master ( 9bb7d3...f67bcc )
by Nazar
04:30
created

_Abstract_with_namespace::namespaces_imitation()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 28
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
rs 6.7272
cc 7
eloc 21
nc 7
nop 1
1
<?php
2
/**
3
 * @package   CleverStyle CMS
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2016, Nazar Mokrynskyi
6
 * @license   MIT License, see license.txt
7
 */
8
namespace cs\Cache;
9
use
10
	cs\Core;
11
12
/**
13
 * Abstract class that simplifies creating cache engines without namespaces support
14
 *
15
 * This class implements methods:
16
 * * `::get()`
17
 * * `::set()`
18
 * * `::del()`
19
 * * `::clean()`
20
 *
21
 * And requires to implement simple low-level `protected` proxy-methods:
22
 * * `::available_internal()`
23
 * * `::get_internal()`
24
 * * `::set_internal()`
25
 * * `::del_internal()`
26
 * * `::clean_internal()`
27
 * * `::increment_internal()`
28
 *
29
 * The main benefit is that namespace support is provided by this class and target class only needs to implement trivial low-level methods
30
 */
31
abstract class _Abstract_with_namespace extends _Abstract {
32
	/**
33
	 * @var array
34
	 */
35
	protected $root_versions_cache = [];
36
	/**
37
	 * Whether current cache engine is available (might be `false` if necessary extension is not installed or something similar)
38
	 *
39
	 * @return bool
40
	 */
41
	abstract protected function available_internal ();
42
	/**
43
	 * @abstract
44
	 *
45
	 * @param string $item
46
	 *
47
	 * @return bool|mixed
48
	 */
49
	abstract protected function get_internal ($item);
50
	/**
51
	 * @abstract
52
	 *
53
	 * @param string $item
54
	 * @param mixed  $data
55
	 *
56
	 * @return bool
57
	 */
58
	abstract protected function set_internal ($item, $data);
59
	/**
60
	 * @abstract
61
	 *
62
	 * @param string $item
63
	 *
64
	 * @return bool
65
	 */
66
	abstract protected function del_internal ($item);
67
	/**
68
	 * @abstract
69
	 *
70
	 * @param string $item
71
	 *
72
	 * @return bool
73
	 */
74
	abstract protected function increment_internal ($item);
75
	/**
76
	 * @abstract
77
	 *
78
	 * @return bool
79
	 */
80
	abstract protected function clean_internal ();
81
	/**
82
	 * @inheritdoc
83
	 */
84
	function get ($item) {
85
		if (!$this->available_internal()) {
86
			return false;
87
		}
88
		return $this->get_internal(
89
			$this->namespaces_imitation($item)
90
		);
91
	}
92
	/**
93
	 * @inheritdoc
94
	 */
95
	function set ($item, $data) {
96
		if (!$this->available_internal()) {
97
			return false;
98
		}
99
		return $this->set_internal(
100
			$this->namespaces_imitation($item),
101
			$data
102
		);
103
	}
104
	/**
105
	 * @inheritdoc
106
	 */
107
	function del ($item) {
108
		if (!$this->available_internal()) {
109
			return false;
110
		}
111
		$domain = $this->domain();
112
		$this->del_internal($this->namespaces_imitation($item));
113
		$this->increment_internal("/$domain/$item");
114
		unset($this->root_versions_cache["/$domain/$item"]);
115
		return true;
116
	}
117
	/**
118
	 * @return string
119
	 */
120
	protected function domain () {
121
		static $domain;
122
		if (!isset($domain)) {
123
			$domain = Core::instance()->domain;
124
		}
125
		return $domain;
126
	}
127
	/**
128
	 * @inheritdoc
129
	 */
130
	function clean () {
131
		if (!$this->available_internal()) {
132
			return false;
133
		}
134
		return $this->clean_internal();
135
	}
136
	/**
137
	 * Namespaces imitation
138
	 *
139
	 * Accepts item as parameter, returns item string that uses namespaces (needed for fast deletion of large branches of cache elements).
140
	 *
141
	 * @param $item
142
	 *
143
	 * @return string
144
	 */
145
	protected function namespaces_imitation ($item) {
146
		$domain = $this->domain();
147
		$exploded = explode('/', $item);
148
		$count    = count($exploded);
149
		if ($count > 1) {
150
			$item_path = $domain;
151
			--$count;
152
			/** @noinspection ForeachInvariantsInspection */
153
			for ($i = 0; $i < $count; ++$i) {
154
				$item_path .= '/'.$exploded[$i];
155
				if (!$i && isset($this->root_versions_cache["/$item_path"])) {
156
					$exploded[$i] .= '/'.$this->root_versions_cache["/$item_path"];
157
					continue;
158
				}
159
				$version = $this->get_internal("/$item_path");
160
				if ($version === false) {
161
					$this->set_internal("/$item_path", 0);
162
					$version = 0;
163
				}
164
				$exploded[$i] .= "/$version";
165
				if (!$i) {
166
					$this->root_versions_cache["/$item_path"] = $version;
167
				}
168
			}
169
			return "$domain/".implode('/', $exploded);
170
		}
171
		return "$domain/$item";
172
	}
173
}
174