Project

General

Profile

Feature #22836 » 14655_02.diff

Administrator Admin, 2010-06-09 01:28

View differences:

tests/t3lib/cache/backend/t3lib_cache_backend_pdobackendtestcase.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2010 Christian Kuhn <lolli@schwarzbu.ch>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* Testcase for the PDO cache backend
*
* @author Christian Kuhn <lolli@schwarzbu.ch>
* @package TYPO3
* @subpackage tests
* @version $Id$
*/
class t3lib_cache_backend_PdoBackendTestCase extends tx_phpunit_testcase {
/**
* Backup of global variable EXEC_TIME
*
* @var array
*/
protected $backupGlobalVariables;
/**
* @var string
*/
protected $fixtureFolder;
/**
* @var string
*/
protected $fixtureDB;
/**
* Sets up this testcase
*
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function setUp() {
if (!extension_loaded('pdo_sqlite')) {
$this->markTestSkipped('pdo_sqlite extension was not available');
}
$this->backupGlobalVariables = array(
'EXEC_TIME' => $GLOBALS['EXEC_TIME'],
);
}
/**
* @test
* @author Karsten Dambekalns <karsten@typo3.org>
* @expectedException t3lib_cache_Exception
*/
public function setThrowsExceptionIfNoFrontEndHasBeenSet() {
$backend = t3lib_div::makeInstance('t3lib_cache_backend_PdoBackend');
$data = 'Some data';
$identifier = 'MyIdentifier';
$backend->set($identifier, $data);
}
/**
* @test
* @author Christian Jul Jensen <julle@typo3.org>
*/
public function itIsPossibleToSetAndCheckExistenceInCache() {
$backend = $this->setUpBackend();
$data = 'Some data';
$identifier = 'MyIdentifier';
$backend->set($identifier, $data);
$this->assertTrue($backend->has($identifier));
}
/**
* @test
* @author Christian Jul Jensen <julle@typo3.org>
*/
public function itIsPossibleToSetAndGetEntry() {
$backend = $this->setUpBackend();
$data = 'Some data';
$identifier = 'MyIdentifier';
$backend->set($identifier, $data);
$fetchedData = $backend->get($identifier);
$this->assertEquals($data, $fetchedData);
}
/**
* @test
* @author Christian Jul Jensen <julle@typo3.org>
*/
public function itIsPossibleToRemoveEntryFromCache() {
$backend = $this->setUpBackend();
$data = 'Some data';
$identifier = 'MyIdentifier';
$backend->set($identifier, $data);
$backend->remove($identifier);
$this->assertFalse($backend->has($identifier));
}
/**
* @test
* @author Christian Jul Jensen <julle@typo3.org>
*/
public function itIsPossibleToOverwriteAnEntryInTheCache() {
$backend = $this->setUpBackend();
$data = 'Some data';
$identifier = 'MyIdentifier';
$backend->set($identifier, $data);
$otherData = 'some other data';
$backend->set($identifier, $otherData);
$fetchedData = $backend->get($identifier);
$this->assertEquals($otherData, $fetchedData);
}
/**
* @test
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function findIdentifiersByTagFindsSetEntries() {
$backend = $this->setUpBackend();
$data = 'Some data';
$entryIdentifier = 'MyIdentifier';
$backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
$retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
$this->assertEquals($entryIdentifier, $retrieved[0]);
$retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
$this->assertEquals($entryIdentifier, $retrieved[0]);
}
/**
* @test
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function findIdentifiersByTagsFindsSetEntries() {
$backend = $this->setUpBackend();
$data = 'Some data';
$entryIdentifier = 'MyIdentifier';
$backend->set($entryIdentifier . 'A', $data, array('UnitTestTag%tag1'));
$backend->set($entryIdentifier . 'B', $data, array('UnitTestTag%tag2'));
$backend->set($entryIdentifier . 'C', $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
$backend->set($entryIdentifier . 'D', $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2', 'UnitTestTag%tag3'));
$retrieved = $backend->findIdentifiersByTags(array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
$this->assertFalse(in_array($entryIdentifier . 'A', $retrieved));
$this->assertFalse(in_array($entryIdentifier . 'B', $retrieved));
$this->assertTrue(in_array($entryIdentifier . 'C', $retrieved));
$this->assertTrue(in_array($entryIdentifier . 'D', $retrieved));
}
/**
* @test
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function setRemovesTagsFromPreviousSet() {
$backend = $this->setUpBackend();
$data = 'Some data';
$entryIdentifier = 'MyIdentifier';
$backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
$backend->set($entryIdentifier, $data, array('UnitTestTag%tag3'));
$retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
$this->assertEquals(array(), $retrieved);
}
/**
* @test
* @author Christian Jul Jensen <julle@typo3.org>
*/
public function hasReturnsFalseIfTheEntryDoesntExist() {
$backend = $this->setUpBackend();
$identifier = 'NonExistingIdentifier';
$this->assertFalse($backend->has($identifier));
}
/**
* @test
* @author Christian Jul Jensen <julle@typo3.org>
*/
public function removeReturnsFalseIfTheEntryDoesntExist() {
$backend = $this->setUpBackend();
$identifier = 'NonExistingIdentifier';
$this->assertFalse($backend->remove($identifier));
}
/**
* @test
* @author Robert Lemke <robert@typo3.org>
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function flushByTagRemovesCacheEntriesWithSpecifiedTag() {
$backend = $this->setUpBackend();
$data = 'some data' . microtime();
$backend->set('PdoBackendTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
$backend->set('PdoBackendTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
$backend->set('PdoBackendTest3', $data, array('UnitTestTag%test'));
$backend->flushByTag('UnitTestTag%special');
$this->assertTrue($backend->has('PdoBackendTest1'), 'PdoBackendTest1');
$this->assertFalse($backend->has('PdoBackendTest2'), 'PdoBackendTest2');
$this->assertTrue($backend->has('PdoBackendTest3'), 'PdoBackendTest3');
}
/**
* @test
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function flushByTagsRemovesCacheEntriesWithSpecifiedTags() {
$backend = $this->setUpBackend();
$data = 'some data' . microtime();
$backend->set('PdoBackendTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
$backend->set('PdoBackendTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special1'));
$backend->set('PdoBackendTest3', $data, array('UnitTestTag%test', 'UnitTestTag%special2'));
$backend->set('PdoBackendTest4', $data, array('UnitTestTag%test', 'UnitTestTag%special2'));
$backend->flushByTags(array('UnitTestTag%special1','UnitTestTag%special2'));
$this->assertTrue($backend->has('PdoBackendTest1'));
$this->assertFalse($backend->has('PdoBackendTest2'));
$this->assertFalse($backend->has('PdoBackendTest3'));
$this->assertFalse($backend->has('PdoBackendTest4'));
}
/**
* @test
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function flushRemovesAllCacheEntries() {
$backend = $this->setUpBackend();
$data = 'some data' . microtime();
$backend->set('PdoBackendTest1', $data);
$backend->set('PdoBackendTest2', $data);
$backend->set('PdoBackendTest3', $data);
$backend->flush();
$this->assertFalse($backend->has('PdoBackendTest1'), 'PdoBackendTest1');
$this->assertFalse($backend->has('PdoBackendTest2'), 'PdoBackendTest2');
$this->assertFalse($backend->has('PdoBackendTest3'), 'PdoBackendTest3');
}
/**
* @test
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function flushRemovesOnlyOwnEntries() {
$thisCache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
$thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
$thisBackend = $this->setUpBackend();
$thisBackend->setCache($thisCache);
$thatCache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
$thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
$thatBackend = $this->setUpBackend();
$thatBackend->setCache($thatCache);
$thisBackend->set('thisEntry', 'Hello');
$thatBackend->set('thatEntry', 'World!');
$thatBackend->flush();
$this->assertEquals('Hello', $thisBackend->get('thisEntry'));
$this->assertFalse($thatBackend->has('thatEntry'));
}
/**
* @test
* @author Ingo Renner <ingo@typo3.org>
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function collectGarbageReallyRemovesAnExpiredCacheEntry() {
$backend = $this->setUpBackend();
$data = 'some data' . microtime();
$entryIdentifier = 'BackendPDORemovalTest';
$backend->set($entryIdentifier, $data, array(), 1);
$this->assertTrue($backend->has($entryIdentifier));
$GLOBALS['EXEC_TIME'] += 2;
$backend->collectGarbage();
$this->assertFalse($backend->has($entryIdentifier));
}
/**
* @test
* @author Ingo Renner <ingo@typo3.org>
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function collectGarbageReallyRemovesAllExpiredCacheEntries() {
$backend = $this->setUpBackend();
$data = 'some data' . microtime();
$entryIdentifier = 'BackendPDORemovalTest';
$backend->set($entryIdentifier . 'A', $data, array(), NULL);
$backend->set($entryIdentifier . 'B', $data, array(), 10);
$backend->set($entryIdentifier . 'C', $data, array(), 1);
$backend->set($entryIdentifier . 'D', $data, array(), 1);
$this->assertTrue($backend->has($entryIdentifier . 'A'));
$this->assertTrue($backend->has($entryIdentifier . 'B'));
$this->assertTrue($backend->has($entryIdentifier . 'C'));
$this->assertTrue($backend->has($entryIdentifier . 'D'));
$GLOBALS['EXEC_TIME'] += 2;
$backend->collectGarbage();
$this->assertTrue($backend->has($entryIdentifier . 'A'));
$this->assertTrue($backend->has($entryIdentifier . 'B'));
$this->assertFalse($backend->has($entryIdentifier . 'C'));
$this->assertFalse($backend->has($entryIdentifier . 'D'));
}
/**
* Sets up the PDO backend used for testing
*
* @return t3lib_cache_backend_PdoBackend
* @author Karsten Dambekalns <karsten@typo3.org>
*/
protected function setUpBackend() {
$this->fixtureFolder = sys_get_temp_dir() . '/' . 'typo3pdobackendtest/';
t3lib_div::mkdir_deep(sys_get_temp_dir() . '/', 'typo3pdobackendtest/');
$this->fixtureDB = uniqid('Cache') . '.db';
$pdoHelper = t3lib_div::makeInstance('t3lib_PdoHelper', 'sqlite:' . $this->fixtureFolder . $this->fixtureDB, '', '');
$pdoHelper->importSql(PATH_t3lib . 'cache/backend/resources/ddl.sql');
$mockCache = $this->getMock('t3lib_cache_frontend_Frontend', array(), array(), '', FALSE);
$mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('TestCache'));
$backendOptions = array(
'dataSourceName' => 'sqlite:' . $this->fixtureFolder . $this->fixtureDB,
'username' => '',
'password' => '',
);
$backend = t3lib_div::makeInstance('t3lib_cache_backend_PdoBackend', $backendOptions);
$backend->setCache($mockCache);
return $backend;
}
/**
* Clean up after the tests
*
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function tearDown() {
if ($this->fixtureDB) {
t3lib_div::rmdir($this->fixtureFolder, TRUE);
}
foreach ($this->backupGlobalVariables as $key => $data) {
$GLOBALS[$key] = $data;
}
}
}
?>
t3lib/config_default.php (working copy)
't3lib_cache_backend_FileBackend' => 't3lib/cache/backend/class.t3lib_cache_backend_filebackend.php:t3lib_cache_backend_FileBackend',
't3lib_cache_backend_GlobalsBackend' => 't3lib/cache/backend/class.t3lib_cache_backend_globalsbackend.php:t3lib_cache_backend_GlobalsBackend',
't3lib_cache_backend_MemcachedBackend' => 't3lib/cache/backend/class.t3lib_cache_backend_memcachedbackend.php:t3lib_cache_backend_MemcachedBackend',
't3lib_cache_backend_PdoBackend' => 't3lib/cache/backend/class.t3lib_cache_backend_pdobackend.php:t3lib_cache_backend_PdoBackend',
't3lib_cache_backend_ApcBackend' => 't3lib/cache/backend/class.t3lib_cache_backend_apcbackend.php:t3lib_cache_backend_ApcBackend',
't3lib_cache_backend_NullBackend' => 't3lib/cache/backend/class.t3lib_cache_backend_nullbackend.php:t3lib_cache_backend_NullBackend'
),
t3lib/cache/backend/resources/ddl.sql (revision 0)
BEGIN;
CREATE TABLE "cache" (
"identifier" VARCHAR(250) NOT NULL,
"cache" VARCHAR(250) NOT NULL,
"scope" CHAR(12) NOT NULL,
"created" INTEGER UNSIGNED NOT NULL,
"lifetime" INTEGER UNSIGNED DEFAULT '0' NOT NULL,
"content" TEXT,
PRIMARY KEY ("identifier", "cache", "scope")
);
CREATE TABLE "tags" (
"identifier" VARCHAR(250) NOT NULL,
"cache" VARCHAR(250) NOT NULL,
"scope" CHAR(12) NOT NULL,
"tag" VARCHAR(250) NOT NULL
);
CREATE INDEX "identifier" ON "tags" ("identifier", "cache", "scope");
CREATE INDEX "tag" ON "tags" ("tag");
COMMIT;
t3lib/cache/backend/class.t3lib_cache_backend_pdobackend.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2010 Christian Kuhn <lolli@schwarzbu.ch>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* A PDO database cache backend
*
* @package TYPO3
* @subpackage t3lib_cache
* @api
* @scope prototype
* @author Christian Kuhn <lolli@schwarzbu.ch>
* @version $Id$
*/
class t3lib_cache_backend_PdoBackend extends t3lib_cache_backend_AbstractBackend {
/**
* @var string
*/
protected $dataSourceName;
/**
* @var string
*/
protected $username;
/**
* @var string
*/
protected $password;
/**
* Used to seperate stored data by user, SAPI, context, ...
* @var string
*/
protected $scope;
/**
* @var PDO
*/
protected $databaseHandle;
/**
* @var string
*/
protected $pdoDriver;
/**
* Constructs this backend
*
* @param mixed $options Configuration options - depends on the actual backend
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function __construct(array $options = array()) {
parent::__construct($options);
$this->connect();
}
/**
* Sets the DSN to use
*
* @param string $DSN The DSN to use for connecting to the DB
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function setDataSourceName($DSN) {
$this->dataSourceName = $DSN;
}
/**
* Sets the username to use
*
* @param string $username The username to use for connecting to the DB
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function setUsername($username) {
$this->username = $username;
}
/**
* Sets the password to use
*
* @param string $password The password to use for connecting to the DB
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function setPassword($password) {
$this->password = $password;
}
/**
* Initializes the identifier prefix when setting the cache.
*
* @param t3lib_cache_frontend_Frontend $cache
* @return void
* @author Robert Lemke <robert@typo3.org>
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function setCache(t3lib_cache_frontend_Frontend $cache) {
parent::setCache($cache);
$processUser = extension_loaded('posix') ? posix_getpwuid(posix_geteuid()) : array('name' => 'default');
$this->scope = t3lib_div::shortMD5(PATH_site . $processUser['name'], 12);
}
/**
* Saves data in the cache.
*
* @param string $entryIdentifier An identifier for this specific cache entry
* @param string $data The data to be stored
* @param array $tags Tags to associate with this cache entry
* @param integer $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited liftime.
* @return void
* @throws t3lib_cache_Exception if no cache frontend has been set.
* @throws t3lib_cache_exception_InvalidData if $data is not a string
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
throw new t3lib_cache_Exception(
'No cache frontend has been set yet via setCache().',
1259515600
);
}
if (!is_string($data)) {
throw new t3lib_cache_exception_InvalidData(
'The specified data is of type "' . gettype($data) . '" but a string is expected.',
1259515601
);
}
if ($this->has($entryIdentifier)) {
$this->remove($entryIdentifier);
}
$lifetime = ($lifetime === NULL) ? $this->defaultLifetime : $lifetime;
$statementHandle = $this->databaseHandle->prepare(
'INSERT INTO "cache" ("identifier", "scope", "cache", "created", "lifetime", "content") VALUES (?, ?, ?, ?, ?, ?)'
);
$result = $statementHandle->execute(
array($entryIdentifier, $this->scope, $this->cacheIdentifier, $GLOBALS['EXEC_TIME'], $lifetime, $data)
);
if ($result === FALSE) {
throw new t3lib_cache_Exception(
'The cache entry "' . $entryIdentifier . '" could not be written.',
1259530791
);
}
$statementHandle = $this->databaseHandle->prepare(
'INSERT INTO "tags" ("identifier", "scope", "cache", "tag") VALUES (?, ?, ?, ?)'
);
foreach ($tags as $tag) {
$result = $statementHandle->execute(
array($entryIdentifier, $this->scope, $this->cacheIdentifier, $tag)
);
if ($result === FALSE) {
throw new t3lib_cache_Exception(
'The tag "' . $tag . ' for cache entry "' . $entryIdentifier . '" could not be written.',
1259530751
);
}
}
}
/**
* Loads data from the cache.
*
* @param string $entryIdentifier An identifier which describes the cache entry to load
* @return mixed The cache entry's content as a string or FALSE if the cache entry could not be loaded
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function get($entryIdentifier) {
$statementHandle = $this->databaseHandle->prepare(
'SELECT "content" FROM "cache" WHERE "identifier"=? AND "scope"=? AND "cache"=?' . $this->getNotExpiredStatement()
);
$statementHandle->execute(
array($entryIdentifier, $this->scope, $this->cacheIdentifier)
);
return $statementHandle->fetchColumn();
}
/**
* Checks if a cache entry with the specified identifier exists.
*
* @param string $entryIdentifier An identifier specifying the cache entry
* @return boolean TRUE if such an entry exists, FALSE if not
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function has($entryIdentifier) {
$statementHandle = $this->databaseHandle->prepare(
'SELECT COUNT("identifier") FROM "cache" WHERE "identifier"=? AND "scope"=? AND "cache"=?' . $this->getNotExpiredStatement()
);
$statementHandle->execute(
array($entryIdentifier, $this->scope, $this->cacheIdentifier)
);
return ($statementHandle->fetchColumn() > 0);
}
/**
* Removes all cache entries matching the specified identifier.
* Usually this only affects one entry but if - for what reason ever -
* old entries for the identifier still exist, they are removed as well.
*
* @param string $entryIdentifier Specifies the cache entry to remove
* @return boolean TRUE if (at least) an entry could be removed or FALSE if no entry was found
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function remove($entryIdentifier) {
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "tags" WHERE "identifier"=? AND "scope"=? AND "cache"=?'
);
$statementHandle->execute(
array($entryIdentifier, $this->scope, $this->cacheIdentifier)
);
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "cache" WHERE "identifier"=? AND "scope"=? AND "cache"=?'
);
$statementHandle->execute(
array($entryIdentifier, $this->scope, $this->cacheIdentifier)
);
return ($statementHandle->rowCount() > 0);
}
/**
* Removes all cache entries of this cache.
*
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function flush() {
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "tags" WHERE "scope"=? AND "cache"=?'
);
$statementHandle->execute(
array($this->scope, $this->cacheIdentifier)
);
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "cache" WHERE "scope"=? AND "cache"=?'
);
$statementHandle->execute(
array($this->scope, $this->cacheIdentifier)
);
}
/**
* Removes all cache entries of this cache which are tagged by the specified tag.
*
* @param string $tag The tag the entries must have
* @return void
* @author Robert Lemke <robert@typo3.org>
* @api
*/
public function flushByTag($tag) {
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "cache" WHERE "scope"=? AND "cache"=? AND "identifier" IN (SELECT "identifier" FROM "tags" WHERE "scope"=? AND "cache"=? AND "tag"=?)'
);
$statementHandle->execute(
array($this->scope, $this->cacheIdentifier,$this->scope, $this->cacheIdentifier, $tag)
);
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "tags" WHERE "scope"=? AND "cache"=? AND "tag"=?'
);
$statementHandle->execute(
array($this->scope, $this->cacheIdentifier, $tag)
);
}
/**
* Removes all cache entries of this cache which are tagged by the specified tags.
* This method doesn't exist in FLOW3, but is mandatory for TYPO3v4.
*
* @TODO: Make smarter
* @param array $tags The tags the entries must have
* @return void
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function flushBytags(array $tags) {
foreach($tags as $tag) {
$this->flushByTag($tag);
}
}
/**
* Finds and returns all cache entry identifiers which are tagged by the
* specified tag.
*
* @param string $tag The tag to search for
* @return array An array with identifiers of all matching entries. An empty array if no entries matched
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function findIdentifiersByTag($tag) {
$statementHandle = $this->databaseHandle->prepare(
'SELECT "identifier" FROM "tags" WHERE "scope"=? AND "cache"=? AND "tag"=?'
);
$statementHandle->execute(
array($this->scope, $this->cacheIdentifier, $tag)
);
return $statementHandle->fetchAll(PDO::FETCH_COLUMN);
}
/**
* Finds and returns all cache entry identifiers which are tagged with
* all of the specified tags.
* This method doesn't exist in FLOW3, but is mandatory for TYPO3v4.
*
* @TODO: Make smarter
* @param array $tags Tags to search for
* @return array An array with identifiers of all matching entries. An empty array if no entries matched
* @author Christian Kuhn <lolli@schwarzbu.ch>
*/
public function findIdentifiersByTags(array $tags) {
$taggedEntries = array();
$foundEntries = array();
foreach ($tags as $tag) {
$taggedEntries[$tag] = $this->findIdentifiersByTag($tag);
}
$intersectedTaggedEntries = call_user_func_array('array_intersect', $taggedEntries);
foreach ($intersectedTaggedEntries as $entryIdentifier) {
if ($this->has($entryIdentifier)) {
$foundEntries[$entryIdentifier] = $entryIdentifier;
}
}
return $foundEntries;
}
/**
* Does garbage collection
*
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
* @api
*/
public function collectGarbage() {
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "tags" WHERE "scope"=? AND "cache"=? AND "identifier" IN ' .
'(SELECT "identifier" FROM "cache" WHERE "scope"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . $GLOBALS['EXEC_TIME'] . ')'
);
$statementHandle->execute(
array($this->scope, $this->cacheIdentifier, $this->scope, $this->cacheIdentifier)
);
$statementHandle = $this->databaseHandle->prepare(
'DELETE FROM "cache" WHERE "scope"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . $GLOBALS['EXEC_TIME']
);
$statementHandle->execute(
array($this->scope, $this->cacheIdentifier)
);
}
/**
* Returns an SQL statement that evaluates to true if the entry is not expired.
*
* @return string
* @author Karsten Dambekalns <karsten@typo3.org>
*/
protected function getNotExpiredStatement() {
return ' AND ("lifetime" = 0 OR "created" + "lifetime" >= ' . $GLOBALS['EXEC_TIME'] . ')';
}
/**
* Connect to the database
*
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
*/
protected function connect() {
try {
$splitdsn = explode(':', $this->dataSourceName, 2);
$this->pdoDriver = $splitdsn[0];
if ($this->pdoDriver === 'sqlite' && !file_exists($splitdsn[1])) {
$this->createCacheTables();
}
$this->databaseHandle = t3lib_div::makeInstance('PDO', $this->dataSourceName, $this->username, $this->password);
$this->databaseHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($this->pdoDriver === 'mysql') {
$this->databaseHandle->exec('SET SESSION sql_mode=\'ANSI\';');
}
} catch (PDOException $e) {
# $this->createCacheTables();
}
}
/**
* Creates the tables needed for the cache backend.
*
* @return void
* @throws RuntimeException if something goes wrong
* @author Karsten Dambekalns <karsten@typo3.org>
*/
protected function createCacheTables() {
try {
$pdoHelper = t3lib_div::makeInstance('t3lib_PdoHelper', $this->dataSourceName, $this->username, $this->password);
$pdoHelper->importSql(PATH_t3lib . 'cache/backend/resources/ddl.sql');
} catch (PDOException $e) {
throw new RuntimeException(
'Could not create cache tables with DSN "' . $this->dataSourceName . '". PDO error: ' . $e->getMessage(),
1259576985
);
}
}
}
if (defined('TYPO3_MODE') && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_pdobackend.php']) {
include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/backend/class.t3lib_cache_backend_pdobackend.php']);
}
?>
t3lib/core_autoload.php (working copy)
't3lib_cache_backend_filebackend' => PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_filebackend.php',
't3lib_cache_backend_memcachedbackend' => PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_memcachedbackend.php',
't3lib_cache_backend_nullbackend' => PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_nullbackend.php',
't3lib_cache_backend_pdobackend' => PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_pdobackend.php',
't3lib_cache_backend_transientmemorybackend' => PATH_t3lib . 'cache/backend/class.t3lib_cache_backend_transientmemorybackend.php',
't3lib_cache_backend_backend' => PATH_t3lib . 'cache/backend/interfaces/interface.t3lib_cache_backend_backend.php',
't3lib_cache_exception_classalreadyloaded' => PATH_t3lib . 'cache/exception/class.t3lib_cache_exception_classalreadyloaded.php',
......
't3lib_matchcondition_abstract' => PATH_t3lib . 'matchcondition/class.t3lib_matchcondition_abstract.php',
't3lib_matchcondition_backend' => PATH_t3lib . 'matchcondition/class.t3lib_matchcondition_backend.php',
't3lib_matchcondition_frontend' => PATH_t3lib . 'matchcondition/class.t3lib_matchcondition_frontend.php',
't3lib_pdohelper' => PATH_t3lib . 'class.t3lib_pdohelper.php',
't3lib_tceforms_suggest' => PATH_t3lib . 'tceforms/class.t3lib_tceforms_suggest.php',
't3lib_tceforms_suggest_defaultreceiver' => PATH_t3lib . 'tceforms/class.t3lib_tceforms_suggest_defaultreceiver.php',
't3lib_utility_client' => PATH_t3lib . 'utility/class.t3lib_utility_client.php',
t3lib/class.t3lib_pdohelper.php (revision 0)
<?php
/***************************************************************
* Copyright notice
*
* (c) 2010 Christian Kuhn <lolli@schwarzbu.ch>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* A helper class for handling PDO databases
* Backport of FLOW3 class PdoHelper, last synced version: 3528
*
* @author Karsten Dambekalns <karsten@typo3.org>
* @package TYPO3
* @subpackage t3lib
* @version $Id$
* @scope prototype
*/
class t3lib_PdoHelper {
/**
* @var PDO
*/
protected $databaseHandle;
/**
* @var string
*/
protected $pdoDriver;
/**
* Construct the helper instance and set up PDO connection.
*
* @param string $dataSourceName
* @param string $user
* @param string $password
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function __construct($dataSourceName, $user, $password) {
$splitdsn = explode(':', $dataSourceName, 2);
$this->pdoDriver = $splitdsn[0];
$this->databaseHandle = t3lib_div::makeInstance('PDO', $dataSourceName, $user, $password);
$this->databaseHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($this->pdoDriver === 'mysql') {
$this->databaseHandle->exec('SET SESSION sql_mode=\'ANSI_QUOTES\';');
}
}
/**
* Pumps the SQL into the database. Use for DDL only.
*
* Important: key definitions with length specifiers (needed for MySQL) must
* be given as "field"(xyz) - no space between double quote and parenthesis -
* so they can be removed automatically.
*
* @param string $pathAndFilename
* @return void
* @author Karsten Dambekalns <karsten@typo3.org>
*/
public function importSql($pathAndFilename) {
$sql = file($pathAndFilename, FILE_IGNORE_NEW_LINES & FILE_SKIP_EMPTY_LINES);
// Remove MySQL style key length delimiters (yuck!) if we are not setting up a MySQL db
if ($this->pdoDriver !== 'mysql') {
$sql = preg_replace('/"\([0-9]+\)/', '"', $sql);
}
$statement = '';
foreach ($sql as $line) {
$statement .= ' ' . trim($line);
if (substr($statement, -1) === ';') {
$this->databaseHandle->query($statement);
$statement = '';
}
}
}
}
if (defined('TYPO3_MODE') && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_pdohelper.php']) {
include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_pdohelper.php']);
}
?>
(2-2/2)