Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Container for all PDO-based cache methods. Inherits additional methods from <CacheCore>. Adheres
4
 * to the ICacheCore interface.
5
 *
6
 * @version 2012.01.28
7
 * @copyright 2006-2012 Ryan Parman
8
 * @copyright 2006-2010 Foleeo, Inc.
9
 * @copyright 2012 Amazon.com, Inc. or its affiliates.
10
 * @copyright 2008-2010 Contributors
11
 * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
12
 * @link http://github.com/skyzyx/cachecore CacheCore
13
 * @link http://getcloudfusion.com CloudFusion
14
 * @link http://php.net/pdo PDO
15
 */
16
class CachePDO extends CacheCore implements ICacheCore
17
{
18
	/**
19
	 * Reference to the PDO connection object.
20
	 */
21
	var $pdo = null;
22
 
23
	/**
24
	 * Holds the parsed URL components.
25
	 */
26
	var $dsn = null;
27
 
28
	/**
29
	 * Holds the PDO-friendly version of the connection string.
30
	 */
31
	var $dsn_string = null;
32
 
33
	/**
34
	 * Holds the prepared statement for creating an entry.
35
	 */
36
	var $create = null;
37
 
38
	/**
39
	 * Holds the prepared statement for reading an entry.
40
	 */
41
	var $read = null;
42
 
43
	/**
44
	 * Holds the prepared statement for updating an entry.
45
	 */
46
	var $update = null;
47
 
48
	/**
49
	 * Holds the prepared statement for resetting the expiry of an entry.
50
	 */
51
	var $reset = null;
52
 
53
	/**
54
	 * Holds the prepared statement for deleting an entry.
55
	 */
56
	var $delete = null;
57
 
58
	/**
59
	 * Holds the response of the read so we only need to fetch it once instead of doing
60
	 * multiple queries.
61
	 */
62
	var $store_read = null;
63
 
64
 
65
	/*%******************************************************************************************%*/
66
	// CONSTRUCTOR
67
 
68
	/**
69
	 * Constructs a new instance of this class.
70
	 *
71
	 * Tested with [MySQL 5.0.x](http://mysql.com), [PostgreSQL](http://postgresql.com), and
72
	 * [SQLite 3.x](http://sqlite.org). SQLite 2.x is assumed to work. No other PDO-supported databases have
73
	 * been tested (e.g. Oracle, Microsoft SQL Server, IBM DB2, ODBC, Sybase, Firebird). Feel free to send
74
	 * patches for additional database support.
75
	 *
76
	 * See <http://php.net/pdo> for more information.
77
	 *
78
	 * @param string $name (Required) A name to uniquely identify the cache object.
79
	 * @param string $location (Required) The location to store the cache object in. This may vary by cache method.
80
	 * @param integer $expires (Required) The number of seconds until a cache object is considered stale.
81
	 * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. Defaults to true.
82
	 * @return object Reference to the cache object.
83
	 */
84
	public function __construct($name, $location, $expires, $gzip = true)
85
	{
86
		// Make sure the name is no longer than 40 characters.
87
		$name = sha1($name);
88
 
89
		// Call parent constructor and set id.
90
		parent::__construct($name, $location, $expires, $gzip);
91
		$this->id = $this->name;
92
		$options = array();
93
 
94
		// Check if the location contains :// (e.g. mysql://user:pass@hostname:port/table)
95
		if (stripos($location, '://') === false)
96
		{
97
			// No? Just pass it through.
98
			$this->dsn = parse_url($location);
99
			$this->dsn_string = $location;
100
		}
101
		else
102
		{
103
			// Yes? Parse and set the DSN
104
			$this->dsn = parse_url($location);
105
			$this->dsn_string = $this->dsn['scheme'] . ':host=' . $this->dsn['host'] . ((isset($this->dsn['port'])) ? ';port=' . $this->dsn['port'] : '') . ';dbname=' . substr($this->dsn['path'], 1);
106
		}
107
 
108
		// Make sure that user/pass are defined.
109
		$user = isset($this->dsn['user']) ? $this->dsn['user'] : null;
110
		$pass = isset($this->dsn['pass']) ? $this->dsn['pass'] : null;
111
 
112
		// Set persistence for databases that support it.
113
		switch ($this->dsn['scheme'])
114
		{
115
			case 'mysql': // MySQL
116
			case 'pgsql': // PostgreSQL
117
				$options[PDO::ATTR_PERSISTENT] = true;
118
				break;
119
		}
120
 
121
		// Instantiate a new PDO object with a persistent connection.
122
		$this->pdo = new PDO($this->dsn_string, $user, $pass, $options);
123
 
124
		// Define prepared statements for improved performance.
125
		$this->create = $this->pdo->prepare("INSERT INTO cache (id, expires, data) VALUES (:id, :expires, :data)");
126
		$this->read = $this->pdo->prepare("SELECT id, expires, data FROM cache WHERE id = :id");
127
		$this->reset = $this->pdo->prepare("UPDATE cache SET expires = :expires WHERE id = :id");
128
		$this->delete = $this->pdo->prepare("DELETE FROM cache WHERE id = :id");
129
	}
130
 
131
	/**
132
	 * Creates a new cache.
133
	 *
134
	 * @param mixed $data (Required) The data to cache.
135
	 * @return boolean Whether the operation was successful.
136
	 */
137
	public function create($data)
138
	{
139
		$data = serialize($data);
140
		$data = $this->gzip ? gzcompress($data) : $data;
141
 
142
		$this->create->bindParam(':id', $this->id);
143
		$this->create->bindParam(':data', $data);
144
		$this->create->bindParam(':expires', $this->generate_timestamp());
145
 
146
		return (bool) $this->create->execute();
147
	}
148
 
149
	/**
150
	 * Reads a cache.
151
	 *
152
	 * @return mixed Either the content of the cache object, or boolean `false`.
153
	 */
154
	public function read()
155
	{
156
		if (!$this->store_read)
157
		{
158
			$this->read->bindParam(':id', $this->id);
159
			$this->read->execute();
160
			$this->store_read = $this->read->fetch(PDO::FETCH_ASSOC);
161
		}
162
 
163
		if ($this->store_read)
164
		{
165
			$data = $this->store_read['data'];
166
			$data = $this->gzip ? gzuncompress($data) : $data;
167
 
168
			return unserialize($data);
169
		}
170
 
171
		return false;
172
	}
173
 
174
	/**
175
	 * Updates an existing cache.
176
	 *
177
	 * @param mixed $data (Required) The data to cache.
178
	 * @return boolean Whether the operation was successful.
179
	 */
180
	public function update($data)
181
	{
182
		$this->delete();
183
		return $this->create($data);
184
	}
185
 
186
	/**
187
	 * Deletes a cache.
188
	 *
189
	 * @return boolean Whether the operation was successful.
190
	 */
191
	public function delete()
192
	{
193
		$this->delete->bindParam(':id', $this->id);
194
		return $this->delete->execute();
195
	}
196
 
197
	/**
198
	 * Checks whether the cache object is expired or not.
199
	 *
200
	 * @return boolean Whether the cache is expired or not.
201
	 */
202
	public function is_expired()
203
	{
204
		if ($this->timestamp() + $this->expires < time())
205
		{
206
			return true;
207
		}
208
 
209
		return false;
210
	}
211
 
212
	/**
213
	 * Retrieves the timestamp of the cache.
214
	 *
215
	 * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
216
	 */
217
	public function timestamp()
218
	{
219
		if (!$this->store_read)
220
		{
221
			$this->read->bindParam(':id', $this->id);
222
			$this->read->execute();
223
			$this->store_read = $this->read->fetch(PDO::FETCH_ASSOC);
224
		}
225
 
226
		if ($this->store_read)
227
		{
228
			$value = $this->store_read['expires'];
229
 
230
			// If 'expires' isn't yet an integer, convert it into one.
231
			if (!is_numeric($value))
232
			{
233
				$value = strtotime($value);
234
			}
235
 
236
			$this->timestamp = date('U', $value);
237
			return $this->timestamp;
238
		}
239
 
240
		return false;
241
	}
242
 
243
	/**
244
	 * Resets the freshness of the cache.
245
	 *
246
	 * @return boolean Whether the operation was successful.
247
	 */
248
	public function reset()
249
	{
250
		$this->reset->bindParam(':id', $this->id);
251
		$this->reset->bindParam(':expires', $this->generate_timestamp());
252
		return (bool) $this->reset->execute();
253
	}
254
 
255
	/**
256
	 * Returns a list of supported PDO database drivers. Identical to <PDO::getAvailableDrivers()>.
257
	 *
258
	 * @return array The list of supported database drivers.
259
	 * @link http://php.net/pdo.getavailabledrivers PHP Method
260
	 */
261
	public function get_drivers()
262
	{
263
		return PDO::getAvailableDrivers();
264
	}
265
 
266
	/**
267
	 * Returns a timestamp value apropriate to the current database type.
268
	 *
269
	 * @return mixed Timestamp for MySQL and PostgreSQL, integer value for SQLite.
270
	 */
271
	protected function generate_timestamp()
272
	{
273
		// Define 'expires' settings differently.
274
		switch ($this->dsn['scheme'])
275
		{
276
			// These support timestamps.
277
			case 'mysql': // MySQL
278
			case 'pgsql': // PostgreSQL
279
				$expires = date(DATE_FORMAT_MYSQL, time());
280
				break;
281
 
282
			// These support integers.
283
			case 'sqlite': // SQLite 3
284
			case 'sqlite2': // SQLite 2
285
				$expires = time();
286
				break;
287
		}
288
 
289
		return $expires;
290
	}
291
}
292
 
293
 
294
/*%******************************************************************************************%*/
295
// EXCEPTIONS
296
 
297
class CachePDO_Exception extends CacheCore_Exception {}