Completed
Push — master ( b93459...5ccbbe )
by Alexander
9s
created

CacheManager::durationIntoSeconds()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
crap 3
1
<?php
2
/**
3
 * This file is part of the SVN-Buddy library.
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 *
7
 * @copyright Alexander Obuhovich <[email protected]>
8
 * @link      https://github.com/console-helpers/svn-buddy
9
 */
10
11
namespace ConsoleHelpers\SVNBuddy\Cache;
12
13
14
use ConsoleHelpers\ConsoleKit\ConsoleIO;
15
use ConsoleHelpers\SVNBuddy\Helper\SizeHelper;
16
17
class CacheManager
18
{
19
20
	/**
21
	 * Working directory.
22
	 *
23
	 * @var string
24
	 */
25
	private $_workingDirectory;
26
27
	/**
28
	 * Console IO.
29
	 *
30
	 * @var ConsoleIO
31
	 */
32
	private $_io;
33
34
	/**
35
	 * Size helper.
36
	 *
37
	 * @var SizeHelper
38
	 */
39
	private $_sizeHelper;
40
41
	/**
42
	 * Create cache manager.
43
	 *
44
	 * @param string     $working_directory Working directory.
45
	 * @param SizeHelper $size_helper       Size helper.
46
	 * @param ConsoleIO  $io                Console IO.
47
	 */
48 16
	public function __construct($working_directory, SizeHelper $size_helper, ConsoleIO $io = null)
49
	{
50 16
		$this->_workingDirectory = $working_directory;
51 16
		$this->_sizeHelper = $size_helper;
52 16
		$this->_io = $io;
53 16
	}
54
55
	/**
56
	 * Sets value in cache.
57
	 *
58
	 * @param string  $name        Name.
59
	 * @param mixed   $value       Value.
60
	 * @param mixed   $invalidator Invalidator.
61
	 * @param integer $duration    Duration in seconds.
62
	 *
63
	 * @return void
64
	 */
65 9
	public function setCache($name, $value, $invalidator = null, $duration = null)
66
	{
67 9
		$duration = $this->durationIntoSeconds($duration);
68
69 9
		$storage = $this->_getStorage($name, $duration);
70 8
		$storage->set(array(
71 8
			'name' => $name,
72 8
			'invalidator' => $invalidator,
73 8
			'duration' => $duration,
74 8
			'expiration' => $duration ? time() + $duration : null,
75 8
			'data' => $value,
76 8
		));
77 8
	}
78
79
	/**
80
	 * Gets value from cache.
81
	 *
82
	 * @param string  $name        Name.
83
	 * @param mixed   $invalidator Invalidator.
84
	 * @param integer $duration    Duration in seconds.
85
	 *
86
	 * @return mixed
87
	 */
88 10
	public function getCache($name, $invalidator = null, $duration = null)
89
	{
90 10
		$storage = $this->_getStorage($name, $this->durationIntoSeconds($duration));
91 10
		$cache = $storage->get();
92
93 10
		if ( !is_array($cache) || $cache['invalidator'] !== $invalidator ) {
94 4
			$storage->invalidate();
95
96 4
			return null;
97
		}
98
99 6
		if ( $cache['expiration'] && $cache['expiration'] < time() ) {
100 1
			$storage->invalidate();
101
102 1
			return null;
103
		}
104
105 6
		return $cache['data'];
106
	}
107
108
	/**
109
	 * Converts duration into seconds.
110
	 *
111
	 * @param integer $duration Duration in seconds.
112
	 *
113
	 * @return integer|null
114
	 */
115 12
	protected function durationIntoSeconds($duration = null)
116
	{
117 12
		if ( !isset($duration) ) {
118 11
			return null;
119
		}
120
121 2
		if ( is_numeric($duration) ) {
122 1
			$duration .= ' seconds';
123 1
		}
124
125 2
		$now = time();
126
127 2
		return strtotime('+' . $duration, $now) - $now;
128
	}
129
130
	/**
131
	 * Returns file-based cache storage.
132
	 *
133
	 * @param string  $name     Cache name.
134
	 * @param integer $duration Duration in seconds.
135
	 *
136
	 * @return ICacheStorage
137
	 * @throws \InvalidArgumentException When namespace is missing in the name.
138
	 */
139 12
	private function _getStorage($name, $duration = null)
140
	{
141 12
		$name_parts = explode(':', $name, 2);
142
143 12
		if ( count($name_parts) != 2 ) {
144 1
			throw new \InvalidArgumentException('The $name parameter must be in "namespace:name" format.');
145
		}
146
147
		$filename_parts = array(
148 11
			$name_parts[0],
149 11
			substr(hash_hmac('sha1', $name_parts[1], 'svn-buddy'), 0, 8),
150 11
			'D' . (isset($duration) ? $duration : 'INF'),
151 11
		);
152
153 11
		$cache_filename = $this->_workingDirectory . DIRECTORY_SEPARATOR . implode('_', $filename_parts) . '.cache';
154
155 11
		if ( isset($this->_io) && $this->_io->isVerbose() ) {
156 2
			$message = $cache_filename;
157
158 2
			if ( file_exists($cache_filename) ) {
159 1
				$message .= ' (hit: ' . $this->_sizeHelper->formatSize(filesize($cache_filename)) . ')';
160 1
			}
161
			else {
162 2
				$message .= ' (miss)';
163
			}
164
165 2
			$this->_io->writeln(array(
166 2
				'',
167 2
				'<debug>[cache]: ' . $message . '</debug>',
168 2
			));
169 2
		}
170
171 11
		return new FileCacheStorage($cache_filename);
172
	}
173
174
}
175