diff --git a/ChangeLog b/ChangeLog index afaad41b5695d869cb188a623efa441b431d0dd1..a49931ceb1b2653533f505aaeb4dbd8fd4add85d 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 2010-08-10 Christian Kuhn <lolli@schwarzbu.ch> + * Added feature #15141: [Caching framework] Add compress data options to DbBackend * Fixed bug #15383: [Unit tests] Add tests for t3lib_div::validEmail * Fixed bug #15382: [Unit tests] Streamline and refactor t3lib_divTest diff --git a/t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php b/t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php index 4858ead1ca9aaa5161bce6db805df72cc9033727..fec585932ddd06131241941b5a9f9245f6421c18 100644 --- a/t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php +++ b/t3lib/cache/backend/class.t3lib_cache_backend_dbbackend.php @@ -36,6 +36,16 @@ class t3lib_cache_backend_DbBackend extends t3lib_cache_backend_AbstractBackend protected $cacheTable; protected $tagsTable; + /** + * @var boolean Indicates wether data is compressed or not (requires php zlib) + */ + protected $compression = FALSE; + + /** + * @var integer -1 to 9, indicates zlib compression level: -1 = default level 6, 0 = no compression, 9 maximum compression + */ + protected $compressionLevel = -1; + protected $identifierField; protected $creationField; protected $lifetimeField; @@ -116,6 +126,10 @@ class t3lib_cache_backend_DbBackend extends t3lib_cache_backend_AbstractBackend $this->remove($entryIdentifier); + if ($this->compression) { + $data = gzcompress($data, $this->compressionLevel); + } + $GLOBALS['TYPO3_DB']->exec_INSERTquery( $this->cacheTable, array( @@ -168,6 +182,10 @@ class t3lib_cache_backend_DbBackend extends t3lib_cache_backend_AbstractBackend $cacheEntry = $cacheEntries[0]['content']; } + if ($this->compression && strlen($cacheEntry)) { + $cacheEntry = gzuncompress($cacheEntry); + } + return $cacheEntry; } @@ -446,6 +464,28 @@ class t3lib_cache_backend_DbBackend extends t3lib_cache_backend_AbstractBackend return $this->tagsTable; } + /** + * Enable data compression + * + * @param boolean TRUE to enable compression + */ + public function setCompression($compression) { + $this->compression = $compression; + } + + /** + * Set data compression level. + * If compression is enabled and this is not set, + * gzcompress default level will be used + * + * @param integer -1 to 9: Compression level + */ + public function setCompressionLevel($compressionLevel) { + if ($compressionLevel >= -1 && $compressionLevel <= 9) { + $this->compressionLevel = $compressionLevel; + } + } + /** * Gets the query to be used for selecting entries by a tag. The asterisk ("*") * is allowed as a wildcard at the beginning and the end of a tag. diff --git a/t3lib/stddb/tables.sql b/t3lib/stddb/tables.sql index 1374a2b8784ef583156ce386b14ef226a951e523..46dccb4f48eec6a6fea5b5d891eb0539a58029ef 100644 --- a/t3lib/stddb/tables.sql +++ b/t3lib/stddb/tables.sql @@ -140,7 +140,7 @@ CREATE TABLE cachingframework_cache_hash ( id int(11) unsigned NOT NULL auto_increment, identifier varchar(128) DEFAULT '' NOT NULL, crdate int(11) unsigned DEFAULT '0' NOT NULL, - content mediumtext, + content mediumblob, lifetime int(11) unsigned DEFAULT '0' NOT NULL, PRIMARY KEY (id), KEY cache_id (identifier) diff --git a/tests/t3lib/cache/backend/t3lib_cache_backend_dbbackendTest.php b/tests/t3lib/cache/backend/t3lib_cache_backend_dbbackendTest.php index 9670f9637a09bf7a9578f9742432f0fa70351322..0f55fae2a88d31f6f04216e1b8184e013b2aaa05 100644 --- a/tests/t3lib/cache/backend/t3lib_cache_backend_dbbackendTest.php +++ b/tests/t3lib/cache/backend/t3lib_cache_backend_dbbackendTest.php @@ -43,20 +43,32 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { protected $testingTagsTable; /** - * Sets up this testcase + * Sets up the backend used for testing * * @return void * @author Ingo Renner <ingo@typo3.org> + * @author Christian Kuhn <lolli@schwarzbu.ch> */ - public function setUp() { - $this->testingCacheTable = 'test_cache_dbbackend'; - $this->testingTagsTable = 'test_cache_dbbackend_tags'; + public function setUpBackend(array $backendOptions = array()) { + $defaultTestingCacheTable = 'test_cache_dbbackend'; + $defaultTestingTagsTable = 'test_cache_dbbackend_tags'; + + $backendOptions = array_merge( + array( + 'cacheTable' => $defaultTestingCacheTable, + 'tagsTable' => $defaultTestingTagsTable, + ), + $backendOptions + ); + + $this->testingCacheTable = $backendOptions['cacheTable']; + $this->testingTagsTable = $backendOptions['tagsTable']; $GLOBALS['TYPO3_DB']->sql_query('CREATE TABLE ' . $this->testingCacheTable . ' ( id int(11) unsigned NOT NULL auto_increment, identifier varchar(128) DEFAULT \'\' NOT NULL, crdate int(11) unsigned DEFAULT \'0\' NOT NULL, - content mediumtext, + content mediumblob, lifetime int(11) unsigned DEFAULT \'0\' NOT NULL, PRIMARY KEY (id), KEY cache_id (identifier) @@ -75,10 +87,20 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { $this->backend = t3lib_div::makeInstance( 't3lib_cache_backend_DbBackend', - array( - 'cacheTable' => $this->testingCacheTable, - 'tagsTable' => $this->testingTagsTable, - ) + $backendOptions + ); + } + + /** + * @author Ingo Renner <ingo@typo3.org> + */ + public function tearDown() { + $GLOBALS['TYPO3_DB']->sql_query( + 'DROP TABLE ' . $this->testingCacheTable . ';' + ); + + $GLOBALS['TYPO3_DB']->sql_query( + 'DROP TABLE ' . $this->testingTagsTable . ';' ); } @@ -97,6 +119,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function getCacheTableReturnsThePreviouslySetTable() { + $this->setUpBackend(); $this->backend->setCacheTable($this->testingCacheTable); $this->assertEquals($this->testingCacheTable, $this->backend->getCacheTable(), 'getCacheTable() did not return the expected value.'); } @@ -107,6 +130,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function setThrowsExceptionIfDataIsNotAString() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -127,6 +151,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function setReallySavesToTheSpecifiedTable() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -158,6 +183,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function setRemovesAnAlreadyExistingCacheEntryForTheSameIdentifier() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -189,6 +215,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function setReallySavesSpecifiedTags() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -219,11 +246,71 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { $this->assertTrue(in_array('UnitTestTag%tag2', $tags), 'Tag UnitTestTag%tag2 does not exist.'); } + /** + * @test + * @author Christian Kuhn <lolli@schwarzbu.ch> + */ + public function setSavesCompressedDataWithEnabledCompression() { + $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE); + $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('UnitTestCache')); + $this->setUpBackend( + array( + 'compression' => TRUE, + ) + ); + $this->backend->setCache($mockCache); + + $data = 'some data ' . microtime(); + + $entryIdentifier = 'BackendDbTest'; + + $this->backend->set($entryIdentifier, $data); + + $entry = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( + 'content', + $this->testingCacheTable, + 'identifier = \'' . $entryIdentifier . '\'' + ); + + $this->assertEquals($data, @gzuncompress($entry[0]['content']), 'Original and compressed data don\'t match'); + } + + /** + * @test + * @author Christian Kuhn <lolli@schwarzbu.ch> + */ + public function setSavesPlaintextDataWithEnabledCompressionAndCompressionLevel0() { + $mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE); + $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('UnitTestCache')); + $this->setUpBackend( + array( + 'compression' => TRUE, + 'compressionLevel' => 0, + ) + ); + $this->backend->setCache($mockCache); + + $data = 'some data ' . microtime(); + + $entryIdentifier = 'BackendDbTest'; + + $this->backend->set($entryIdentifier, $data); + + $entry = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( + 'content', + $this->testingCacheTable, + 'identifier = \'' . $entryIdentifier . '\'' + ); + + $this->assertGreaterThan(0, substr_count($entry[0]['content'], $data), 'Plaintext data not found'); + } + /** * @test * @author Ingo Renner <ingo@typo3.org> */ public function getReturnsContentOfTheCorrectCacheEntry() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -250,6 +337,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function hasReturnsTheCorrectResult() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -272,6 +360,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function removeReallyRemovesACacheEntry() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -309,6 +398,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function collectGarbageReallyRemovesAnExpiredCacheEntry() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -348,6 +438,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function collectGarbageReallyRemovesAllExpiredCacheEntries() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -390,6 +481,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -417,6 +509,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function flushRemovesAllCacheEntries() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -447,6 +540,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function flushByTagRemovesCacheEntriesWithSpecifiedTag() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -481,6 +575,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function hasReturnsTheCorrectResultForEntryWithExceededLifetime() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -509,6 +604,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function getReturnsFalseForEntryWithExceededLifetime() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -538,6 +634,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function findIdentifiersByTagReturnsEmptyArrayForEntryWithExceededLifetime() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -561,6 +658,7 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { * @author Ingo Renner <ingo@typo3.org> */ public function setWithUnlimitedLifetimeWritesCorrectEntry() { + $this->setUpBackend(); $cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'), array(), @@ -585,21 +683,6 @@ class t3lib_cache_backend_DbBackendTest extends tx_phpunit_testcase { $retrievedData = $entriesFound[0]['content']; $this->assertEquals($data, $retrievedData, 'The original and the retrieved data don\'t match.'); } - - - /** - * @author Ingo Renner <ingo@typo3.org> - */ - public function tearDown() { - $GLOBALS['TYPO3_DB']->sql_query( - 'DROP TABLE ' . $this->testingCacheTable . ';' - ); - - $GLOBALS['TYPO3_DB']->sql_query( - 'DROP TABLE ' . $this->testingTagsTable . ';' - ); - } - } ?> \ No newline at end of file diff --git a/typo3/sysext/cms/ext_tables.sql b/typo3/sysext/cms/ext_tables.sql index f615469c52d8dddec21b607b930eb682483bf3c3..79230a1bc875fa4f2b6b04799940a4e5d1d9cfc6 100755 --- a/typo3/sysext/cms/ext_tables.sql +++ b/typo3/sysext/cms/ext_tables.sql @@ -43,7 +43,7 @@ CREATE TABLE cachingframework_cache_pages ( id int(11) unsigned NOT NULL auto_increment, identifier varchar(128) DEFAULT '' NOT NULL, crdate int(11) unsigned DEFAULT '0' NOT NULL, - content mediumtext, + content mediumblob, lifetime int(11) unsigned DEFAULT '0' NOT NULL, PRIMARY KEY (id), KEY cache_id (identifier) @@ -70,7 +70,7 @@ CREATE TABLE cachingframework_cache_pagesection ( id int(11) unsigned NOT NULL auto_increment, identifier varchar(128) DEFAULT '' NOT NULL, crdate int(11) unsigned DEFAULT '0' NOT NULL, - content mediumtext, + content mediumblob, lifetime int(11) unsigned DEFAULT '0' NOT NULL, PRIMARY KEY (id), KEY cache_id (identifier)