1
<?php
2
/**
3
* File-based Output Cache Library
4
*
5
* @author Zhou Yuan <yuanzhou19@gmail.com>
6
* @link http://www.infopotato.com/
7
* @copyright Copyright © 2009-2011 Zhou Yuan
8
* @license http://www.opensource.org/licenses/mit-license.php MIT Licence
9
* @link based on http://www.jongales.com/blog/2009/02/18/simple-file-based-php-cache-class/
10
* @link based on http://www.rooftopsolutions.nl/article/107
11
*/
12
class Output_Cache_Library {
13
14
/**
15
* The cache dir. The dir should end with DIRECTORY_SEPARATOR
16
*
17
* @var string
18
*/
19
private $_dir;
20
21
/**
22
* Constructor
23
*
24
* @param array $config['cache_dir']
25
*
26
*/
27
public function __construct(array $config = NULL) {
28
if (count($config) > 0) {
29
if (isset($config['cache_dir'])) {
30
$this->_dir = $config['cache_dir'];
31
}
32
}
33
}
34
35
/**
36
* Find the filename for a certain key
37
*
38
* @param string
39
* @return string
40
*/
41
private function _name($key) {
42
return ($this->_dir).sha1($key);
43
}
44
45
/**
46
* Get the cached file for a certain key
47
*
48
* @param $key string
49
* @return mixed - FALSE|string (cached data)
50
*/
51
public function get($key) {
52
if ( ! is_dir($this->_dir)) {
53
return FALSE;
54
}
55
$cache_path = $this->_name($key);
56
57
if ( ! file_exists($cache_path) || ! is_readable($cache_path)) {
58
return FALSE;
59
}
60
// Open for reading only; use 'b' to force binary mode
61
if ( ! $fp = fopen($cache_path, 'rb')) {
62
return FALSE;
63
}
64
// To acquire a shared lock (reader)
65
flock($fp, LOCK_SH);
66
// file_get_contents() is much faster than fread()
67
// $cached_data is an array contains [0] => expire time, [1] => cached content
68
$cached_data = unserialize(file_get_contents($cache_path));
69
// To release a lock (shared or exclusive)
70
flock($fp, LOCK_UN);
71
// The lock is released also by fclose() (which is also called automatically when script finished).
72
fclose($fp);
73
74
if ($cached_data) {
75
// Check if the cached file was expired
76
if (time() > $cached_data[0]) {
77
$this->clear($key);
78
return FALSE;
79
}
80
return $cached_data[1];
81
}
82
return FALSE;
83
}
84
85
/**
86
* Create the cache file for a certain key
87
*
88
* @param $key string
89
* @param $data string the data to be cached
90
* @param $ttl integer - time to life (seconds)
91
* @return boolean
92
*/
93
public function set($key, $data, $ttl = 3600) {
94
if ( ! is_dir($this->_dir) || ! $this->_is_really_writable($this->_dir)) {
95
return FALSE;
96
}
97
$cache_path = $this->_name($key);
98
99
// Open for writing only; use 'b' to force binary mode
100
if ( ! $fp = fopen($cache_path, 'wb')) {
101
return FALSE;
102
}
103
// To acquire an exclusive lock (writer)
104
if (flock($fp, LOCK_EX)) {
105
// fwrite is faster than file_put_contents()
106
fwrite($fp, serialize(array(time() + $ttl, $data)));
107
// To release a lock (shared or exclusive)
108
flock($fp, LOCK_UN);
109
// The lock is released also by fclose() (which is also called automatically when script finished).
110
fclose($fp);
111
} else {
112
return FALSE;
113
}
114
chmod($cache_path, 0777);
115
return TRUE;
116
}
117
118
/**
119
* Delete the cached file for a certain key
120
*
121
* @param $key string
122
* @return boolean
123
*/
124
public function clear($key) {
125
$cache_path = $this->_name($key);
126
if (file_exists($cache_path)) {
127
// Deletes cached file
128
unlink($cache_path);
129
return TRUE;
130
}
131
return FALSE;
132
}
133
134
/**
135
* Tests for file writability
136
*
137
* is_writable() returns TRUE on Windows servers when you really can't write to
138
* the file, based on the read-only attribute. is_writable() is also unreliable
139
* on Unix servers if safe_mode is on.
140
*
141
* @return void
142
*/
143
private function _is_really_writable($file) {
144
// If we're on a Unix server with safe_mode off we call is_writable
145
if (DIRECTORY_SEPARATOR == '/' && @ini_get("safe_mode") == FALSE) {
146
return is_writable($file);
147
}
148
149
// For windows servers and safe_mode "on" installations we'll actually
150
// write a file then read it. Bah...
151
if (is_dir($file)) {
152
$file = rtrim($file, '/').'/'.md5(rand(1, 100));
153
154
if (($fp = @fopen($file, 'ab')) === FALSE) {
155
return FALSE;
156
}
157
158
fclose($fp);
159
@chmod($file, 0777);
160
@unlink($file);
161
return TRUE;
162
} elseif (($fp = @fopen($file, 'ab')) === FALSE) {
163
return FALSE;
164
}
165
166
fclose($fp);
167
return TRUE;
168
}
169
}
170
171
/* End of file: ./system/libraries/output_cache/output_cache_library.php */
Page URI: http://www.infopotato.com/index.php/code/library/output_cache/
