blob: 56b7356487e0bc9b0d420d6f06ee009f9092eb6b [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreev24276a32012-01-08 02:44:38 +02008 *
Andrey Andreevcce6bd12018-01-09 11:32:02 +02009 * Copyright (c) 2014 - 2018, British Columbia Institute of Technology
Andrey Andreev24276a32012-01-08 02:44:38 +020010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Andrey Andreevcce6bd12018-01-09 11:32:02 +020032 * @copyright Copyright (c) 2014 - 2018, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 1.0.0
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Derek Allard2067d1a2008-11-13 22:59:24 +000040/**
41 * Database Cache Class
42 *
43 * @category Database
Derek Jonesf4a4bd82011-10-20 12:18:42 -050044 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +020045 * @link https://codeigniter.com/user_guide/database/
Derek Allard2067d1a2008-11-13 22:59:24 +000046 */
47class CI_DB_Cache {
48
Andrey Andreevae85eb42012-11-02 01:42:31 +020049 /**
50 * CI Singleton
51 *
52 * @var object
53 */
Andrey Andreev24276a32012-01-08 02:44:38 +020054 public $CI;
Andrey Andreevae85eb42012-11-02 01:42:31 +020055
56 /**
57 * Database object
58 *
59 * Allows passing of DB object so that multiple database connections
60 * and returned DB objects can be supported.
61 *
62 * @var object
63 */
64 public $db;
65
66 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +000067
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030068 /**
69 * Constructor
70 *
Andrey Andreev6df461a2012-10-24 14:57:37 +030071 * @param object &$db
Andrey Andreev5fd3ae82012-10-24 14:55:35 +030072 * @return void
73 */
Andrey Andreev24276a32012-01-08 02:44:38 +020074 public function __construct(&$db)
Derek Allard2067d1a2008-11-13 22:59:24 +000075 {
Andrey Andreev24276a32012-01-08 02:44:38 +020076 // Assign the main CI object to $this->CI and load the file helper since we use it a lot
Derek Allard2067d1a2008-11-13 22:59:24 +000077 $this->CI =& get_instance();
78 $this->db =& $db;
Barry Mienydd671972010-10-04 16:33:58 +020079 $this->CI->load->helper('file');
Andrey Andreev256a18c2012-10-23 12:18:32 +030080
81 $this->check_path();
Derek Allard2067d1a2008-11-13 22:59:24 +000082 }
83
84 // --------------------------------------------------------------------
85
86 /**
87 * Set Cache Directory Path
88 *
Andrey Andreevae85eb42012-11-02 01:42:31 +020089 * @param string $path Path to the cache directory
Derek Allard2067d1a2008-11-13 22:59:24 +000090 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +020091 */
Andrey Andreev24276a32012-01-08 02:44:38 +020092 public function check_path($path = '')
Derek Allard2067d1a2008-11-13 22:59:24 +000093 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +010094 if ($path === '')
Derek Allard2067d1a2008-11-13 22:59:24 +000095 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +010096 if ($this->db->cachedir === '')
Derek Allard2067d1a2008-11-13 22:59:24 +000097 {
98 return $this->db->cache_off();
99 }
Barry Mienydd671972010-10-04 16:33:58 +0200100
Derek Allard2067d1a2008-11-13 22:59:24 +0000101 $path = $this->db->cachedir;
102 }
Barry Mienydd671972010-10-04 16:33:58 +0200103
Derek Allard2067d1a2008-11-13 22:59:24 +0000104 // Add a trailing slash to the path if needed
Andrey Andreev256a18c2012-10-23 12:18:32 +0300105 $path = realpath($path)
106 ? rtrim(realpath($path), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR
107 : rtrim($path, '/').'/';
Derek Allard2067d1a2008-11-13 22:59:24 +0000108
Brian Gottier51c0b552012-11-13 18:47:19 -0800109 if ( ! is_dir($path))
Derek Allard2067d1a2008-11-13 22:59:24 +0000110 {
Brian Gottier4a18c952012-11-14 07:40:55 -0800111 log_message('debug', 'DB cache path error: '.$path);
Brian Gottier51c0b552012-11-13 18:47:19 -0800112
Derek Allard2067d1a2008-11-13 22:59:24 +0000113 // If the path is wrong we'll turn off caching
114 return $this->db->cache_off();
115 }
Barry Mienydd671972010-10-04 16:33:58 +0200116
Brian Gottier51c0b552012-11-13 18:47:19 -0800117 if ( ! is_really_writable($path))
118 {
Brian Gottier4a18c952012-11-14 07:40:55 -0800119 log_message('debug', 'DB cache dir not writable: '.$path);
Brian Gottier51c0b552012-11-13 18:47:19 -0800120
121 // If the path is not really writable we'll turn off caching
122 return $this->db->cache_off();
123 }
124
Derek Allard2067d1a2008-11-13 22:59:24 +0000125 $this->db->cachedir = $path;
126 return TRUE;
127 }
Barry Mienydd671972010-10-04 16:33:58 +0200128
Derek Allard2067d1a2008-11-13 22:59:24 +0000129 // --------------------------------------------------------------------
130
131 /**
132 * Retrieve a cached query
133 *
134 * The URI being requested will become the name of the cache sub-folder.
Andrey Andreevae85eb42012-11-02 01:42:31 +0200135 * An MD5 hash of the SQL statement will become the cache file name.
Derek Allard2067d1a2008-11-13 22:59:24 +0000136 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300137 * @param string $sql
Derek Allard2067d1a2008-11-13 22:59:24 +0000138 * @return string
139 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200140 public function read($sql)
Derek Allard2067d1a2008-11-13 22:59:24 +0000141 {
Andrey Andreeve4c30192012-06-04 15:08:24 +0300142 $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
143 $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
Barry Mienydd671972010-10-04 16:33:58 +0200144 $filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql);
145
Andrey Andreevc9054be2017-05-10 11:36:31 +0300146 if ( ! is_file($filepath) OR FALSE === ($cachedata = file_get_contents($filepath)))
Barry Mienydd671972010-10-04 16:33:58 +0200147 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000148 return FALSE;
149 }
Barry Mienydd671972010-10-04 16:33:58 +0200150
151 return unserialize($cachedata);
152 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000153
154 // --------------------------------------------------------------------
155
156 /**
157 * Write a query to a cache file
158 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300159 * @param string $sql
160 * @param object $object
Derek Allard2067d1a2008-11-13 22:59:24 +0000161 * @return bool
162 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200163 public function write($sql, $object)
Derek Allard2067d1a2008-11-13 22:59:24 +0000164 {
Andrey Andreeve4c30192012-06-04 15:08:24 +0300165 $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
166 $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
Derek Allard2067d1a2008-11-13 22:59:24 +0000167 $dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';
Derek Allard2067d1a2008-11-13 22:59:24 +0000168 $filename = md5($sql);
Barry Mienydd671972010-10-04 16:33:58 +0200169
Andrey Andreev45965742014-08-27 20:40:11 +0300170 if ( ! is_dir($dir_path) && ! @mkdir($dir_path, 0750))
Derek Allard2067d1a2008-11-13 22:59:24 +0000171 {
Andrey Andreev45965742014-08-27 20:40:11 +0300172 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000173 }
Barry Mienydd671972010-10-04 16:33:58 +0200174
Derek Allard2067d1a2008-11-13 22:59:24 +0000175 if (write_file($dir_path.$filename, serialize($object)) === FALSE)
176 {
177 return FALSE;
178 }
Barry Mienydd671972010-10-04 16:33:58 +0200179
Andrey Andreev45965742014-08-27 20:40:11 +0300180 chmod($dir_path.$filename, 0640);
Derek Allard2067d1a2008-11-13 22:59:24 +0000181 return TRUE;
182 }
183
184 // --------------------------------------------------------------------
185
186 /**
187 * Delete cache files within a particular directory
188 *
Andrey Andreevae85eb42012-11-02 01:42:31 +0200189 * @param string $segment_one
190 * @param string $segment_two
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300191 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000192 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200193 public function delete($segment_one = '', $segment_two = '')
Barry Mienydd671972010-10-04 16:33:58 +0200194 {
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100195 if ($segment_one === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000196 {
Andrey Andreeve4c30192012-06-04 15:08:24 +0300197 $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
Derek Allard2067d1a2008-11-13 22:59:24 +0000198 }
Barry Mienydd671972010-10-04 16:33:58 +0200199
Alex Bilbie48a2baf2012-06-02 11:09:54 +0100200 if ($segment_two === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000201 {
Andrey Andreeve4c30192012-06-04 15:08:24 +0300202 $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
Derek Allard2067d1a2008-11-13 22:59:24 +0000203 }
Barry Mienydd671972010-10-04 16:33:58 +0200204
Derek Allard2067d1a2008-11-13 22:59:24 +0000205 $dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';
Derek Allard2067d1a2008-11-13 22:59:24 +0000206 delete_files($dir_path, TRUE);
207 }
208
209 // --------------------------------------------------------------------
210
211 /**
212 * Delete all existing cache files
213 *
Andrey Andreev5fd3ae82012-10-24 14:55:35 +0300214 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000215 */
Andrey Andreev24276a32012-01-08 02:44:38 +0200216 public function delete_all()
Derek Allard2067d1a2008-11-13 22:59:24 +0000217 {
Andrey Andreev53b8ef52012-11-08 21:38:53 +0200218 delete_files($this->db->cachedir, TRUE, TRUE);
Derek Allard2067d1a2008-11-13 22:59:24 +0000219 }
220
221}