From 682c16fb4c7d55acf4e245cab2b7c64197f4ff17 Mon Sep 17 00:00:00 2001 From: Benjamin Mack <benni@typo3.org> Date: Wed, 31 Dec 2014 01:17:16 +0100 Subject: [PATCH] [TASK] Cache cache_imagesizes using the Caching Framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streamline the code by moving the functionality to cache image sizes processed by GraphicalFunctions (local-only so far) from the database table cache_imagesizes to the Caching Framework. The following changes are done: * use sha1 instead of md5 * use Caching Framework instead of hardcoded DB table * store only necessary data in the cache The new Caching Framework configuration is stored in a new group called "lowlevel" which is only emptied when pressing the clear cache button in the install tool. The former table cache_imagesizes has been filled automatically and never been cleaned except manually in the Install Tool area "Cleanup". This means there could be a lot of leftover entries. Now the cache is cleared when using the common clear caches button in the install tool. Resolves: #28484 Releases: master Change-Id: Ia68410eb382163e90654718aeb17165dc48e40cc Reviewed-on: http://review.typo3.org/35686 Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Stephan Großberndt <stephan@grossberndt.de> Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org> Tested-by: Helmut Hummel <helmut.hummel@typo3.org> --- .../Classes/Imaging/GraphicalFunctions.php | 108 ++++++++++-------- .../Configuration/DefaultConfiguration.php | 8 ++ typo3/sysext/core/ext_tables.sql | 13 --- .../Controller/Action/Tool/CleanUp.php | 4 - 4 files changed, 69 insertions(+), 64 deletions(-) diff --git a/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php b/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php index 81b0f13cf384..b22cf5583522 100644 --- a/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php +++ b/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php @@ -227,7 +227,7 @@ class GraphicalFunctions { public $absPrefix = ''; /** - * ImageMagick scaling command; "-geometry" eller "-sample". Used in makeText() and imageMagickConvert() + * ImageMagick scaling command; "-geometry" or "-sample". Used in makeText() and imageMagickConvert() * * @var string */ @@ -2234,7 +2234,7 @@ class GraphicalFunctions { if (file_exists($output)) { $info[3] = $output; $info[2] = $newExt; - // params could realisticly change some imagedata! + // params might change some image data! if ($params) { $info = $this->getImageDimensions($info[3]); } @@ -2261,7 +2261,7 @@ class GraphicalFunctions { if ($returnArr = $this->getCachedImageDimensions($imageFile)) { return $returnArr; } else { - if ($temp = @getImageSize($imageFile)) { + if ($temp = @getimagesize($imageFile)) { $returnArr = array($temp[0], $temp[1], strtolower($reg[0]), $imageFile); } else { $returnArr = $this->imageMagickIdentify($imageFile); @@ -2276,61 +2276,75 @@ class GraphicalFunctions { } /** - * Cache the result of the getImageDimensions function into the database. Does not check if the - * file exists! + * Caches the result of the getImageDimensions function into the database. Does not check if the file exists. * * @param array $identifyResult Result of the getImageDimensions function - * @return bool TRUE if operation was successful + * + * @return bool always TRUE */ - public function cacheImageDimensions($identifyResult) { - // Create md5 hash of filemtime and filesize - $fileStatus = stat($identifyResult[3]); - $md5Hash = md5($fileStatus['mtime'] . $fileStatus['size']); - $result = FALSE; - if ($md5Hash) { - $fieldArray = array( - 'md5hash' => $md5Hash, - 'md5filename' => md5($identifyResult[3]), - 'tstamp' => $GLOBALS['EXEC_TIME'], - 'filename' => $identifyResult[3], - 'imagewidth' => $identifyResult[0], - 'imageheight' => $identifyResult[1] + public function cacheImageDimensions(array $identifyResult) { + $filePath = $identifyResult[3]; + $statusHash = $this->generateCacheKeyForImageFile($filePath); + + /** @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend $cache */ + $cache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_imagesizes'); + $imageDimensions = array( + 'hash' => $statusHash, + 'imagewidth' => $identifyResult[0], + 'imageheight' => $identifyResult[1], + ); + $cache->set($statusHash, $imageDimensions); + + return TRUE; + } + + /** + * Fetches the cached image dimensions from the cache. Does not check if the image file exists. + * + * @param string $filePath the image file path + * + * @return array|bool an array where [0]/[1] is w/h, [2] is extension and [3] is the file name, + * or FALSE for a cache miss + */ + public function getCachedImageDimensions($filePath) { + $statusHash = $this->generateCacheKeyForImageFile($filePath); + /** @var \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend $cache */ + $cache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('cache_imagesizes'); + $cachedImageDimensions = $cache->get($statusHash); + if (!isset($cachedImageDimensions['hash'])) { + return FALSE; + } + + if ($cachedImageDimensions['hash'] !== $statusHash) { + // The file has changed. Delete the cache entry. + $cache->remove($filePath); + $result = FALSE; + } else { + preg_match('/([^\\.]*)$/', $filePath, $imageExtension); + $result = array( + (int)$cachedImageDimensions['imagewidth'], + (int)$cachedImageDimensions['imageheight'], + strtolower($imageExtension[0]), + $filePath ); - $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_imagesizes', $fieldArray); - if (!($err = $GLOBALS['TYPO3_DB']->sql_error())) { - $result = TRUE; - } } + return $result; } /** - * Fetch the cached imageDimensions from the MySQL database. Does not check if the image file exists! + * Creates the key for the image dimensions cache for an image file. * - * @param string $imageFile The image filepath - * @return array Returns an array where [0]/[1] is w/h, [2] is extension and [3] is the filename. + * This method does not check if the image file actually exists. + * + * @param string $filePath + * + * @return string the hash key (an SHA1 hash), will not be empty */ - public function getCachedImageDimensions($imageFile) { - // Create md5 hash of filemtime and filesize - $fileStatus = stat($imageFile); - $md5Hash = md5($fileStatus['mtime'] . $fileStatus['size']); - $cachedImageDimensions = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('md5hash, md5filename, imagewidth, imageheight', 'cache_imagesizes', 'md5filename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr(md5($imageFile), 'cache_imagesizes')); - $result = FALSE; - if (is_array($cachedImageDimensions)) { - if ($cachedImageDimensions['md5hash'] != $md5Hash) { - // File has changed, delete the row - $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_imagesizes', 'md5filename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($cachedImageDimensions['md5filename'], 'cache_imagesizes')); - } else { - preg_match('/([^\\.]*)$/', $imageFile, $imageExtension); - $result = array( - (int)$cachedImageDimensions['imagewidth'], - (int)$cachedImageDimensions['imageheight'], - strtolower($imageExtension[0]), - $imageFile - ); - } - } - return $result; + protected function generateCacheKeyForImageFile($filePath) { + $fileStatus = stat($filePath); + + return sha1($fileStatus['mtime'] . $fileStatus['size']); } /** diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php index 746d5e28c78b..11973abe8f2a 100644 --- a/typo3/sysext/core/Configuration/DefaultConfiguration.php +++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php @@ -175,6 +175,14 @@ return array( 'options' => array(), 'groups' => array('pages', 'all') ), + 'cache_imagesizes' => array( + 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, + 'backend' => \TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend::class, + 'options' => array( + 'defaultLifetime' => 0, + ), + 'groups' => array('lowlevel'), + ), 'l10n' => array( 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, 'backend' => \TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend::class, diff --git a/typo3/sysext/core/ext_tables.sql b/typo3/sysext/core/ext_tables.sql index d5538e7d1f61..f05f5e23e5c1 100644 --- a/typo3/sysext/core/ext_tables.sql +++ b/typo3/sysext/core/ext_tables.sql @@ -90,19 +90,6 @@ CREATE TABLE be_users ( KEY username (username) ); -# -# Table structure for table 'cache_imagesizes' -# -CREATE TABLE cache_imagesizes ( - md5hash varchar(32) DEFAULT '' NOT NULL, - md5filename varchar(32) DEFAULT '' NOT NULL, - tstamp int(11) DEFAULT '0' NOT NULL, - filename varchar(255) DEFAULT '' NOT NULL, - imagewidth mediumint(11) unsigned DEFAULT '0' NOT NULL, - imageheight mediumint(11) unsigned DEFAULT '0' NOT NULL, - PRIMARY KEY (md5filename) -) ENGINE=InnoDB; - # # Table structure for table 'pages' # diff --git a/typo3/sysext/install/Classes/Controller/Action/Tool/CleanUp.php b/typo3/sysext/install/Classes/Controller/Action/Tool/CleanUp.php index 64c4a4765bea..83959f69e554 100644 --- a/typo3/sysext/install/Classes/Controller/Action/Tool/CleanUp.php +++ b/typo3/sysext/install/Classes/Controller/Action/Tool/CleanUp.php @@ -62,10 +62,6 @@ class CleanUp extends Action\AbstractAction { 'name' => 'be_sessions', 'description' => 'Backend user sessions' ), - array( - 'name' => 'cache_imagesizes', - 'description' => 'Cached image sizes', - ), array( 'name' => 'cache_md5params', 'description' => 'Frontend redirects', -- GitLab