Passed
Push — release-2.1 ( f28109...493a4c )
by Mathias
06:40
created

Sqlite::cacheSettings()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 2
eloc 15
c 2
b 1
f 0
nc 2
nop 1
dl 0
loc 23
rs 9.7666
1
<?php
2
3
/**
4
 * Simple Machines Forum (SMF)
5
 *
6
 * @package SMF
7
 * @author Simple Machines https://www.simplemachines.org
8
 * @copyright 2020 Simple Machines and individual contributors
9
 * @license https://www.simplemachines.org/about/smf/license.php BSD
10
 *
11
 * @version 2.1 RC3
12
 */
13
14
namespace SMF\Cache\APIs;
15
16
use SMF\Cache\CacheApi;
17
use SMF\Cache\CacheApiInterface;
18
use SQLite3;
19
20
if (!defined('SMF'))
21
	die('No direct access...');
22
23
/**
24
 * SQLite Cache API class
25
 *
26
 * @package CacheAPI
27
 */
28
class Sqlite extends CacheApi implements CacheApiInterface
29
{
30
	/**
31
	 * @var string The path to the current $cachedir directory.
32
	 */
33
	private $cachedir = null;
34
35
	/**
36
	 * @var SQLite3
37
	 */
38
	private $cacheDB = null;
39
40
	public function __construct()
41
	{
42
		parent::__construct();
43
44
		// Set our default cachedir.
45
		$this->setCachedir();
46
	}
47
48
	/**
49
	 * {@inheritDoc}
50
	 */
51
	public function connect()
52
	{
53
		$database = $this->cachedir . '/' . 'SQLite3Cache.db3';
54
		$this->cacheDB = new SQLite3($database);
55
		$this->cacheDB->busyTimeout(1000);
56
		if (filesize($database) == 0)
57
		{
58
			$this->cacheDB->exec('CREATE TABLE cache (key text unique, value blob, ttl int);');
59
			$this->cacheDB->exec('CREATE INDEX ttls ON cache(ttl);');
60
		}
61
	}
62
63
	/**
64
	 * {@inheritDoc}
65
	 */
66
	public function isSupported($test = false)
67
	{
68
		$supported = class_exists("SQLite3") && is_writable($this->cachedir);
69
70
		if ($test)
71
			return $supported;
72
73
		return parent::isSupported() && $supported;
74
	}
75
76
	/**
77
	 * {@inheritDoc}
78
	 */
79
	public function getData($key, $ttl = null)
80
	{
81
		$query = 'SELECT value FROM cache WHERE key = \'' . $this->cacheDB->escapeString($key) . '\' AND ttl >= ' . time() . ' LIMIT 1';
82
		$result = $this->cacheDB->query($query);
83
84
		$value = null;
85
		while ($res = $result->fetchArray(SQLITE3_ASSOC))
86
			$value = $res['value'];
87
88
		return !empty($value) ? $value : null;
89
	}
90
91
	/**
92
	 * {@inheritDoc}
93
	 */
94
	public function putData($key, $value, $ttl = null)
95
	{
96
		$ttl = time() + (int) ($ttl !== null ? $ttl : $this->ttl);
97
		if ($value === null)
98
			$query = 'DELETE FROM cache WHERE key = \'' . $this->cacheDB->escapeString($key) . '\';';
99
		else
100
			$query = 'REPLACE INTO cache VALUES (\'' . $this->cacheDB->escapeString($key) . '\', \'' . $this->cacheDB->escapeString($value) . '\', ' . $ttl . ');';
101
		$result = $this->cacheDB->exec($query);
102
103
		return $result;
104
	}
105
106
	/**
107
	 * {@inheritDoc}
108
	 */
109
	public function cleanCache($type = '')
110
	{
111
		if ($type == 'expired')
112
			$query = 'DELETE FROM cache WHERE ttl >= ' . time() . ';';
113
		else
114
			$query = 'DELETE FROM cache;';
115
116
		$result = $this->cacheDB->exec($query);
117
118
		$query = 'VACUUM;';
119
		$this->cacheDB->exec($query);
120
121
		return $result;
122
	}
123
124
	/**
125
	 * {@inheritDoc}
126
	 */
127
	public function cacheSettings(array &$config_vars)
128
	{
129
		global $context, $txt;
130
131
		$class_name = $this->getImplementationClassKeyName();
132
		$class_name_txt_key = strtolower($class_name);
133
134
		$config_vars[] = $txt['cache_'. $class_name_txt_key .'_settings'];
135
		$config_vars[] = array(
136
			'cachedir_'. $class_name_txt_key,
137
			$txt['cachedir_'. $class_name_txt_key],
138
			'file',
139
			'text',
140
			36,
141
			'cache_'. $class_name_txt_key .'_cachedir');
142
143
		if (!isset($context['settings_post_javascript']))
144
			$context['settings_post_javascript'] = '';
145
146
		$context['settings_post_javascript'] .= '
147
			$("#cache_accelerator").change(function (e) {
148
				var cache_type = e.currentTarget.value;
149
				$("#cachedir_'. $class_name_txt_key .'").prop("disabled", cache_type != "'. $class_name .'");
150
			});';
151
	}
152
153
	/**
154
	 * Sets the $cachedir or uses the SMF default $cachedir..
155
	 *
156
	 * @access public
157
	 *
158
	 * @param string $dir A valid path
159
	 *
160
	 * @return boolean If this was successful or not.
161
	 */
162
	public function setCachedir($dir = null)
163
	{
164
		global $cachedir, $cachedir_sqlite;
165
166
		// If its invalid, use SMF's.
167
		if (is_null($dir) || !is_writable($dir))
168
			if (is_null($cachedir_sqlite) || !is_writable($cachedir_sqlite))
169
				$this->cachedir = $cachedir;
170
			else
171
				$this->cachedir = $cachedir_sqlite;
172
		else
173
			$this->cachedir = $dir;
174
	}
175
176
	/**
177
	 * {@inheritDoc}
178
	 */
179
	public function getVersion()
180
	{
181
		if (null == $this->cacheDB)
182
			$this->connect();
183
184
		return $this->cacheDB->version()['versionString'];
185
	}
186
187
	/**
188
	 * {@inheritDoc}
189
	 */
190
	public function housekeeping()
191
	{
192
		$this->cleanCache('expired');
193
	}
194
}
195
196
?>