Completed
Push — master ( f5d71d...bfd9cb )
by Sam
12:52
created

Cache::factory()   C

Complexity

Conditions 8
Paths 40

Size

Total Lines 42
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 25
c 1
b 0
f 0
nc 40
nop 3
dl 0
loc 42
rs 5.3846
1
<?php
2
3
namespace SilverStripe\Core;
4
5
use Zend_Cache;
6
use Zend_Cache_Core;
7
8
/**
9
 * The `[api:Cache]` class provides a bunch of static functions wrapping the Zend_Cache system
10
 * in something a little more easy to use with the SilverStripe config system.
11
 *
12
 * @see https://docs.silverstripe.org/en/3.4/developer_guides/performance/caching/
13
 */
14
class Cache {
15
16
	/**
17
	 * @var array $backends
18
	 */
19
	protected static $backends = array();
20
21
	/**
22
	 * @var array $backend_picks
23
	 */
24
	protected static $backend_picks = array();
25
26
	/**
27
	 * @var array $cache_lifetime
28
	 */
29
	protected static $cache_lifetime = array();
30
31
	/**
32
	 * Initialize the 'default' named cache backend.
33
	 */
34
	protected static function init(){
35
		if (!isset(self::$backends['default'])) {
36
			$cachedir = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'cache';
37
38
			if (!is_dir($cachedir)) {
39
				mkdir($cachedir);
40
			}
41
42
			/** @skipUpgrade */
43
			self::$backends['default'] = array(
44
				'File',
45
				array(
46
					'cache_dir' => $cachedir
47
				)
48
			);
49
50
			self::$cache_lifetime['default'] = array(
51
				'lifetime' => 600,
52
				'priority' => 1
53
			);
54
		}
55
	}
56
57
	/**
58
	 * Add a new named cache backend.
59
	 *
60
	 * @see http://framework.zend.com/manual/en/zend.cache.html
61
	 *
62
	 * @param string $name The name of this backend as a freeform string
63
	 * @param string $type The Zend_Cache backend ('File' or 'Sqlite' or ...)
64
	 * @param array $options The Zend_Cache backend options
65
	 */
66
	public static function add_backend($name, $type, $options = array()) {
67
		self::init();
68
		self::$backends[$name] = array($type, $options);
69
	}
70
71
	/**
72
	 * Pick a named cache backend for a particular named cache.
73
	 *
74
	 * The priority call with the highest number will be the actual backend
75
	 * picked. A backend picked for a specific cache name will always be used
76
	 * instead of 'any' if it exists, no matter the priority.
77
	 *
78
	 * @param string $name The name of the backend, as passed as the first argument to add_backend
79
	 * @param string $for The name of the cache to pick this backend for (or 'any' for any backend)
80
	 * @param integer $priority The priority of this pick
81
	 */
82
	public static function pick_backend($name, $for, $priority = 1) {
83
		self::init();
84
85
		$current = -1;
86
87
		if (isset(self::$backend_picks[$for])) {
88
			$current = self::$backend_picks[$for]['priority'];
89
		}
90
91
		if ($priority >= $current) {
92
			self::$backend_picks[$for] = array(
93
				'name' => $name,
94
				'priority' => $priority
95
			);
96
		}
97
	}
98
99
	/**
100
	 * Return the cache lifetime for a particular named cache.
101
	 *
102
	 * @param string $for
103
	 *
104
	 * @return string
105
	 */
106
	public static function get_cache_lifetime($for) {
107
		if(isset(self::$cache_lifetime[$for])) {
108
			return self::$cache_lifetime[$for];
109
		}
110
111
		return null;
112
	}
113
114
	/**
115
	 * Set the cache lifetime for a particular named cache
116
	 *
117
	 * @param string $for The name of the cache to set this lifetime for (or 'any' for all backends)
118
	 * @param integer $lifetime The lifetime of an item of the cache, in seconds, or -1 to disable caching
119
	 * @param integer $priority The priority. The highest priority setting is used. Unlike backends, 'any' is not
120
	 *                          special in terms of priority.
121
	 */
122
	public static function set_cache_lifetime($for, $lifetime=600, $priority=1) {
123
		self::init();
124
125
		$current = -1;
126
127
		if (isset(self::$cache_lifetime[$for])) {
128
			$current = self::$cache_lifetime[$for]['priority'];
129
		}
130
131
		if ($priority >= $current) {
132
			self::$cache_lifetime[$for] = array(
133
				'lifetime' => $lifetime,
134
				'priority' => $priority
135
			);
136
		}
137
	}
138
139
	/**
140
	 * Build a cache object.
141
	 *
142
	 * @see http://framework.zend.com/manual/en/zend.cache.html
143
	 *
144
	 * @param string $for The name of the cache to build
145
	 * @param string $frontend (optional) The type of Zend_Cache frontend
146
	 * @param array $frontendOptions (optional) Any frontend options to use.
147
	 * @return Zend_Cache_Core The cache object
148
	 */
149
	public static function factory($for, $frontend='Output', $frontendOptions=null) {
150
		self::init();
151
152
		$backend_name = 'default';
153
		$backend_priority = -1;
154
		$cache_lifetime = self::$cache_lifetime['default']['lifetime'];
155
		$lifetime_priority = -1;
156
157
		foreach(array('any', $for) as $name) {
158
			if(isset(self::$backend_picks[$name])) {
159
				if(self::$backend_picks[$name]['priority'] > $backend_priority) {
160
					$backend_name = self::$backend_picks[$name]['name'];
161
					$backend_priority = self::$backend_picks[$name]['priority'];
162
				}
163
			}
164
165
			if (isset(self::$cache_lifetime[$name])) {
166
				if(self::$cache_lifetime[$name]['priority'] > $lifetime_priority) {
167
					$cache_lifetime = self::$cache_lifetime[$name]['lifetime'];
168
					$lifetime_priority = self::$cache_lifetime[$name]['priority'];
169
				}
170
			}
171
		}
172
173
		$backend = self::$backends[$backend_name];
174
175
		$basicOptions = array('cache_id_prefix' => $for);
176
177
		if ($cache_lifetime >= 0) {
178
			$basicOptions['lifetime'] = $cache_lifetime;
179
		} else {
180
			$basicOptions['caching'] = false;
181
		}
182
183
		$frontendOptions = $frontendOptions ? array_merge($basicOptions, $frontendOptions) : $basicOptions;
184
185
		require_once 'Zend/Cache.php';
186
187
		return Zend_Cache::factory(
188
			$frontend, $backend[0], $frontendOptions, $backend[1]
189
		);
190
	}
191
}
192