diff --git a/cron/delete_invalid.php b/cron/delete_invalid.php index d70e0c3..820bcf5 100644 --- a/cron/delete_invalid.php +++ b/cron/delete_invalid.php @@ -22,9 +22,13 @@ $ext = new Extension_cachelite; while (true) { - $next = Symphony::Database()->fetch( - "SELECT * FROM `tbl_cachelite_invalid` LIMIT 1" - ); + $next = Symphony::Database() + ->select(['*']) + ->from('tbl_cachelite_invalid') + ->limit(1) + ->execute() + ->rows(); + if (empty($next)) { break; } @@ -49,10 +53,14 @@ sleep(1); echo '. Done.' . PHP_EOL; } - Symphony::Database()->delete( - 'tbl_cachelite_invalid', - " `section_id` = $section_id AND `entry_id` = $entry_id" - ); + + Symphony::Database() + ->delete('tbl_cachelite_invalid') + ->where(['section_id' => $section_id]) + ->where(['entry_id' => $entry_id]) + ->execute() + ->success(); + sleep(1); } diff --git a/extension.driver.php b/extension.driver.php index 1b23e83..2bcc1c5 100755 --- a/extension.driver.php +++ b/extension.driver.php @@ -384,7 +384,7 @@ public function interceptPage($context) $modified = $this->_cacheLite->lastModified(); $modified_gmt = gmdate('r', $modified); if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $modified_gmt || - str_replace('"', NULL, stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == $this->computeEtag()){ + str_replace('"', null, stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == $this->computeEtag()){ Page::renderStatusCode(Page::HTTP_NOT_MODIFIED); exit(); } @@ -492,11 +492,13 @@ public function entryEdit($context) public function entryDelete($context) { if (Symphony::Configuration()->get('backend-delegates', 'cachelite') == 'no') return; - $ids = !is_array($context['entry_id']) ? array($context['entry_id']) : $context['entry_id']; - // flush by Entry ID - foreach ($ids as $id) { - $this->clearPagesByStrategy($id, 'entry'); + $id = $context['entry_id']; + if (!is_array($id)) { + $id = array($id); + } + foreach ($id as $i) { + $this->clearPagesByStrategy($i, 'entry'); } } @@ -665,10 +667,14 @@ public function getPagesByContent($id, $type) try { $col = $type == 'entry' ? 'entry_id' : 'section_id'; $id = General::intval($id); - return Symphony::Database()->fetch( - "SELECT DISTINCT `page` FROM `tbl_cachelite_references` - WHERE `$col` = $id" - ); + + return Symphony::Database() + ->select(['page']) + ->distinct() + ->from('tbl_cachelite_references') + ->where([$col => $id]) + ->execute() + ->rows(); } catch (Exception $ex) { Symphony::Log()->pushExceptionToLog($ex); } @@ -680,10 +686,14 @@ public function isInvalidByContent($id, $type) try { $col = $type == 'entry' ? 'entry_id' : 'section_id'; $id = General::intval($id); - return !empty(Symphony::Database()->fetch( - "SELECT DISTINCT `$col` FROM `tbl_cachelite_invalid` - WHERE `$col` = $id" - )); + + return Symphony::Database() + ->select([$col]) + ->distinct() + ->from('tbl_cachelite_invalid') + ->where([$col => $id]) + ->execute() + ->rows(); } catch (Exception $ex) { Symphony::Log()->pushExceptionToLog($ex); } @@ -693,10 +703,11 @@ public function isInvalidByContent($id, $type) public function deletePageReferences($url) { try { - $url = Symphony::Database()->cleanValue($url); - return Symphony::Database()->query( - "DELETE FROM `tbl_cachelite_references` WHERE `page` = '$url'" - ); + return Symphony::Database() + ->delete('tbl_cachelite_references') + ->where(['page' => $url]) + ->execute() + ->success(); } catch (Exception $ex) { Symphony::Log()->pushExceptionToLog($ex); } @@ -705,28 +716,36 @@ public function deletePageReferences($url) protected function saveReferences($reference, $url, $ids) { - try { - $now = DateTimeObj::get('Y-m-d H:i:s'); - $values = array(); - foreach ($ids as $id) { + $now = DateTimeObj::get('Y-m-d H:i:s'); + $values = array(); + $result = true; + foreach ($ids as $id) { + try { $id = General::intval($id); - $values[] = "('$url', $id, '$now')"; + + $thisResult = Symphony::Database() + ->insert('tbl_cachelite_references') + ->values([ + 'page' => $url, + $reference => $id, + 'timestamp' => $now, + ]) + ->updateOnDuplicateKey() + ->execute() + ->success(); + if (!$thisResult) { + $result = false; + } + } catch (Exception $ex) { + $result = false; + Symphony::Log()->pushExceptionToLog($ex); } - $values = implode(',', $values); - return Symphony::Database()->query( - "INSERT INTO `tbl_cachelite_references` (`page`, `$reference`, `timestamp`) - VALUES $values - ON DUPLICATE KEY UPDATE `timestamp` = '$now'" - ); - } catch (Exception $ex) { - Symphony::Log()->pushExceptionToLog($ex); } - return false; + return $result; } protected function savePageReferences($url, array $sections, array $entries) { - $url = Symphony::Database()->cleanValue($url); // Create sections rows $sections = $this->saveReferences('section_id', $url, $sections); // Create entries rows @@ -738,12 +757,14 @@ protected function saveInvalid($id, $type) { $col = $type == 'entry' ? 'entry_id' : 'section_id'; try { - $id = General::intval(Symphony::Database()->cleanValue($id)); - return Symphony::Database()->query( - "INSERT INTO `tbl_cachelite_invalid` (`$col`) - VALUES ($id) - ON DUPLICATE KEY UPDATE `$col` = `$col`" - ); + return Symphony::Database() + ->insert('tbl_cachelite_invalid') + ->values([ + $col => $id, + ]) + ->updateOnDuplicateKey() + ->execute() + ->success(); } catch (Exception $ex) { Symphony::Log()->pushExceptionToLog($ex); throw $ex; @@ -754,52 +775,100 @@ protected function saveInvalid($id, $type) protected function createPageTable() { // Create extension table - return Symphony::Database()->query(" - CREATE TABLE `tbl_cachelite_references` ( - `page` char(128) NOT NULL, - `section_id` int(11) NOT NULL default 0, - `entry_id` int(11) NOT NULL default 0, - `timestamp` datetime NOT NULL /*!50600 default CURRENT_TIMESTAMP */, - PRIMARY KEY (`page`, `section_id`, `entry_id`), - KEY `page` (`page`), - KEY `section_page` (`page`, `section_id`), - KEY `entry_page` (`page`, `entry_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci - "); + return Symphony::Database() + ->create('tbl_cachelite_references') + ->ifNotExists() + ->fields([ + 'page' => 'char(128)', + 'section_id' => [ + 'type' => 'int(11)', + 'default' => 0, + ], + 'entry_id' => [ + 'type' => 'int(11)', + 'default' => 0, + ], + 'timestamp' => 'datetime', + ]) + ->keys([ + 'page_section_entry' => [ + 'type' => 'primary', + 'cols' => ['page', 'section_id', 'entry_id'], + ], + 'page' => 'key', + 'section_page' => [ + 'type' => 'key', + 'cols' => ['page', 'section_id'], + ], + 'entry_page' => [ + 'type' => 'key', + 'cols' => ['page', 'entry_id'], + ], + ]) + ->execute() + ->success(); } protected function createInvalidTable() { // Create extension table - return Symphony::Database()->query(" - CREATE TABLE `tbl_cachelite_invalid` ( - `section_id` int(11) NOT NULL default 0, - `entry_id` int(11) NOT NULL default 0, - PRIMARY KEY (`section_id`, `entry_id`), - KEY `section_id` (`section_id`), - KEY `entry_id` (`entry_id`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci - "); + return Symphony::Database() + ->create('tbl_cachelite_invalid') + ->ifNotExists() + ->fields([ + 'section_id' => [ + 'type' => 'int(11)', + 'default' => 0, + ], + 'entry_id' => [ + 'type' => 'int(11)', + 'default' => 0, + ], + ]) + ->keys([ + 'section_entry' => [ + 'type' => 'primary', + 'cols' => ['section_id', 'entry_id'], + ], + 'section_id' => 'key', + 'entry_id' => 'key', + ]) + ->execute() + ->success(); } public function dropPageTable() { - return Symphony::Database()->query("DROP TABLE IF EXISTS `tbl_cachelite_references`"); + return Symphony::Database() + ->drop('tbl_cachelite_references') + ->ifExists() + ->execute() + ->success(); } public function dropInvalidTable() { - return Symphony::Database()->query("DROP TABLE IF EXISTS `tbl_cachelite_invalid`"); + return Symphony::Database() + ->drop('tbl_cachelite_invalid') + ->ifExists() + ->execute() + ->success(); } public function optimizePageTable() { - return Symphony::Database()->query("OPTIMIZE TABLE `tbl_cachelite_references`"); + return Symphony::Database() + ->optimize('tbl_cachelite_references') + ->execute() + ->success(); } public function optimizeInvalidTable() { - return Symphony::Database()->query("OPTIMIZE TABLE `tbl_cachelite_invalid`"); + return Symphony::Database() + ->optimize('tbl_cachelite_invalid') + ->execute() + ->success(); } /*------------------------------------------------------------------------- diff --git a/extension.meta.xml b/extension.meta.xml index 09ffc73..f84d8d7 100644 --- a/extension.meta.xml +++ b/extension.meta.xml @@ -16,6 +16,9 @@ + + - Update for Symphony 4.x + - Fix crash on deleting entries @@ -108,4 +111,4 @@ - Added support for flushing the cache based on entry/section I - \ No newline at end of file + diff --git a/lib/class.cachelite.php b/lib/class.cachelite.php index 58890ee..c7f3ae9 100644 --- a/lib/class.cachelite.php +++ b/lib/class.cachelite.php @@ -79,7 +79,7 @@ class Cache_Lite * @var string $_file */ var $_file; - + /** * File name (without path) * @@ -128,7 +128,7 @@ class Cache_Lite * @var int $_pearErrorMode */ var $_pearErrorMode = CACHE_LITE_ERROR_RETURN; - + /** * Current cache id * @@ -146,7 +146,7 @@ class Cache_Lite /** * Enable / Disable "Memory Caching" * - * NB : There is no lifetime for memory caching ! + * NB : There is no lifetime for memory caching ! * * @var boolean $_memoryCaching */ @@ -180,7 +180,7 @@ class Cache_Lite * @var int $memoryCachingLimit */ var $_memoryCachingLimit = 1000; - + /** * File Name protection * @@ -192,17 +192,17 @@ class Cache_Lite * @var boolean $fileNameProtection */ var $_fileNameProtection = true; - + /** * Enable / disable automatic serialization * * it can be used to save directly datas which aren't strings - * (but it's slower) + * (but it's slower) * * @var boolean $_serialize */ var $_automaticSerialization = false; - + /** * Disable / Tune the automatic cleaning process * @@ -215,39 +215,39 @@ class Cache_Lite * @var int $_automaticCleaning */ var $_automaticCleaningFactor = 0; - + /** * Nested directory level * - * Set the hashed directory structure level. 0 means "no hashed directory - * structure", 1 means "one level of directory", 2 means "two levels"... - * This option can speed up Cache_Lite only when you have many thousands of - * cache file. Only specific benchs can help you to choose the perfect value + * Set the hashed directory structure level. 0 means "no hashed directory + * structure", 1 means "one level of directory", 2 means "two levels"... + * This option can speed up Cache_Lite only when you have many thousands of + * cache file. Only specific benchs can help you to choose the perfect value * for you. Maybe, 1 or 2 is a good start. * * @var int $_hashedDirectoryLevel */ var $_hashedDirectoryLevel = 0; - + /** * Umask for hashed directory structure * * @var int $_hashedDirectoryUmask */ var $_hashedDirectoryUmask = 0700; - + /** * API break for error handling in CACHE_LITE_ERROR_RETURN mode - * + * * In CACHE_LITE_ERROR_RETURN mode, error handling was not good because * for example save() method always returned a boolean (a PEAR_Error object * would be better in CACHE_LITE_ERROR_RETURN mode). To correct this without * breaking the API, this option (false by default) can change this handling. - * + * * @var boolean */ var $_errorHandlingAPIBreak = false; - + // --- Public methods --- /** @@ -273,19 +273,19 @@ class Cache_Lite * 'hashedDirectoryUmask' => umask for hashed directory structure (int), * 'errorHandlingAPIBreak' => API break for better error handling ? (boolean) * ); - * - * If sys_get_temp_dir() is available and the - * 'cacheDir' option is not provided in the - * constructor options array its output is used + * + * If sys_get_temp_dir() is available and the + * 'cacheDir' option is not provided in the + * constructor options array its output is used * to determine the suitable temporary directory. - * + * * @see http://de.php.net/sys_get_temp_dir * @see http://pear.php.net/bugs/bug.php?id=18328 * * @param array $options options * @access public */ - function Cache_Lite($options = array(NULL)) + function Cache_Lite($options = array(null)) { foreach($options as $key => $value) { $this->setOption($key, $value); @@ -294,7 +294,7 @@ function Cache_Lite($options = array(NULL)) $this->setOption('cacheDir', sys_get_temp_dir() . DIRECTORY_SEPARATOR); } } - + /** * Generic way to set a Cache_Lite option * @@ -304,7 +304,7 @@ function Cache_Lite($options = array(NULL)) * @var mixed $value value of the option * @access public */ - function setOption($name, $value) + function setOption($name, $value) { $availableOptions = array('errorHandlingAPIBreak', 'hashedDirectoryUmask', 'hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode'); if (in_array($name, $availableOptions)) { @@ -312,7 +312,7 @@ function setOption($name, $value) $this->$property = $value; } } - + /** * Test if a cache is available and (if yes) return it * @@ -340,7 +340,7 @@ function get($id, $group = 'default', $doNotTestCacheValidity = false) } if ($this->_onlyMemoryCaching) { return false; - } + } } if (($doNotTestCacheValidity) || (is_null($this->_refreshTime))) { if (file_exists($this->_file)) { @@ -361,7 +361,7 @@ function get($id, $group = 'default', $doNotTestCacheValidity = false) } return false; } - + /** * Save some data in a cache file * @@ -371,7 +371,7 @@ function get($id, $group = 'default', $doNotTestCacheValidity = false) * @return boolean true if no problem (else : false or a PEAR_Error object) * @access public */ - function save($data, $id = NULL, $group = 'default') + function save($data, $id = null, $group = 'default') { if ($this->_caching) { if ($this->_automaticSerialization) { @@ -398,13 +398,13 @@ function save($data, $id = NULL, $group = 'default') // if $res if false, we need to invalidate the cache @touch($this->_file, time() - 2*abs($this->_lifeTime)); return false; - } + } } else { $res = $this->_write($data); } if (is_object($res)) { - // $res is a PEAR_Error object - if (!($this->_errorHandlingAPIBreak)) { + // $res is a PEAR_Error object + if (!($this->_errorHandlingAPIBreak)) { return false; // we return false (old API) } } @@ -447,7 +447,7 @@ function remove($id, $group = 'default', $checkbeforeunlink = false) * else only cache files of the specified group will be destroyed * * @param string $group name of the cache group - * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup', + * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup', * 'callback_myFunction' * @return boolean true if no problem * @access public @@ -456,12 +456,12 @@ function clean($group = false, $mode = 'ingroup') { return $this->_cleanDir($this->_cacheDir, $group, $mode); } - + /** * Set to debug mode * * When an error is found, the script will stop and the message will be displayed - * (in debug mode only). + * (in debug mode only). * * @access public */ @@ -530,7 +530,7 @@ function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity } } } - + /** * Return the cache last modification time * @@ -538,11 +538,11 @@ function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity * * @return int last modification time */ - function lastModified() + function lastModified() { return @filemtime($this->_file); } - + /** * Trigger a PEAR error * @@ -559,27 +559,27 @@ function raiseError($msg, $code) include_once('PEAR.php'); return PEAR::raiseError($msg, $code, $this->_pearErrorMode); } - + /** * Extend the life of a valid cache file - * + * * see http://pear.php.net/bugs/bug.php?id=6681 - * + * * @access public */ function extendLife() { @touch($this->_file); } - + // --- Private methods --- - + /** * Compute & set the refresh time * * @access private */ - function _setRefreshTime() + function _setRefreshTime() { if (is_null($this->_lifeTime)) { $this->_refreshTime = null; @@ -587,10 +587,10 @@ function _setRefreshTime() $this->_refreshTime = time() - $this->_lifeTime; } } - + /** * Remove a file - * + * * @param string $file complete file path and name * @return boolean true if no problem * @access private @@ -600,7 +600,7 @@ function _unlink($file) if (!@unlink($file)) { return $this->raiseError('Cache_Lite : Unable to remove cache !', -3); } - return true; + return true; } /** @@ -676,7 +676,7 @@ function _cleanDir($dir, $group = false, $mode = 'ingroup') } return $result; } - + /** * Add some date in the memory caching array * @@ -703,7 +703,7 @@ function _memoryCacheAdd($data) */ function _setFileName($id, $group) { - + if ($this->_fileNameProtection) { $suffix = 'cache_'.md5($group).'_'.md5($id); } else { @@ -719,7 +719,7 @@ function _setFileName($id, $group) $this->_fileName = $suffix; $this->_file = $root.$suffix; } - + /** * Read the cache file and return the content * @@ -740,7 +740,7 @@ function _read() if ($this->_readControl) { $hashControl = @fread($fp, 32); $length = $length - 32; - } + } if ($length) { $data = @fread($fp, $length); } else { @@ -755,7 +755,7 @@ function _read() $hashData = $this->_hash($data, $this->_readControlType); if ($hashData != $hashControl) { if (!(is_null($this->_lifeTime))) { - @touch($this->_file, time() - 2*abs($this->_lifeTime)); + @touch($this->_file, time() - 2*abs($this->_lifeTime)); } else { @unlink($this->_file); } @@ -764,9 +764,9 @@ function _read() } return $data; } - return $this->raiseError('Cache_Lite : Unable to read cache !', -2); + return $this->raiseError('Cache_Lite : Unable to read cache !', -2); } - + /** * Write the given data in the cache file * @@ -806,7 +806,7 @@ function _write($data) } return $this->raiseError('Cache_Lite : Unable to write cache file : '.$this->_file, -1); } - + /** * Write the given data in the cache file and control it just after to avoir corrupted cache entries * @@ -825,11 +825,11 @@ function _writeAndControl($data) return $dataRead; # We return the PEAR_Error object } if ((is_bool($dataRead)) && (!$dataRead)) { - return false; + return false; } return ($dataRead==$data); } - + /** * Make a control key with the string containing datas * @@ -851,5 +851,5 @@ function _hash($data, $controlType) return $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5); } } - + }