Index: t3lib/stddb/tables.sql =================================================================== --- t3lib/stddb/tables.sql (revision 5769) +++ t3lib/stddb/tables.sql (working copy) @@ -188,6 +188,17 @@ ); # +# Table structure for table 'sys_registry' +# +CREATE TABLE sys_registry ( + uid int(11) unsigned NOT NULL auto_increment, + entry_key varchar(128) DEFAULT '' NOT NULL, + entry_value longtext, + PRIMARY KEY (uid), + UNIQUE KEY entry_key (entry_key) +); + +# # Table structure for table 'sys_be_shortcuts' # CREATE TABLE sys_be_shortcuts ( Index: t3lib/core_autoload.php =================================================================== --- t3lib/core_autoload.php (revision 5769) +++ t3lib/core_autoload.php (working copy) @@ -47,6 +47,7 @@ 't3lib_readmail' => PATH_t3lib . 'class.t3lib_readmail.php', 't3lib_recordlist' => PATH_t3lib . 'class.t3lib_recordlist.php', 't3lib_refindex' => PATH_t3lib . 'class.t3lib_refindex.php', + 't3lib_registry' => PATH_t3lib . 'class.t3lib_registry.php', 't3lib_rteapi' => PATH_t3lib . 'class.t3lib_rteapi.php', 't3lib_scbase' => PATH_t3lib . 'class.t3lib_scbase.php', 't3lib_softrefproc' => PATH_t3lib . 'class.t3lib_softrefproc.php', Index: t3lib/class.t3lib_registry.php =================================================================== --- t3lib/class.t3lib_registry.php (revision 0) +++ t3lib/class.t3lib_registry.php (revision 0) @@ -0,0 +1,150 @@ + +* +* 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 class to store and retrieve entries in a registry database table. + * Credits: Heavily inspired by Drupal's variable_*() functions. + * + * @author Ingo Renner + * @package TYPO3 + * @subpackage t3lib + */ +class t3lib_Registry implements t3lib_Singleton { + + protected $entries = array(); + + /** + * Load the persistent registry table. + * + * The registry table is composed of values that have been saved in the table + * with set(). + */ + public function __construct() { + $entries = array(); + + // TODO might add caching like Drupal does + + $storedEntries = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( + '*', + 'sys_registry', + '' + ); + + foreach ($storedEntries as $storedEntry) { + $entries[$storedEntry['entry_key']] = unserialize($storedEntry['entry_value']); + } + + $this->entries = $entries; + } + + /** + * Returns a persistent entry. + * + * @param string The key of the entry to return. + * @param mixed The default value to use if this entry has never been set. + * @return mixed The value of the entry. + */ + public function get($key, $defaultValue) { + return isset($this->entries[$key]) ? $this->entries[$key] : $defaultValue; + } + + /** + * Sets a persistent entry. + * + * @param string The key of the entry to set. Must be namespaced by prepending the key with the extension key for extensions or 'core' for core registry entries. Example: tx_myext.my.entry + * @param mixed The value to set. This can be any PHP data type; this class takes care of serialization as necessary. + * @throws InvalidArgumentException Throws an exception if the entry key is not prefixed with a namespace + */ + public function set($key, $value) { + $allowedNamespacePrefixes = array('core', 'tx_', 'user_'); + $keyIsProperlyPrefixed = false; + + // checking for proper namespacing + foreach ($allowedNamespacePrefixes as $prefix) { + if (t3lib_div::isFirstPartOfStr($key, $prefix)) { + $keyIsProperlyPrefixed = true; + break; + } + } + if (!$keyIsProperlyPrefixed) { + throw new InvalidArgumentException( + 'Key "' . $key . '" was not properly prefixed with either of "' + . implode('", "', $allowedNamespacePrefixes) . '".', + 1249755131 + ); + } + if (strpos($key, '.') === false) { + throw new InvalidArgumentException( + 'Key "' . $key . '" was not properly namespaced. A "." was not found, which should be used for namespacing.', + 1249755545 + ); + } + + $serializedValue = serialize($value); + + $GLOBALS['TYPO3_DB']->exec_UPDATEquery( + 'sys_registry', + 'entry_key = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($key, 'sys_registry'), + array('entry_value' => $serializedValue) + ); + + if (!$GLOBALS['TYPO3_DB']->sql_affected_rows()) { + $GLOBALS['TYPO3_DB']->exec_INSERTquery( + 'sys_registry', + array( + 'entry_key' => $key, + 'entry_value' => $serializedValue + ) + ); + } + + $this->entries[$key] = $value; + } + + /** + * Unsets a persistent entry. + * + * @param string The key of the entry to unset. + */ + public function remove($key) { + $GLOBALS['TYPO3_DB']->exec_DELETEquery( + 'sys_registry', + 'entry_key = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($key, 'sys_registry') + ); + + unset($this->entries[$key]); + } +} + + +if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_registry.php']) { + include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_registry.php']); +} + +?> \ No newline at end of file Index: tests/t3lib/t3lib_registry_testcase.php =================================================================== --- tests/t3lib/t3lib_registry_testcase.php (revision 0) +++ tests/t3lib/t3lib_registry_testcase.php (revision 0) @@ -0,0 +1,258 @@ + +* 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 class t3lib_Regsitry + * + * @author Ingo Renner + * @package TYPO3 + * @subpackage t3lib + */ +class t3lib_Registry_testcase extends tx_phpunit_testcase { + + protected $registry = null; + + /** + * Sets up this testcase + * + * @return void + * @author Ingo Renner + */ + public function setUp() { + for ($i = 0; $i < 5; $i++) { + $GLOBALS['TYPO3_DB']->exec_INSERTquery( + 'sys_registry', + array( + 'entry_key' => 'tx_phpunit.t3lib_Registry_testcase.testData.' . $i, + 'entry_value' => serialize('testData' . $i) + ) + ); + } + + $this->registry = t3lib_div::makeInstance('t3lib_Registry'); + } + + /** + * Tears down this testcase + * + * @author Ingo Renner + */ + public function tearDown() { + $keys = array(0, 1, 2, 3, 4, 'setReallySavesTheGivenValueToTheDatabase', 'setReallySavesTheGivenValue', 'getRetrievesTheCorrectEntry'); + + foreach ($keys as $key) { + $GLOBALS['TYPO3_DB']->exec_DELETEquery( + 'sys_registry', + 'entry_key = \'tx_phpunit.t3lib_Registry_testcase.testData.' . $key . '\'' + ); + } + } + + /** + * @test + * @author Ingo Renner + */ + public function theConstructorLoadsAllAvailableEntries() { + for ($i = 0; $i < 5; $i++) { + $key = 'tx_phpunit.t3lib_Registry_testcase.testData.' . $i; + $this->assertEquals( + $this->registry->get($key, false), + 'testData' . $i, + 'The actual data for ' . $key . ' did not match the expected data.' + ); + } + } + + /** + * @test + * @author Ingo Renner + */ + public function setReallySavesTheGivenValueToTheDatabase() { + $this->registry->set( + 'tx_phpunit.t3lib_Registry_testcase.testData.setReallySavesTheGivenValueToTheDatabase', + 'setReallySavesTheGivenValueToTheDatabase' + ); + + $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( + '*', + 'sys_registry', + 'entry_key = \'tx_phpunit.t3lib_Registry_testcase.testData.setReallySavesTheGivenValueToTheDatabase\'' + ); + + $this->assertEquals( + $rows[0]['entry_value'], + serialize('setReallySavesTheGivenValueToTheDatabase'), + 'The actual data did not match the expected data.' + ); + } + + /** + * @test + * @expectedException InvalidArgumentException + * @author Ingo Renner + */ + public function setThrowsAnExceptionOnWrongNamespacePrefix() { + $this->registry->set( + 'WrongPrefix_tx_phpunit.t3lib_Registry_testcase.testData.setThrowsAnExceptionOnWrongNamespacePrefix', + 'testValue' + ); + } + + /** + * @test + * @expectedException InvalidArgumentException + * @author Ingo Renner + */ + public function setThrowsAnExceptionOnMissingNamespacing() { + $this->registry->set( + 'tx_phpunit_setThrowsAnExceptionOnMissingNamespacing', + 'testValue' + ); + } + + + /** + * @test + * @author Ingo Renner + */ + public function setReallySavesTheGivenValue() { + $testValue = 'setReallySavesTheGivenValue'; + + $this->registry->set( + 'tx_phpunit.t3lib_Registry_testcase.testData.setReallySavesTheGivenValue', + $testValue + ); + + $this->assertEquals( + $this->registry->get('tx_phpunit.t3lib_Registry_testcase.testData.setReallySavesTheGivenValue', false), + $testValue, + 'The actual data did not match the expected data.' + ); + } + + /** + * @test + * @author Ingo Renner + */ + public function getRetrievesTheCorrectEntry() { + $testValue = 'getRetrievesTheCorrectEntry'; + + $this->registry->set( + 'tx_phpunit.t3lib_Registry_testcase.testData.getRetrievesTheCorrectEntry', + $testValue + ); + + $this->assertEquals( + $this->registry->get('tx_phpunit.t3lib_Registry_testcase.testData.getRetrievesTheCorrectEntry', false), + $testValue, + 'The actual data did not match the expected data.' + ); + } + + /** + * @test + * @author Ingo Renner + */ + public function getReturnsTheDefaultValueIfTheRequestedKeyWasNotFound() { + $defaultValue = 'getReturnsTheDefaultValueIfTheRequestedKeyWasNotFound'; + + $this->assertEquals( + $defaultValue, + $this->registry->get('tx_phpunit.t3lib_Registry_testcase.testData.getReturnsTheDefaultValueIfTheRequestedKeyWasNotFound', $defaultValue), + 'A value other than the default value was returned.' + ); + } + + /** + * @test + * @author Ingo Renner + */ + public function removeReallyRemovesTheEntryFromTheDatabase() { + $testValue = 'removeReallyRemovesTheEntryFromTheDatabase'; + + $this->registry->set( + 'tx_phpunit.t3lib_Registry_testcase.testData.removeReallyRemovesTheEntryFromTheDatabase', + $testValue + ); + $this->registry->remove('tx_phpunit.t3lib_Registry_testcase.testData.removeReallyRemovesTheEntryFromTheDatabase'); + + $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( + '*', + 'sys_registry', + 'entry_key = \'tx_phpunit.t3lib_Registry_testcase.testData.removeReallyRemovesTheEntryFromTheDatabase\'' + ); + + $this->assertEquals( + 0, + count($rows), + 'At least one entry was found while none where expected.' + ); + } + + /** + * @test + * @author Ingo Renner + */ + public function removeReallyRemovesTheEntry() { + $testValue = 'removeReallyRemovesTheEntry'; + $expectedValue = 'expectedValue'; + + $this->registry->set( + 'tx_phpunit.t3lib_Registry_testcase.testData.removeReallyRemovesTheEntry', + $testValue + ); + $this->registry->remove('tx_phpunit.t3lib_Registry_testcase.testData.removeReallyRemovesTheEntry'); + + $this->assertEquals( + $expectedValue, + // should return the default value now instead of the value set in the first place + $this->registry->get('tx_phpunit.t3lib_Registry_testcase.testData.removeReallyRemovesTheEntry', $expectedValue), + 'A value other than the default value was returned, thus the entry was still present.' + ); + } + + /** + * @test + * @author Ingo Renner + */ + public function getCanNotRetrieveAnEntryAfterRemovingIt() { + $testValue = 'getCanNotRetrieveAnEntryAfterRemovingIt'; + + $this->registry->set( + 'tx_phpunit.t3lib_Registry_testcase.testData.getCanNotRetrieveAnEntryAfterRemovingIt', + $testValue + ); + $this->registry->remove('tx_phpunit.t3lib_Registry_testcase.testData.getCanNotRetrieveAnEntryAfterRemovingIt'); + + $this->assertNotEquals( + $testValue, + // should return the default value now instead of the value set in the first place + $this->registry->get('tx_phpunit.t3lib_Registry_testcase.testData.getCanNotRetrieveAnEntryAfterRemovingIt', 'defaultValue'), + 'The initial value was returned.' + ); + } +} + +?> \ No newline at end of file