Completed
Push — master ( 3b9fde...4aaf35 )
by Peter
38:20 queued 18:30
created

MetaCache::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3.072

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
ccs 12
cts 15
cp 0.8
rs 9.4285
cc 3
eloc 11
nc 4
nop 3
crap 3.072
1
<?php
2
3
/**
4
 * This software package is licensed under AGPL, Commercial license.
5
 *
6
 * @package maslosoft/addendum
7
 * @licence AGPL, Commercial
8
 * @copyright Copyright (c) Piotr Masełkowski <[email protected]> (Meta container, further improvements, bugfixes)
9
 * @copyright Copyright (c) Maslosoft (Meta container, further improvements, bugfixes)
10
 * @copyright Copyright (c) Jan Suchal (Original version, builder, parser)
11
 * @link http://maslosoft.com/addendum/ - maslosoft addendum
12
 * @link https://code.google.com/p/addendum/ - original addendum project
13
 */
14
15
namespace Maslosoft\Addendum\Cache;
16
17
use FilesystemIterator;
18
use Maslosoft\Addendum\Addendum;
19
use Maslosoft\Addendum\Collections\Meta;
20
use Maslosoft\Addendum\Helpers\SoftIncluder;
21
use Maslosoft\Addendum\Interfaces\AnnotatedInterface;
22
use Maslosoft\Addendum\Options\MetaOptions;
23
use Maslosoft\Cli\Shared\ConfigDetector;
24
use Maslosoft\Cli\Shared\Helpers\PhpExporter;
25
use RecursiveDirectoryIterator;
26
use RecursiveIteratorIterator;
27
use RuntimeException;
28
29
class MetaCache
30
{
31
32
	private $_metaClass = null;
33
	private $_component = null;
34
35
	/**
36
	 * Options
37
	 * @var string
38
	 */
39
	private $_instanceId = null;
40
41
	/**
42
	 * Addendum runtime path
43
	 * @var string
44
	 */
45
	private $_path = '';
46
47
	/**
48
	 *
49
	 * @var NsCache
50
	 */
51
	private $_nsCache = null;
52
53
	/**
54
	 * Runtime path
55
	 * @var string
56
	 */
57
	private static $_runtimePath = null;
58
59
	/**
60
	 * Local cacheq
61
	 * @var type
62
	 */
63
	private static $_cache = [];
64
65 3
	public function __construct($metaClass = null, AnnotatedInterface $component = null, MetaOptions $options = null)
66
	{
67 3
		if (null === self::$_runtimePath)
68 3
		{
69
			self::$_runtimePath = (new ConfigDetector)->getRuntimePath();
70
		}
71 3
		$this->_path = self::$_runtimePath . '/addendum';
72 3
		$this->_metaClass = $metaClass;
73 3
		$this->_component = $component;
74 3
		if (empty($options))
75 3
		{
76 3
			$this->_instanceId = Addendum::DefaultInstanceId;
77 3
		}
78
		else
79
		{
80
			$this->_instanceId = $options->instanceId;
81
		}
82 3
		$this->_nsCache = new NsCache(dirname($this->_getFilename()), Addendum::fly($this->_instanceId));
83 3
	}
84
85 32
	public function setComponent(AnnotatedInterface $component = null)
86
	{
87 32
		$this->_component = $component;
88 32
	}
89
90 32
	public function setOptions(MetaOptions $options = null)
91
	{
92 32
		$this->_nsCache->setOptions($options);
93 32
	}
94
95 32
	public function prepare()
96
	{
97 32
		if (!file_exists($this->_path))
98 32
		{
99 32
			if (!file_exists(self::$_runtimePath))
100 32
			{
101
102 1
				if (is_writable(dirname(self::$_runtimePath)))
103 1
				{
104 1
					$this->mkdir(self::$_runtimePath);
105 1
				}
106 1
				if (!is_writable(self::$_runtimePath))
107 1
				{
108
					throw new RuntimeException(sprintf("Runtime path `%s` must exists and be writable", self::$_runtimePath));
109
				}
110 1
			}
111 32
			if (is_writable(self::$_runtimePath))
112 32
			{
113 32
				$this->mkdir($this->_path);
114 32
			}
115 32
			if (!is_writable($this->_path))
116 32
			{
117
				throw new RuntimeException(sprintf("Addendum runtime path `%s` must exists and be writable", $this->_path));
118
			}
119 32
		}
120 32
		if (!file_exists(dirname($this->_getFilename())))
121 32
		{
122 32
			$this->mkdir(dirname($this->_getFilename()));
123 32
		}
124 32
	}
125
126 32
	public function get()
127
	{
128 32
		$this->prepare();
129 32
		$filename = $this->_getFilename();
130
131 32
		if (!$this->_nsCache->valid())
132 32
		{
133 2
			$this->_clearCurrent();
134 2
			return false;
135
		}
136
137 31
		if (isset(self::$_cache[$filename]))
138 31
		{
139 4
			return self::$_cache[$filename];
140
		}
141
142 27
		$data = SoftIncluder::includeFile($filename);
143
144 27
		if (empty($data))
145 27
		{
146 27
			return false;
147
		}
148
		self::$_cache[$filename] = $data;
149
		return $data;
150
	}
151
152 21
	public function set(Meta $meta)
153
	{
154
155
156
157 21
		$filename = $this->_getFilename();
158
159 21
		self::$_cache[$filename] = $meta;
160
161 21
		file_put_contents($filename, PhpExporter::export($meta));
162 21
		chmod($filename, 0666);
163 21
		$this->_nsCache->set();
164 21
		return $meta;
165
	}
166
167
	public function remove()
168
	{
169
		$filename = $this->_getFilename();
170
		unset(self::$_cache[$filename]);
171
		if (file_exists($filename))
172
		{
173
			return unlink($filename);
174
		}
175
		return false;
176
	}
177
178
	/**
179
	 * Clear entire cache
180
	 * @return boolean
181
	 */
182 3
	public function clear()
183
	{
184 3
		return $this->_clear($this->_path);
185
	}
186
187 2
	private function _clearCurrent()
188
	{
189 2
		return $this->_classToFile(dirname($this->_getFilename()));
190
	}
191
192 3
	private function _clear($path)
193
	{
194 3
		if (!file_exists($path))
195 3
		{
196 3
			return false;
197
		}
198 1
		foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $dir)
199
		{
200 1
			$dir->isDir() && !$dir->isLink() ? rmdir($dir->getPathname()) : unlink($dir->getPathname());
201 1
		}
202 1
		return rmdir($path);
203
	}
204
205 34
	private function _getFilename()
206
	{
207 34
		return sprintf('%s/%s@%s/%s.php', $this->_path, $this->_classToFile($this->_metaClass), $this->_instanceId, str_replace('\\', '/', $this->_classToFile(get_class($this->_component))));
208
	}
209
210 34
	private function _classToFile($className)
211
	{
212 34
		return str_replace('\\', '.', $className);
213
	}
214
215
	/**
216
	 * Recursively create dir with proper permissions.
217
	 * 
218
	 * @param string $path
219
	 */
220 32
	private function mkdir($path)
221
	{
222 32
		$mask = umask(0000);
223 32
		mkdir($path, 0777, true);
224 32
		umask($mask);
225 32
	}
226
227
}
228