Subversion Repositories SmartDukaan

Rev

Rev 10582 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
10582 lgm 1
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2
 
3
 
4
 
5
class Cache
6
{
7
	private $_ci;
8
	private $_path;
9
	private $_contents;
10
	private $_filename;
11
	private $_expires;
12
	private $_default_expires;
13
	private $_created;
14
	private $_dependencies;
15
 
16
	/**
17
	 * Constructor - Initializes and references CI
18
	 */
19
	function __construct()
20
	{
21
		log_message('debug', "Cache Class Initialized.");
22
 
23
		$this->_ci =& get_instance();
24
		$this->_reset();
25
 
26
		$this->_ci->load->config('cache');
27
 
28
		$this->_path = $this->_ci->config->item('cache_dir');
29
		$this->_default_expires = $this->_ci->config->item('cache_default_expires');
30
		if ( ! is_dir($this->_path))
31
		{
32
			show_error("Cache Path not found: $this->_path");
33
		}
34
	}
35
 
36
	/**
37
	 * Initialize Cache object to empty
38
	 *
39
	 * @access	private
40
	 * @return	void
41
	 */
42
	private function _reset()
43
	{
44
		$this->_contents = NULL;
45
		$this->_filename = NULL;
46
		$this->_expires = NULL;
47
		$this->_created = NULL;
48
		$this->_dependencies = array();
49
	}
50
 
51
	/**
52
	 * Call a library's cached result or create new cache
53
	 *
54
	 * @access	public
55
	 * @param	string
56
	 * @return	array
57
	 */
58
	public function library($library, $method, $arguments = array(), $expires = NULL)
59
	{
60
		if ( ! class_exists(ucfirst($library)))
61
		{
62
			$this->_ci->load->library($library);
63
		}
64
 
65
		return $this->_call($library, $method, $arguments, $expires);
66
	}
67
 
68
	/**
69
	 * Call a model's cached result or create new cache
70
	 *
71
	 * @access	public
72
	 * @return	array
73
	 */
74
	public function model($model, $method, $arguments = array(), $expires = NULL)
75
	{
76
		if ( ! class_exists(ucfirst($model)))
77
		{
78
			$this->_ci->load->model($model);
79
		}
80
 
81
		return $this->_call($model, $method, $arguments, $expires);
82
	}
83
 
84
	// Depreciated, use model() or library()
85
	private function _call($property, $method, $arguments = array(), $expires = NULL)
86
	{
87
		$this->_ci->load->helper('security');
88
 
89
		if ( !  is_array($arguments))
90
		{
91
			$arguments = (array) $arguments;
92
		}
93
 
94
		// Clean given arguments to a 0-index array
95
		$arguments = array_values($arguments);
96
 
97
		$cache_file = $property.DIRECTORY_SEPARATOR.do_hash($method.serialize($arguments), 'sha1');
98
 
99
		// See if we have this cached or delete if $expires is negative
100
		if($expires >= 0)
101
		{
102
			$cached_response = $this->get($cache_file);
103
		}
104
		else
105
		{
106
			$this->delete($cache_file);
107
			return;
108
		}
109
 
110
		// Not FALSE? Return it
111
		if($cached_response !== FALSE && $cached_response !== NULL)
112
		{
113
			return $cached_response;
114
		}
115
 
116
		else
117
		{
118
			// Call the model or library with the method provided and the same arguments
119
			$new_response = call_user_func_array(array($this->_ci->$property, $method), $arguments);
120
			$this->write($new_response, $cache_file, $expires);
121
 
122
			return $new_response;
123
		}
124
	}
125
 
126
	/**
127
	 * Helper functions for the dependencies property
128
	 */
129
	function set_dependencies($dependencies)
130
	{
131
		if (is_array($dependencies))
132
		{
133
			$this->_dependencies = $dependencies;
134
		}
135
		else
136
		{
137
			$this->_dependencies = array($dependencies);
138
		}
139
 
140
		return $this;
141
	}
142
 
143
	function add_dependencies($dependencies)
144
	{
145
		if (is_array($dependencies))
146
		{
147
			$this->_dependencies = array_merge($this->_dependencies, $dependencies);
148
		}
149
		else
150
		{
151
			$this->_dependencies[] = $dependencies;
152
		}
153
 
154
		return $this;
155
	}
156
 
157
	function get_dependencies() { return $this->_dependencies; }
158
 
159
	/**
160
	 * Helper function to get the cache creation date
161
	 */
162
	function get_created($created) { return $this->_created; }
163
 
164
 
165
	/**
166
	 * Retrieve Cache File
167
	 *
168
	 * @access	public
169
	 * @param	string
170
	 * @param	boolean
171
	 * @return	mixed
172
	 */
173
	function get($filename = NULL, $use_expires = true)
174
	{
175
		// Check if cache was requested with the function or uses this object
176
		//print_r($filename);
20488 amit.gupta 177
		log_message('debug', "Retrieving Cache: ".$filename);
10582 lgm 178
		if ($filename !== NULL)
179
		{
180
			$this->_reset();
181
			$this->_filename = $filename;
182
		}
183
 
184
		// Check directory permissions
185
		if ( ! is_dir($this->_path) OR ! is_really_writable($this->_path))
186
		{
187
			return FALSE;
188
		}
189
 
190
		// Build the file path.
191
		$filepath = $this->_path.$this->_filename.'.cache';
192
		// Check if the cache exists, if not return FALSE
193
		if ( ! @file_exists($filepath))
194
		{
195
 
196
			return FALSE;
197
		}
198
		// Check if the cache can be opened, if not return FALSE
199
		if ( ! $fp = @fopen($filepath, FOPEN_READ))
200
		{
201
			return FALSE;
202
		}
203
		// Lock the cache
204
		flock($fp, LOCK_SH);
205
 
206
		// If the file contains data return it, otherwise return NULL
207
		if (filesize($filepath) > 0)
208
		{
209
			//echo 'file size'.filesize($filepath);
210
			$this->_contents = unserialize(fread($fp, filesize($filepath)));
211
			//print_r($this->_contents);
212
		}
213
		else
214
		{
215
			//echo 'inside else';
216
			$this->_contents = NULL;
217
		}
218
		// Unlock the cache and close the file
219
		flock($fp, LOCK_UN);
220
		fclose($fp);
221
 
222
		// Check cache expiration, delete and return FALSE when expired
223
		if ($use_expires && ! empty($this->_contents['__cache_expires']) && $this->_contents['__cache_expires'] < time())
224
		{
225
			//echo 'inside if';
226
			//$this->delete($filename);
227
			return FALSE;
228
		}
229
		// Check Cache dependencies
230
		if(isset($this->_contents['__cache_dependencies']))
231
		{
232
			//echo 'inside if';
233
			foreach ($this->_contents['__cache_dependencies'] as $dep)
234
			{
235
				$cache_created = filemtime($this->_path.$this->_filename.'.cache');
236
 
237
				// If dependency doesn't exist or is newer than this cache, delete and return FALSE
238
				if (! file_exists($this->_path.$dep.'.cache') or filemtime($this->_path.$dep.'.cache') > $cache_created)
239
				{
240
					//echo 'file deleted';
241
					$this->delete($filename);
242
					return FALSE;
243
				}
244
			}
245
		}
246
		// Instantiate the object variables
247
		$this->_expires		= isset($this->_contents['__cache_expires']) ? $this->_contents['__cache_expires'] : NULL;
248
		$this->_dependencies = isset($this->_contents['__cache_dependencies']) ? $this->_contents['__cache_dependencies'] : NULL;
249
		$this->_created		= isset($this->_contents['__cache_created']) ? $this->_contents['__cache_created'] : NULL;
250
 
251
		// Cleanup the meta variables from the contents
252
		$this->_contents = @$this->_contents['__cache_contents'];
253
		log_message('debug', "Cache retrieved: ".$filename);
254
		//print_r($this->_contents);
255
		//echo "<br/>----------------------------------------cache file ends--------------------------------------<br/>";
256
		// Return the cache
257
		log_message('debug', "Cache retrieved: ".$filename);
20488 amit.gupta 258
		log_message('debug', "Hahaha");
10582 lgm 259
		return $this->_contents;
260
	}
261
 
262
	/**
263
	 * Write Cache File
264
	 *
265
	 * @access	public
266
	 * @param	mixed
267
	 * @param	string
268
	 * @param	int
269
	 * @param	array
270
	 * @return	void
271
	 */
272
	function write($contents = NULL, $filename = NULL, $expires = NULL, $dependencies = array())
273
	{
274
		// Check if cache was passed with the function or uses this object
275
		if ($contents !== NULL)
276
		{
277
			$this->_reset();
278
			$this->_contents = $contents;
279
			$this->_filename = $filename;
280
			$this->_expires = $expires;
281
			$this->_dependencies = $dependencies;
282
		}
283
 
284
		// Put the contents in an array so additional meta variables
285
		// can be easily removed from the output
286
		$this->_contents = array('__cache_contents' => $this->_contents);
287
 
288
		// Check directory permissions
289
		if ( ! is_dir($this->_path) OR ! is_really_writable($this->_path))
290
		{
291
			return;
292
		}
293
 
294
		// check if filename contains dirs
295
		$subdirs = explode(DIRECTORY_SEPARATOR, $this->_filename);
296
		if (count($subdirs) > 1)
297
		{
298
			array_pop($subdirs);
299
			$test_path = $this->_path.implode(DIRECTORY_SEPARATOR, $subdirs);
300
 
301
			// check if specified subdir exists
302
			if ( ! @file_exists($test_path))
303
			{
304
				// create non existing dirs, asumes PHP5
305
				if ( ! @mkdir($test_path, DIR_WRITE_MODE, TRUE)) return FALSE;
306
			}
307
		}
308
 
309
		// Set the path to the cachefile which is to be created
310
		$cache_path = $this->_path.$this->_filename.'.cache';
311
 
312
		// Open the file and log if an error occures
313
		if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
314
		{
315
			log_message('error', "Unable to write Cache file: ".$cache_path);
316
			return;
317
		}
318
 
319
		// Meta variables
320
		$this->_contents['__cache_created'] = time();
321
		$this->_contents['__cache_dependencies'] = $this->_dependencies;
322
 
323
		// Add expires variable if its set...
324
		if (! empty($this->_expires))
325
		{
326
			$this->_contents['__cache_expires'] = $this->_expires + time();
327
		}
328
		// ...or add default expiration if its set
329
		elseif (! empty($this->_default_expires) )
330
		{
331
			$this->_contents['__cache_expires'] = $this->_default_expires + time();
332
		}
333
 
334
		// Lock the file before writing or log an error if it failes
335
		if (flock($fp, LOCK_EX))
336
		{
337
			fwrite($fp, serialize($this->_contents));
338
			flock($fp, LOCK_UN);
339
		}
340
		else
341
		{
342
			log_message('error', "Cache was unable to secure a file lock for file at: ".$cache_path);
343
			return;
344
		}
345
		fclose($fp);
346
		@chmod($cache_path, DIR_WRITE_MODE);
347
 
348
		// Log success
349
		log_message('debug', "Cache file written: ".$cache_path);
350
 
351
		// Reset values
352
		$this->_reset();
353
	}
354
 
355
	/**
356
	 * Delete Cache File
357
	 *
358
	 * @access	public
359
	 * @param	string
360
	 * @return	void
361
	 */
362
	function delete($filename = NULL)
363
	{
364
		if ($filename !== NULL) $this->_filename = $filename;
365
 
366
		$file_path = $this->_path.$this->_filename.'.cache';
367
 
368
		if (file_exists($file_path)) unlink($file_path);
369
 
370
		// Reset values
371
		$this->_reset();
372
	}
373
 
374
	/**
375
	 * Delete a group of cached files
376
	 *
377
	 * Allows you to pass a group to delete cache. Example:
378
	 *
379
	 * <code>
380
	 * $this->cache->write($data, 'nav_title');
381
	 * $this->cache->write($links, 'nav_links');
382
	 * $this->cache->delete_group('nav_');
383
	 * </code>
384
	 *
385
	 * @param 	string $group
386
	 * @return 	void
387
	 */
388
	public function delete_group($group = null)
389
	{
390
		if ($group === null)
391
		{
392
			return FALSE;
393
		}
394
 
395
		$this->_ci->load->helper('directory');
396
		$map = directory_map($this->_path, TRUE);
397
 
398
		foreach ($map AS $file)
399
		{
400
			if (strpos($file, $group)  !== FALSE)
401
			{
402
				unlink($this->_path.$file);
403
			}
404
		}
405
 
406
		// Reset values
407
		$this->_reset();
408
	}
409
 
410
	/**
411
	 * Delete Full Cache or Cache subdir
412
	 *
413
	 * @access	public
414
	 * @param	string
415
	 * @return	void
416
	 */
417
	function delete_all($dirname = '')
418
	{
419
		if (empty($this->_path))
420
		{
421
			return FALSE;
422
		}
423
 
424
		$this->_ci->load->helper('file');
425
		if (file_exists($this->_path.$dirname)) delete_files($this->_path.$dirname, TRUE);
426
 
427
		// Reset values
428
		$this->_reset();
429
	}
430
}
431
 
432
/* End of file Cache.php */
433
/* Location: ./application/libraries/Cache.php */