Bug #22842 ยป 14666_01.diff
tests/t3lib/cache/frontend/t3lib_cache_frontend_phpfrontendtestcase.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 PHP source code cache frontend
|
||
*
|
||
* This file is a backport from FLOW3
|
||
*
|
||
* @author Christian Kuhn <lolli@schwarzbu.ch>
|
||
* @package TYPO3
|
||
* @subpackage tests
|
||
* @version $Id$
|
||
*/
|
||
class t3lib_cache_frontend_PhpFrontendTestCase extends tx_phpunit_testcase {
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @expectedException InvalidArgumentException
|
||
*/
|
||
public function setChecksIfTheIdentifierIsValid() {
|
||
$cache = $this->getMock('t3lib_cache_frontend_StringFrontend', array('isValidEntryIdentifier'), array(), '', FALSE);
|
||
$cache->expects($this->once())->method('isValidEntryIdentifier')->with('foo')->will($this->returnValue(FALSE));
|
||
$cache->set('foo', 'bar');
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
*/
|
||
public function setPassesPhpSourceCodeTagsAndLifetimeToBackend() {
|
||
$originalSourceCode = 'return "hello world!";';
|
||
$modifiedSourceCode = '<?php' . chr(10) . $originalSourceCode . chr(10) . '__halt_compiler();';
|
||
$mockBackend = $this->getMock('t3lib_cache_backend_PhpCapableBackend', array(), array(), '', FALSE);
|
||
$mockBackend->expects($this->once())->method('set')->with('Foo-Bar', $modifiedSourceCode, array('tags'), 1234);
|
||
$cache = t3lib_div::makeInstance('t3lib_cache_frontend_PhpFrontend', 'PhpFrontend', $mockBackend);
|
||
$cache->set('Foo-Bar', $originalSourceCode, array('tags'), 1234);
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @expectedException t3lib_cache_exception_InvalidData
|
||
*/
|
||
public function setThrowsInvalidDataExceptionOnNonStringValues() {
|
||
$cache = $this->getMock('t3lib_cache_frontend_PhpFrontend', array('dummy'), array(), '', FALSE);
|
||
$cache->set('Foo-Bar', array());
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
*/
|
||
public function requireOnceCallsTheBackendsRequireOnceMethod() {
|
||
$mockBackend = $this->getMock('t3lib_cache_backend_PhpCapableBackend', array(), array(), '', FALSE);
|
||
$mockBackend->expects($this->once())->method('requireOnce')->with('Foo-Bar')->will($this->returnValue('hello world!'));
|
||
$cache = t3lib_div::makeInstance('t3lib_cache_frontend_PhpFrontend', 'PhpFrontend', $mockBackend);
|
||
$result = $cache->requireOnce('Foo-Bar');
|
||
$this->assertSame('hello world!', $result);
|
||
}
|
||
}
|
||
?>
|
tests/t3lib/cache/backend/t3lib_cache_backend_filebackendtestcase.php (working copy) | ||
---|---|---|
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2009 Ingo Renner <ingo@typo3.org>
|
||
* (c) 2009-2010 Ingo Renner <ingo@typo3.org>
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the TYPO3 project. The TYPO3 project is
|
||
... | ... | |
*
|
||
* This file is a backport from FLOW3
|
||
*
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
* @author Christian Kuhn <lolli@schwarzbu.ch>
|
||
* @package TYPO3
|
||
* @subpackage tests
|
||
* @version $Id: t3lib_cache_backend_filebackendtestcase.php 7825 2010-06-06 14:52:10Z lolli $
|
||
*/
|
||
class t3lib_cache_backend_FileBackendTestCase extends tx_phpunit_testcase {
|
||
/**
|
||
* Backup of global variable EXEC_TIME
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $backupGlobalVariables;
|
||
/**
|
||
* If set, the tearDown() method will clean up the cache subdirectory used by this unit test.
|
||
... | ... | |
*/
|
||
protected $backend;
|
||
/**
|
||
* @var string Directory for testing data, relative to PATH_site
|
||
*/
|
||
protected $testingCacheDirectory;
|
||
/**
|
||
... | ... | |
* @return void
|
||
*/
|
||
public function setUp() {
|
||
$this->backupGlobalVariables = array(
|
||
'EXEC_TIME' => $GLOBALS['EXEC_TIME'],
|
||
);
|
||
$this->testingCacheDirectory = 'typo3temp/cache/testing/';
|
||
$this->backend = t3lib_div::makeInstance(
|
||
... | ... | |
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function getCacheDirectoryReturnsThePreviouslySetDirectory() {
|
||
public function getCacheDirectoryReturnsTheCurrentCacheDirectory() {
|
||
$directory = $this->testingCacheDirectory;
|
||
$fullPathToDirectory = t3lib_div::getIndpEnv('TYPO3_DOCUMENT_ROOT') . '/' . $directory;
|
||
... | ... | |
* @expectedException t3lib_cache_exception_InvalidData
|
||
*/
|
||
public function setThrowsExceptionIfDataIsNotAString() {
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$this->backend->setCache($mockCache);
|
||
$data = array('Some data');
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$this->backend->setCache($cache);
|
||
$this->backend->set($entryIdentifier, $data);
|
||
}
|
||
... | ... | |
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function setReallySavesToTheSpecifiedDirectory() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$entryIdentifierHash = sha1($entryIdentifier);
|
||
$this->backend->setCache($mockCache);
|
||
$pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
|
||
$this->backend->setCache($cache);
|
||
$this->backend->set($entryIdentifier, $data);
|
||
$this->backend->set($entryIdentifier, $data, array(), 10);
|
||
$cacheDirectory = $this->backend->getCacheDirectory();
|
||
$pathAndFilename = $cacheDirectory
|
||
. 'data/'
|
||
. $cacheIdentifier . '/'
|
||
. $entryIdentifierHash[0] . '/'
|
||
. $entryIdentifierHash[1] . '/'
|
||
. $entryIdentifier;
|
||
$this->assertTrue(file_exists($pathAndFilename), 'File does not exist.');
|
||
$retrievedData = file_get_contents($pathAndFilename, NULL, NULL, t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH);
|
||
$this->assertEquals(
|
||
$data,
|
||
$retrievedData,
|
||
'The original and the retrieved data don\'t match.'
|
||
);
|
||
$this->assertFileExists($pathAndFilename);
|
||
$retrievedData = file_get_contents($pathAndFilename, NULL, NULL, 0, strlen($data));
|
||
$this->assertEquals($data, $retrievedData);
|
||
}
|
||
/**
|
||
... | ... | |
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function setOverwritesAnAlreadyExistingCacheEntryForTheSameIdentifier() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$data1 = 'some data' . microtime();
|
||
$data2 = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileRemoveBeforeSetTest';
|
||
$entryIdentifierHash = sha1($entryIdentifier);
|
||
$this->backend->setCache($cache);
|
||
$this->backend->setCache($mockCache);
|
||
$this->backend->set($entryIdentifier, $data1, array(), 500);
|
||
// setting a second entry with the same identifier, but different
|
||
// Setting a second entry with the same identifier, but different
|
||
// data, this should _replace_ the existing one we set before
|
||
$this->backend->set($entryIdentifier, $data2, array(), 200);
|
||
$cacheDirectory = $this->backend->getCacheDirectory();
|
||
$pathAndFilename = $cacheDirectory
|
||
. 'data/'
|
||
. $cacheIdentifier . '/'
|
||
. $entryIdentifierHash[0] . '/'
|
||
. $entryIdentifierHash[1] . '/'
|
||
. $entryIdentifier;
|
||
$this->assertTrue(file_exists($pathAndFilename), 'File does not exist.');
|
||
$retrievedData = file_get_contents($pathAndFilename, NULL, NULL, t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH);
|
||
$pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
|
||
$this->assertFileExists($pathAndFilename);
|
||
$retrievedData = file_get_contents($pathAndFilename, NULL, NULL, 0, strlen($data2));
|
||
$this->assertEquals($data2, $retrievedData);
|
||
}
|
||
... | ... | |
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function setReallySavesSpecifiedTags() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
public function setAlsoSavesSpecifiedTags() {
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$entryIdentifierHash = sha1($entryIdentifier);
|
||
$this->backend->setCache($cache);
|
||
$tagsDirectory = $this->backend->getCacheDirectory() . 'tags/';
|
||
$this->backend->setCache($mockCache);
|
||
$this->backend->set($entryIdentifier, $data, array('Tag1', 'Tag2'));
|
||
$this->backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
|
||
$this->assertTrue(is_dir($tagsDirectory . 'UnitTestTag%tag1'), 'Tag directory UnitTestTag%tag1 does not exist.');
|
||
$this->assertTrue(is_dir($tagsDirectory . 'UnitTestTag%tag2'), 'Tag directory UnitTestTag%tag2 does not exist.');
|
||
$filename = $tagsDirectory . 'UnitTestTag%tag1/' . $cacheIdentifier . t3lib_cache_backend_FileBackend::SEPARATOR . $entryIdentifier;
|
||
$this->assertTrue(file_exists($filename), 'File "' . $filename . '" does not exist.');
|
||
$filename = $tagsDirectory . 'UnitTestTag%tag2/' . $cacheIdentifier . t3lib_cache_backend_FileBackend::SEPARATOR . $entryIdentifier;
|
||
$this->assertTrue(file_exists($filename), 'File "' . $filename . '" does not exist.');
|
||
$pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
|
||
$this->assertFileExists($pathAndFilename);
|
||
$retrievedData = file_get_contents($pathAndFilename, NULL, NULL, (strlen($data) + t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH), 9);
|
||
$this->assertEquals('Tag1 Tag2', $retrievedData);
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Karsten Dambekalns <karsten@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function getReturnsContentOfTheCorrectCacheFile() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
public function setWithUnlimitedLifetimeWritesCorrectEntry() {
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$this->backend->setCache($cache);
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$data = 'some data' . microtime();
|
||
$this->backend->set($entryIdentifier, $data, array(), 500);
|
||
$this->backend->setCache($mockCache);
|
||
$pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
|
||
$data = 'some other data' . microtime();
|
||
$this->backend->set($entryIdentifier, $data, array(), 100);
|
||
$this->backend->set($entryIdentifier, $data, array(), 0);
|
||
$loadedData = $this->backend->get($entryIdentifier);
|
||
$this->assertFileExists($pathAndFilename);
|
||
$this->assertEquals($data, $loadedData, 'The original and the retrieved data don\'t match.');
|
||
$dataSize = (integer)file_get_contents($pathAndFilename, NULL, NULL, filesize($pathAndFilename) - t3lib_cache_backend_FileBackend::DATASIZE_DIGITS, t3lib_cache_backend_FileBackend::DATASIZE_DIGITS);
|
||
$retrievedData = file_get_contents($pathAndFilename, NULL, NULL, 0, $dataSize);
|
||
$this->assertEquals($data, $retrievedData, 'The original and the retrieved data don\'t match.');
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
*/
|
||
public function getReturnsFalseForExpiredEntries() {
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$backend = $this->getMock('t3lib_cache_backend_FileBackend', array('isCacheFileExpired'), array(), '', FALSE);
|
||
$fullPathToCacheFile = t3lib_div::getIndpEnv('TYPO3_DOCUMENT_ROOT') . '/typo3temp/cache/UnitTestCache/ExpiredEntry';
|
||
$backend->expects($this->once())->method('isCacheFileExpired')->with($fullPathToCacheFile)->will($this->returnValue(TRUE));
|
||
$backend->setCache($mockCache);
|
||
$this->assertFalse($backend->get('ExpiredEntry'));
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function hasReturnsTheCorrectResult() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
public function hasReturnsTrueIfAnEntryExists() {
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$this->backend->setCache($cache);
|
||
$this->backend->setCache($mockCache);
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$data = 'some data' . microtime();
|
||
$this->backend->set($entryIdentifier, $data);
|
||
... | ... | |
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
*/
|
||
public function hasReturnsFalseForExpiredEntries() {
|
||
$backend = $this->getMock('t3lib_cache_backend_FileBackend', array('isCacheFileExpired'), array(), '', FALSE);
|
||
$backend->expects($this->exactly(2))->method('isCacheFileExpired')->will($this->onConsecutiveCalls(TRUE, FALSE));
|
||
$this->assertFalse($backend->has('foo'));
|
||
$this->assertTrue($backend->has('bar'));
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function removeReallyRemovesACacheEntry() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileRemovalTest';
|
||
$entryIdentifierHash = sha1($entryIdentifier);
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$cacheDirectory = $this->backend->getCacheDirectory();
|
||
$this->backend->setCache($cache);
|
||
$pathAndFilename = $cacheDirectory
|
||
. 'data/'
|
||
. $cacheIdentifier . '/'
|
||
. $entryIdentifierHash[0] . '/'
|
||
. $entryIdentifierHash[1] . '/'
|
||
. $entryIdentifier;
|
||
$this->backend->setCache($mockCache);
|
||
$pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
|
||
$this->backend->set($entryIdentifier, $data);
|
||
$this->assertTrue(file_exists($pathAndFilename), 'The cache entry does not exist.');
|
||
$this->assertFileExists($pathAndFilename);
|
||
$this->backend->remove($entryIdentifier);
|
||
$this->assertFalse(file_exists($pathAndFilename), 'The cache entry still exists.');
|
||
$this->assertFileNotExists($pathAndFilename);
|
||
}
|
||
/**
|
||
... | ... | |
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function collectGarbageReallyRemovesAnExpiredCacheEntry() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileRemovalTest';
|
||
$entryIdentifierHash = sha1($entryIdentifier);
|
||
$cacheDirectory = $this->backend->getCacheDirectory();
|
||
$this->backend->setCache($cache);
|
||
$pathAndFilename = $cacheDirectory
|
||
. 'data/'
|
||
. $cacheIdentifier . '/'
|
||
. $entryIdentifierHash[0] . '/'
|
||
. $entryIdentifierHash[1] . '/'
|
||
. $entryIdentifier;
|
||
$this->backend->setCache($mockCache);
|
||
$pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
|
||
$this->backend->set($entryIdentifier, $data, array(), 1);
|
||
$this->assertTrue(file_exists($pathAndFilename), 'The cache entry does not exist.');
|
||
sleep(2);
|
||
$this->assertFileExists($pathAndFilename);
|
||
$GLOBALS['EXEC_TIME'] += 2;
|
||
$this->backend->collectGarbage();
|
||
$this->assertFalse(file_exists($pathAndFilename), 'The cache entry still exists.');
|
||
$this->assertFileNotExists($pathAndFilename);
|
||
}
|
||
/**
|
||
... | ... | |
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function collectGarbageReallyRemovesAllExpiredCacheEntries() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileRemovalTest';
|
||
$cacheDirectory = $this->backend->getCacheDirectory();
|
||
$this->backend->setCache($cache);
|
||
$this->backend->setCache($mockCache);
|
||
$pathAndFilename = $this->backend->getCacheDirectory() . $entryIdentifier;
|
||
$pattern = $cacheDirectory
|
||
. 'data/'
|
||
. $cacheIdentifier . '/*/*/'
|
||
. $entryIdentifier
|
||
. '?';
|
||
$this->backend->set($entryIdentifier . 'A', $data, array(), 1);
|
||
$this->backend->set($entryIdentifier . 'B', $data, array(), 1);
|
||
$this->backend->set($entryIdentifier . 'A', $data, array(), NULL);
|
||
$this->backend->set($entryIdentifier . 'B', $data, array(), 10);
|
||
$this->backend->set($entryIdentifier . 'C', $data, array(), 1);
|
||
$filesFound = glob($pattern);
|
||
$this->assertTrue(is_array($filesFound) && count($filesFound) > 0, 'The cache entries do not exist.');
|
||
$this->backend->set($entryIdentifier . 'D', $data, array(), 1);
|
||
sleep(2);
|
||
$this->assertFileExists($pathAndFilename . 'A');
|
||
$this->assertFileExists($pathAndFilename . 'B');
|
||
$this->assertFileExists($pathAndFilename . 'C');
|
||
$this->assertFileExists($pathAndFilename . 'D');
|
||
$GLOBALS['EXEC_TIME'] += 2;
|
||
$this->backend->collectGarbage();
|
||
$filesFound = is_array(glob($pattern)) ? glob($pattern) : array();
|
||
$this->assertTrue(count($filesFound) === 0, 'The cache entries still exist.');
|
||
$this->assertFileExists($pathAndFilename . 'A');
|
||
$this->assertFileExists($pathAndFilename . 'B');
|
||
$this->assertFileNotExists($pathAndFilename . 'C');
|
||
$this->assertFileNotExists($pathAndFilename . 'D');
|
||
}
|
||
/**
|
||
... | ... | |
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function removeReallyRemovesTagsOfRemovedEntry() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag() {
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$this->backend->setCache($mockCache);
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
|
||
$this->backend->set('BackendFileTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
|
||
$this->backend->set('BackendFileTest3', $data, array('UnitTestTag%test'));
|
||
$this->backend->setCache($cache);
|
||
$expectedEntry = 'BackendFileTest2';
|
||
$tagsDirectory = $this->backend->getCacheDirectory() . 'tags/';
|
||
$actualEntries = $this->backend->findIdentifiersByTag('UnitTestTag%special');
|
||
$this->backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
|
||
$this->backend->remove($entryIdentifier);
|
||
$this->assertTrue(!file_exists($tagsDirectory . 'UnitTestTag%tag1/' . $entryIdentifier), 'File "' . $tagsDirectory . 'UnitTestTag%tag1/' . $entryIdentifier . '" still exists.');
|
||
$this->assertTrue(!file_exists($tagsDirectory . 'UnitTestTag%tag2/' . $entryIdentifier), 'File "' . $tagsDirectory . 'UnitTestTag%tag2/' . $entryIdentifier . '" still exists.');
|
||
$this->assertTrue(is_array($actualEntries), 'actualEntries is not an array.');
|
||
$this->assertEquals($expectedEntry, array_pop($actualEntries));
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
public function findIdentifiersByTagDoesNotReturnExpiredEntries() {
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$this->backend->setCache($cache);
|
||
$this->backend->setCache($mockCache);
|
||
$data = 'some data' . microtime();
|
||
$data = 'some data';
|
||
$this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
|
||
$this->backend->set('BackendFileTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
|
||
$this->backend->set('BackendFileTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'), -100);
|
||
$this->backend->set('BackendFileTest3', $data, array('UnitTestTag%test'));
|
||
$expectedEntry = 'BackendFileTest2';
|
||
$actualEntries = $this->backend->findIdentifiersByTag('UnitTestTag%special');
|
||
$this->assertTrue(is_array($actualEntries), 'actualEntries is not an array.');
|
||
$this->assertEquals($expectedEntry, array_pop($actualEntries));
|
||
$this->assertSame(array(), $this->backend->findIdentifiersByTag('UnitTestTag%special'));
|
||
$foundIdentifiers = $this->backend->findIdentifiersByTag('UnitTestTag%test');
|
||
sort($foundIdentifiers);
|
||
$this->assertSame(array('BackendFileTest1', 'BackendFileTest3'), $foundIdentifiers);
|
||
}
|
||
/**
|
||
... | ... | |
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function flushRemovesAllCacheEntriesAndRelatedTags() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
public function flushRemovesAllCacheEntries() {
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$this->backend->setCache($cache);
|
||
$this->backend->setCache($mockCache);
|
||
$tagsDirectory = $this->backend->getCacheDirectory() . 'tags/';
|
||
$cacheDirectory = $this->backend->getCacheDirectory() . 'data/' . $cacheIdentifier . '/';
|
||
$data = 'some data' . microtime();
|
||
$this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test'));
|
||
$this->backend->set('BackendFileTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
|
||
... | ... | |
$this->backend->flush();
|
||
$pattern = $cacheDirectory . '*/*/*';
|
||
$pattern = $this->backend->getCacheDirectory() . '*';
|
||
$filesFound = is_array(glob($pattern)) ? glob($pattern) : array();
|
||
$this->assertTrue(count($filesFound) === 0, 'Still files in the cache directory');
|
||
$tagPrefixTest = $tagsDirectory . 'UnitTestTag%test/' . $cacheIdentifier . '^';
|
||
$tagPrefixSpecial = $tagsDirectory . 'UnitTestTag%special/' . $cacheIdentifier . '^';
|
||
$entryIdentifier = 'BackendFileTest1';
|
||
$this->assertTrue(!file_exists($tagPrefixTest . $entryIdentifier), 'File "' . $tagPrefixTest . $entryIdentifier . '" still exists.');
|
||
$entryIdentifier = 'BackendFileTest2';
|
||
$this->assertTrue(!file_exists($tagPrefixTest . $entryIdentifier), 'File "' . $tagPrefixTest . $entryIdentifier . '" still exists.');
|
||
$this->assertTrue(!file_exists($tagPrefixSpecial . $entryIdentifier), 'File "' . $tagPrefixSpecial . $entryIdentifier . '" still exists.');
|
||
$entryIdentifier = 'BackendFileTest3';
|
||
$this->assertTrue(!file_exists($tagPrefixTest . $entryIdentifier), 'File "' . $tagPrefixTest . $entryIdentifier . '" still exists.');
|
||
}
|
||
/**
|
||
... | ... | |
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function flushByTagRemovesCacheEntriesWithSpecifiedTag() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$mockCache = $this->getMock('t3lib_cache_frontend_AbstractFrontend', array(), array(), '', FALSE);
|
||
$mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
|
||
$this->backend->setCache($cache);
|
||
$this->backend->setCache($mockCache);
|
||
$data = 'some data' . microtime();
|
||
$this->backend->set('BackendFileTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
|
||
... | ... | |
$this->assertTrue($this->backend->has('BackendFileTest3'), 'BackendFileTest3');
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Karsten Dambekalns <karsten@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function hasReturnsTheCorrectResultForEntryWithExceededLifetime() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$this->backend->setCache($cache);
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$data = 'some data' . microtime();
|
||
$this->backend->set($entryIdentifier, $data);
|
||
$expiredEntryIdentifier = 'ExpiredBackendFileTest';
|
||
$expiredData = 'some old data' . microtime();
|
||
$this->backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
|
||
sleep(2);
|
||
$this->assertFalse($this->backend->has($expiredEntryIdentifier), 'has() did not return FALSE.');
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Karsten Dambekalns <karsten@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function getReturnsFalseForEntryWithExceededLifetime() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$this->backend->setCache($cache);
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$data = 'some data' . microtime();
|
||
$this->backend->set($entryIdentifier, $data);
|
||
$expiredEntryIdentifier = 'ExpiredBackendFileTest';
|
||
$expiredData = 'some old data' . microtime();
|
||
$this->backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
|
||
sleep(2);
|
||
$this->assertEquals($data, $this->backend->get($entryIdentifier), 'The original and the retrieved data don\'t match.');
|
||
$this->assertFalse($this->backend->get($expiredEntryIdentifier), 'The expired entry could be loaded.');
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Karsten Dambekalns <karsten@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function findIdentifiersByTagReturnsEmptyArrayForEntryWithExceededLifetime() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$this->backend->setCache($cache);
|
||
$this->backend->set('BackendFileTest', 'some data', array('UnitTestTag%special'), 1);
|
||
sleep(2);
|
||
$this->assertEquals(array(), $this->backend->findIdentifiersByTag('UnitTestTag%special'));
|
||
}
|
||
/**
|
||
* @test
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Karsten Dambekalns <karsten@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function setWithUnlimitedLifetimeWritesCorrectEntry() {
|
||
$cacheIdentifier = 'UnitTestCache';
|
||
$cache = $this->getMock('t3lib_cache_frontend_AbstractFrontend',
|
||
array('getIdentifier', 'set', 'get', 'getByTag', 'has', 'remove'),
|
||
array(),
|
||
'',
|
||
FALSE
|
||
);
|
||
$cache->expects($this->atLeastOnce())
|
||
->method('getIdentifier')
|
||
->will($this->returnValue($cacheIdentifier));
|
||
$data = 'some data' . microtime();
|
||
$entryIdentifier = 'BackendFileTest';
|
||
$entryIdentifierHash = sha1($entryIdentifier);
|
||
$this->backend->setCache($cache);
|
||
$this->backend->set($entryIdentifier, $data, array(), 0);
|
||
$cacheDirectory = $this->backend->getCacheDirectory();
|
||
$pathAndFilename = $cacheDirectory
|
||
. 'data/'
|
||
. $cacheIdentifier . '/'
|
||
. $entryIdentifierHash[0] . '/'
|
||
. $entryIdentifierHash[1] . '/'
|
||
. $entryIdentifier;
|
||
$this->assertTrue(file_exists($pathAndFilename), 'File not found.');
|
||
$retrievedData = file_get_contents($pathAndFilename, NULL, NULL, t3lib_cache_backend_FileBackend::EXPIRYTIME_LENGTH);
|
||
$this->assertEquals($data, $retrievedData, 'The original and the retrieved data don\'t match.');
|
||
}
|
||
/**
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
public function tearDown() {
|
||
if (is_object($this->backend)) {
|
||
$directory = $this->backend->getCacheDirectory();
|
||
if (is_dir($directory)) {
|
||
t3lib_div::rmdir($directory, true);
|
||
t3lib_div::rmdir($directory, TRUE);
|
||
}
|
||
}
|
||
foreach ($this->backupGlobalVariables as $key => $data) {
|
||
$GLOBALS[$key] = $data;
|
||
}
|
||
}
|
||
}
|
||
?>
|
||
?>
|
t3lib/cache/frontend/class.t3lib_cache_frontend_phpfrontend.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 cache frontend tailored to PHP code.
|
||
*
|
||
* This file is a backport from FLOW3
|
||
*
|
||
* @package TYPO3
|
||
* @subpackage t3lib_cache
|
||
* @api
|
||
* @scope prototype
|
||
* @version $Id$
|
||
*/
|
||
class t3lib_cache_frontend_PhpFrontend extends t3lib_cache_frontend_StringFrontend {
|
||
/**
|
||
* Constructs the cache
|
||
*
|
||
* @param string $identifier A identifier which describes this cache
|
||
* @param t3lib_cache_backend_PhpCapableBackend $backend Backend to be used for this cache
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
*/
|
||
public function __construct($identifier, t3lib_cache_backend_PhpCapableBackend $backend) {
|
||
parent::__construct($identifier, $backend);
|
||
}
|
||
/**
|
||
* Saves the PHP source code in the cache.
|
||
*
|
||
* @param string $entryIdentifier An identifier used for this cache entry, for example the class name
|
||
* @param string $sourceCode PHP source code
|
||
* @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
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @api
|
||
*/
|
||
public function set($entryIdentifier, $sourceCode, $tags = array(), $lifetime = NULL) {
|
||
if (!$this->isValidEntryIdentifier($entryIdentifier)) {
|
||
throw new InvalidArgumentException(
|
||
'"' . $entryIdentifier . '" is not a valid cache entry identifier.',
|
||
1264023823
|
||
);
|
||
}
|
||
if (!is_string($sourceCode)) {
|
||
throw new t3lib_cache_exception_InvalidData(
|
||
'The given source code is not a valid string.',
|
||
1264023824
|
||
);
|
||
}
|
||
foreach ($tags as $tag) {
|
||
if (!$this->isValidTag($tag)) {
|
||
throw new InvalidArgumentException(
|
||
'"' . $tag . '" is not a valid tag for a cache entry.',
|
||
1264023825
|
||
);
|
||
}
|
||
}
|
||
$sourceCode = '<?php' . chr(10) . $sourceCode . chr(10) . '__halt_compiler();';
|
||
$this->backend->set($entryIdentifier, $sourceCode, $tags, $lifetime);
|
||
}
|
||
/**
|
||
* Loads PHP code from the cache and require_onces it right away.
|
||
*
|
||
* @param string $entryIdentifier An identifier which describes the cache entry to load
|
||
* @return mixed Potential return value from the include operation
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @api
|
||
*/
|
||
public function requireOnce($entryIdentifier) {
|
||
return $this->backend->requireOnce($entryIdentifier);
|
||
}
|
||
}
|
||
if (defined('TYPO3_MODE') && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_frontend_phpfrontend.php']) {
|
||
include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/cache/class.t3lib_cache_frontend_phpfrontend.php']);
|
||
}
|
||
?>
|
t3lib/cache/backend/interfaces/interface.t3lib_cache_backend_phpcapablebackend.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 contract for a cache backend which is capable of storing, retrieving and
|
||
* including PHP source code.
|
||
*
|
||
* @version $Id$
|
||
* @api
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
*/
|
||
interface t3lib_cache_backend_PhpCapableBackend extends t3lib_cache_backend_Backend {
|
||
/**
|
||
* Loads PHP code from the cache and require_onces it right away.
|
||
*
|
||
* @param string $entryIdentifier An identifier which describes the cache entry to load
|
||
* @return mixed Potential return value from the include operation
|
||
* @api
|
||
*/
|
||
public function requireOnce($entryIdentifier);
|
||
}
|
||
?>
|
t3lib/cache/backend/class.t3lib_cache_backend_filebackend.php (working copy) | ||
---|---|---|
* @api
|
||
* @version $Id$
|
||
*/
|
||
class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBackend {
|
||
class t3lib_cache_backend_FileBackend extends t3lib_cache_backend_AbstractBackend implements t3lib_cache_backend_PhpCapableBackend {
|
||
const SEPARATOR = '^';
|
||
const EXPIRYTIME_FORMAT = 'YmdHis';
|
||
const EXPIRYTIME_LENGTH = 14;
|
||
const DATASIZE_DIGITS = 10;
|
||
/**
|
||
* @var string Directory where the files are stored
|
||
*/
|
||
protected $cacheDirectory = '';
|
||
/**
|
||
* @var string Absolute path to root, usually document root of website
|
||
*/
|
||
protected $root = '/';
|
||
/**
|
||
* Maximum allowed file path length in the current environment.
|
||
* Will be set in initializeObject()
|
||
*
|
||
* @var integer
|
||
*/
|
||
... | ... | |
public function __construct(array $options = array()) {
|
||
parent::__construct($options);
|
||
if (is_null($this->maximumPathLength)) {
|
||
$this->maximumPathLength = t3lib_div::getMaximumPathLength();
|
||
}
|
||
}
|
||
/**
|
||
* Sets a reference to the cache frontend which uses this backend and
|
||
* initializes the default cache directory
|
||
*
|
||
* @void
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
*/
|
||
public function setCache(t3lib_cache_frontend_frontend $cache) {
|
||
parent::setCache($cache);
|
||
if (empty($this->cacheDirectory)) {
|
||
$cacheDirectory = 'typo3temp/cache/';
|
||
try {
|
||
$this->setCacheDirectory($cacheDirectory);
|
||
} catch(t3lib_cache_Exception $exception) {
|
||
}
|
||
}
|
||
if (is_null($this->maximumPathLength)) {
|
||
$this->maximumPathLength = t3lib_div::getMaximumPathLength();
|
||
}
|
||
}
|
||
/**
|
||
... | ... | |
$documentRoot = PATH_site;
|
||
if (($open_basedir = ini_get('open_basedir'))) {
|
||
if (TYPO3_OS === 'WIN') {
|
||
$delimiter = ';';
|
||
$cacheDirectory = str_replace('\\', '/', $cacheDirectory);
|
||
... | ... | |
$cacheDirectory = PATH_site . $cacheDirectory;
|
||
}
|
||
}
|
||
$basedirs = explode($delimiter, $open_basedir);
|
||
$basedirs = explode($delimiter, $open_basedir);
|
||
$cacheDirectoryInBaseDir = FALSE;
|
||
foreach ($basedirs as $basedir) {
|
||
if (TYPO3_OS === 'WIN') {
|
||
$basedir = str_replace('\\', '/', $basedir);
|
||
... | ... | |
break;
|
||
}
|
||
}
|
||
if (!$cacheDirectoryInBaseDir) {
|
||
throw new t3lib_cache_Exception(
|
||
'Open_basedir restriction in effect. The directory "' . $cacheDirectory . '" is not in an allowed path.'
|
||
... | ... | |
}
|
||
} else {
|
||
if ($cacheDirectory[0] == '/') {
|
||
// absolute path to cache directory.
|
||
// Absolute path to cache directory.
|
||
$documentRoot = '/';
|
||
}
|
||
if (TYPO3_OS === 'WIN') {
|
||
$documentRoot = '';
|
||
}
|
||
}
|
||
// after this point all paths have '/' as directory seperator
|
||
// After this point all paths have '/' as directory seperator
|
||
if ($cacheDirectory[strlen($cacheDirectory) - 1] !== '/') {
|
||
$cacheDirectory .= '/';
|
||
}
|
||
$cacheDirectory .= $this->cacheIdentifier;
|
||
if ($cacheDirectory[strlen($cacheDirectory) - 1] !== '/') {
|
||
$cacheDirectory .= '/';
|
||
}
|
||
if (!is_writable($documentRoot . $cacheDirectory)) {
|
||
t3lib_div::mkdir_deep(
|
||
... | ... | |
$cacheDirectory
|
||
);
|
||
}
|
||
if (!is_dir($documentRoot . $cacheDirectory)) {
|
||
throw new t3lib_cache_Exception(
|
||
'The directory "' . $documentRoot . $cacheDirectory . '" does not exist.',
|
||
1203965199
|
||
);
|
||
}
|
||
if (!is_writable($documentRoot . $cacheDirectory)) {
|
||
throw new t3lib_cache_Exception(
|
||
'The directory "' . $documentRoot . $cacheDirectory . '" is not writable.',
|
||
... | ... | |
);
|
||
}
|
||
$tagsDirectory = $cacheDirectory . 'tags/';
|
||
if (!is_writable($documentRoot . $tagsDirectory)) {
|
||
t3lib_div::mkdir_deep(
|
||
$documentRoot,
|
||
$tagsDirectory
|
||
);
|
||
}
|
||
$this->root = $documentRoot;
|
||
$this->cacheDirectory = $cacheDirectory;
|
||
}
|
||
... | ... | |
*
|
||
* @return string Full path of the cache directory
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @api
|
||
*/
|
||
public function getCacheDirectory() {
|
||
return $this->root . $this->cacheDirectory;
|
||
... | ... | |
/**
|
||
* Saves data in a cache file.
|
||
*
|
||
* @param string An identifier for this specific cache entry
|
||
* @param string The data to be stored
|
||
* @param array Tags to associate with this cache entry
|
||
* @param integer Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
|
||
* @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 lifetime.
|
||
* @return void
|
||
* @throws t3lib_cache_Exception if the directory does not exist or is not writable or exceeds the maximum allowed path length, or if no cache frontend has been set.
|
||
* @throws t3lib_cache_exception_InvalidData if the data to bes stored is not a string.
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @api
|
||
*/
|
||
public function set($entryIdentifier, $data, array $tags = array(), $lifetime = NULL) {
|
||
if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
|
||
... | ... | |
);
|
||
}
|
||
$expirytime = $this->calculateExpiryTime($lifetime);
|
||
$cacheEntryPath = $this->renderCacheEntryPath($entryIdentifier);
|
||
$absCacheEntryPath = $this->root . $cacheEntryPath;
|
||
if (!is_writable($absCacheEntryPath)) {
|
||
try {
|
||
t3lib_div::mkdir_deep(
|
||
$this->root,
|
||
$cacheEntryPath
|
||
);
|
||
} catch(Exception $exception) {
|
||
}
|
||
if (!is_writable($absCacheEntryPath)) {
|
||
throw new t3lib_cache_Exception(
|
||
'The cache directory "' . $absCacheEntryPath . '" could not be created.',
|
||
1204026250
|
||
);
|
||
}
|
||
}
|
||
$this->remove($entryIdentifier);
|
||
$data = $expirytime->format(self::EXPIRYTIME_FORMAT) . $data;
|
||
$cacheEntryPathAndFilename = $absCacheEntryPath . uniqid() . '.temp';
|
||
if (strlen($cacheEntryPathAndFilename) > $this->maximumPathLength) {
|
||
$temporaryCacheEntryPathAndFilename = $this->root . $this->cacheDirectory . uniqid() . '.temp';
|
||
if (strlen($temporaryCacheEntryPathAndFilename) > $this->maximumPathLength) {
|
||
throw new t3lib_cache_Exception(
|
||
'The length of the temporary cache file path "' . $cacheEntryPathAndFilename .
|
||
'" is ' . strlen($cacheEntryPathAndFilename) . ' characters long and exceeds the maximum path length of ' .
|
||
'The length of the temporary cache file path "' . $temporaryCacheEntryPathAndFilename .
|
||
'" is ' . strlen($temporaryCacheEntryPathAndFilename) . ' characters long and exceeds the maximum path length of ' .
|
||
$this->maximumPathLength . '. Please consider setting the temporaryDirectoryBase option to a shorter path. ',
|
||
1248710426
|
||
);
|
||
}
|
||
$result = file_put_contents($cacheEntryPathAndFilename, $data);
|
||
$expiryTime = ($lifetime === NULL) ? 0 : ($GLOBALS['EXEC_TIME'] + $lifetime);
|
||
$metaData = str_pad($expiryTime, self::EXPIRYTIME_LENGTH) . implode(' ', $tags) . str_pad(strlen($data), self::DATASIZE_DIGITS);
|
||
$result = file_put_contents($temporaryCacheEntryPathAndFilename, $data . $metaData);
|
||
if ($result === FALSE) {
|
||
throw new t3lib_cache_Exception(
|
||
'The temporary cache file "' . $cacheEntryPathAndFilename . '" could not be written.',
|
||
throw new t3lib_cache_exception(
|
||
'The temporary cache file "' . $temporaryCacheEntryPathAndFilename . '" could not be written.',
|
||
1204026251
|
||
);
|
||
}
|
||
for ($i = 0; $i < 5; $i++) {
|
||
$result = rename($cacheEntryPathAndFilename, $absCacheEntryPath . $entryIdentifier);
|
||
if ($result === TRUE) {
|
||
break;
|
||
}
|
||
$i = 0;
|
||
$cacheEntryPathAndFilename = $this->root . $this->cacheDirectory . $entryIdentifier;
|
||
// @TODO: Figure out why the heck this is done and maybe find a smarter solution, report to FLOW3
|
||
while (!rename($temporaryCacheEntryPathAndFilename, $cacheEntryPathAndFilename) && $i < 5) {
|
||
$i++;
|
||
}
|
||
// @FIXME: At least the result of rename() should be handled here, report to FLOW3
|
||
if ($result === FALSE) {
|
||
throw new t3lib_cache_Exception(
|
||
'The cache file "' . $entryIdentifier . '" could not be written.',
|
||
throw new t3lib_cache_exception(
|
||
'The cache file "' . $cacheEntryPathAndFilename . '" could not be written.',
|
||
1222361632
|
||
);
|
||
}
|
||
foreach ($tags as $tag) {
|
||
$this->setTag($entryIdentifier, $tag);
|
||
}
|
||
}
|
||
/**
|
||
* Creates a tag that is associated with the given cache identifier
|
||
*
|
||
* @param string $entryIdentifier An identifier for this specific cache entry
|
||
* @param string $tag Tag to associate with this cache entry
|
||
* @return void
|
||
* @throws t3lib_cache_Exception if the tag path is not writable or exceeds the maximum allowed path length
|
||
* @author Bastian Waidelich <bastian@typo3.org>
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
*/
|
||
protected function setTag($entryIdentifier, $tag) {
|
||
$tagPath = $this->cacheDirectory . 'tags/' . $tag . '/';
|
||
$absTagPath = $this->root . $tagPath;
|
||
if (!is_writable($absTagPath)) {
|
||
t3lib_div::mkdir_deep($this->root, $tagPath);
|
||
if (!is_writable($absTagPath)) {
|
||
throw new t3lib_cache_Exception(
|
||
'The tag directory "' . $absTagPath . '" could not be created.',
|
||
1238242144
|
||
);
|
||
}
|
||
}
|
||
$tagPathAndFilename = $absTagPath . $this->cacheIdentifier
|
||
. self::SEPARATOR . $entryIdentifier;
|
||
if (strlen($tagPathAndFilename) > $this->maximumPathLength) {
|
||
throw new t3lib_cache_Exception(
|
||
'The length of the tag path "' . $tagPathAndFilename . '" is ' . strlen($tagPathAndFilename) .
|
||
' characters long and exceeds the maximum path length of ' . $this->maximumPathLength .
|
||
'. Please consider setting the temporaryDirectoryBase option to a shorter path. ',
|
||
1248710426
|
||
);
|
||
}
|
||
touch($tagPathAndFilename);
|
||
}
|
||
/**
|
||
* Loads data from a cache file.
|
||
*
|
||
* @param string An identifier which describes the cache entry to load
|
||
* @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 Robert Lemke <robert@typo3.org>
|
||
* @author Karsten Dambekalns <karsten@typo3.org>
|
||
* @api
|
||
*/
|
||
public function get($entryIdentifier) {
|
||
$pathAndFilename = $this->root . $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
|
||
return ($this->isCacheFileExpired($pathAndFilename)) ? FALSE : file_get_contents($pathAndFilename, NULL, NULL, self::EXPIRYTIME_LENGTH);
|
||
$pathAndFilename = $this->root . $this->cacheDirectory . $entryIdentifier;
|
||
if ($this->isCacheFileExpired($pathAndFilename)) {
|
||
return FALSE;
|
||
}
|
||
$dataSize = (integer)file_get_contents($pathAndFilename, NULL, NULL, filesize($pathAndFilename) - self::DATASIZE_DIGITS, self::DATASIZE_DIGITS);
|
||
return file_get_contents($pathAndFilename, NULL, NULL, 0, $dataSize);
|
||
}
|
||
/**
|
||
* Checks if a cache entry with the specified identifier exists.
|
||
*
|
||
* @param string $entryIdentifier
|
||
* @return boolean TRUE if such an entry exists, FALSE if not
|
||
* @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 Robert Lemke <robert@typo3.org>
|
||
* @api
|
||
*/
|
||
public function has($entryIdentifier) {
|
||
return !$this->isCacheFileExpired($this->root . $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier);
|
||
return !$this->isCacheFileExpired($this->root . $this->cacheDirectory . $entryIdentifier);
|
||
}
|
||
/**
|
||
* Removes all cache entries matching the specified identifier.
|
||
* Usually this only affects one entry.
|
||
*
|
||
* @param string Specifies the cache entry to remove
|
||
* @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 Robert Lemke <robert@typo3.org>
|
||
* @api
|
||
*/
|
||
public function remove($entryIdentifier) {
|
||
$pathAndFilename = $this->root . $this->renderCacheEntryPath($entryIdentifier) . $entryIdentifier;
|
||
$pathAndFilename = $this->root . $this->cacheDirectory . $entryIdentifier;
|
||
if (!file_exists($pathAndFilename)) {
|
||
return FALSE;
|
||
}
|
||
if (unlink($pathAndFilename) === FALSE) {
|
||
return FALSE;
|
||
}
|
||
foreach($this->findTagFilesByEntry($entryIdentifier) as $pathAndFilename) {
|
||
if (!file_exists($pathAndFilename)) {
|
||
return FALSE;
|
||
}
|
||
if (unlink($pathAndFilename) === FALSE) {
|
||
return FALSE;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
... | ... | |
* Finds and returns all cache entry identifiers which are tagged by the
|
||
* specified tag.
|
||
*
|
||
* @param string The tag to search for
|
||
* @param string $searchedTag The tag to search for
|
||
* @return array An array with identifiers of all matching entries. An empty array if no entries matched
|
||
* @author Robert Lemke <robert@typo3.org>
|
||
* @author Karsten Dambekalns <karsten@typo3.org>
|
||
* @api
|
||
*/
|
||
public function findIdentifiersByTag($tag) {
|
||
if (!$this->cache instanceof t3lib_cache_frontend_Frontend) {
|
||
throw new t3lib_cache_Exception(
|
||
'Yet no cache frontend has been set via setCache().',
|
||
1204111376
|
||
);
|
||
}
|
||
public function findIdentifiersByTag($searchedTag) {
|
||
$entryIdentifiers = array();
|
||
$now = $GLOBALS['EXEC_TIME'];
|
||
for ($directoryIterator = t3lib_div::makeInstance('DirectoryIterator', $this->root . $this->cacheDirectory); $directoryIterator->valid(); $directoryIterator->next()) {
|
||
if ($directoryIterator->isDot()) {
|
||
continue;
|
||
}
|
||
$cacheEntryPathAndFilename = $directoryIterator->getPathname();
|
||
$index = (integer)file_get_contents($cacheEntryPathAndFilename, NULL, NULL, filesize($cacheEntryPathAndFilename) - self::DATASIZE_DIGITS, self::DATASIZE_DIGITS);
|
||
$metaData = file_get_contents($cacheEntryPathAndFilename, NULL, NULL, $index);
|
||
$path = $this->root . $this->cacheDirectory . 'tags/';
|
||
$pattern = $path . $tag . '/' . $this->cacheIdentifier . self::SEPARATOR . '*';
|
||
$filesFound = glob($pattern);
|
||
if ($filesFound === FALSE || count($filesFound) === 0) {
|
||
return array();
|
||
}
|
||
$cacheEntries = array();
|
||
foreach ($filesFound as $filename) {
|
||
list(,$entryIdentifier) = explode(self::SEPARATOR, basename($filename));
|
||
if ($this->has($entryIdentifier)) {
|
||
$cacheEntries[$entryIdentifier] = $entryIdentifier;
|
||
$expiryTime = (integer)substr($metaData, 0, self::EXPIRYTIME_LENGTH);
|
||
if ($expiryTime !== 0 && $expiryTime < $now) {
|
||
continue;
|
||
}
|
||
if (in_array($searchedTag, explode(' ', substr($metaData, self::EXPIRYTIME_LENGTH, -self::DATASIZE_DIGITS)))) {
|
||
$entryIdentifiers[] = $directoryIterator->getFilename();
|
||
}
|
||
}
|
||
return array_values($cacheEntries);
|
||
return $entryIdentifiers;
|
||
}
|
||
/**
|
||
* Finds and returns all cache entry identifiers which are tagged by the
|
||
* specified tags.
|
||
*
|
||
* @param array Array of tags to search for
|
||
* @param array $searchedTags Array of tags to search for
|
||
* @return array An array with identifiers of all matching entries. An empty array if no entries matched
|
||
* @author Ingo Renner <ingo@typo3.org>
|
||
* @author Christian Kuhn <lolli@schwarzbu.ch>
|
||
* @api
|
||
*/
|
||
public function findIdentifiersByTags(array $tags) {
|
||
$taggedEntries = array();
|
||
$foundEntries = array();
|
||
public function findIdentifiersByTags(array $searchedTags) {
|
||
$entryIdentifiers = array();
|
||
for ($directoryIterator = t3lib_div::makeInstance('DirectoryIterator', $this->root . $this->cacheDirectory); $directoryIterator->valid(); $directoryIterator->next()) {
|
||
if ($directoryIterator->isDot()) {
|
||
continue;
|
||
}
|
||
$cacheEntryPathAndFilename = $directoryIterator->getPathname();
|
||
$index = (integer)file_get_contents($cacheEntryPathAndFilename, NULL, NULL, filesize($cacheEntryPathAndFilename) - self::DATASIZE_DIGITS, self::DATASIZE_DIGITS);
|
||
$metaData = file_get_contents($cacheEntryPathAndFilename, NULL, NULL, $index);
|
||
foreach ($tags as $tag) {
|