diff --git a/NEWS b/NEWS index 70e721c2..11b3936a 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier ========================== 2.1.4, unknown release date +! DefinitionCacheFactory now can register new implementations - Colors missing # but in hex form will be corrected - CSS Number algorithm improved diff --git a/library/HTMLPurifier/DefinitionCache.php b/library/HTMLPurifier/DefinitionCache.php index d4c9d239..5b14fdfe 100644 --- a/library/HTMLPurifier/DefinitionCache.php +++ b/library/HTMLPurifier/DefinitionCache.php @@ -120,6 +120,9 @@ class HTMLPurifier_DefinitionCache /** * Clears all expired (older version or revision) objects from cache + * @note Be carefuly implementing this method as flush. Flush must + * not interfere with other Definition types, and cleanup() + * should not be repeatedly called by userland code. */ function cleanup($config) { trigger_error('Cannot call abstract method', E_USER_ERROR); diff --git a/library/HTMLPurifier/DefinitionCacheFactory.php b/library/HTMLPurifier/DefinitionCacheFactory.php index acc66182..dead92a3 100644 --- a/library/HTMLPurifier/DefinitionCacheFactory.php +++ b/library/HTMLPurifier/DefinitionCacheFactory.php @@ -1,6 +1,7 @@ array()); + var $implementations = array(); var $decorators = array(); /** @@ -51,14 +49,21 @@ class HTMLPurifier_DefinitionCacheFactory return $instance; } + /** + * Registers a new definition cache object + * @param $short Short name of cache object, for reference + * @param $long Full class name of cache object, for construction + */ + function register($short, $long) { + $this->implementations[$short] = $long; + } + /** * Factory method that creates a cache object based on configuration * @param $name Name of definitions handled by cache * @param $config Instance of HTMLPurifier_Config */ function &create($type, $config) { - // only one implementation as for right now, $config will - // be used to determine implementation $method = $config->get('Cache', 'DefinitionImpl'); if ($method === null) { $null = new HTMLPurifier_DefinitionCache_Null($type); @@ -67,7 +72,17 @@ class HTMLPurifier_DefinitionCacheFactory if (!empty($this->caches[$method][$type])) { return $this->caches[$method][$type]; } - $cache = new HTMLPurifier_DefinitionCache_Serializer($type); + if ( + isset($this->implementations[$method]) && + class_exists($class = $this->implementations[$method]) + ) { + $cache = new $class($type); + } else { + if ($method != 'Serializer') { + trigger_error("Unrecognized DefinitionCache $method, using Serializer instead", E_USER_WARNING); + } + $cache = new HTMLPurifier_DefinitionCache_Serializer($type); + } foreach ($this->decorators as $decorator) { $new_cache = $decorator->decorate($cache); // prevent infinite recursion in PHP 4 diff --git a/tests/HTMLPurifier/DefinitionCacheFactoryTest.php b/tests/HTMLPurifier/DefinitionCacheFactoryTest.php index a2768d7b..4bc097cf 100644 --- a/tests/HTMLPurifier/DefinitionCacheFactoryTest.php +++ b/tests/HTMLPurifier/DefinitionCacheFactoryTest.php @@ -5,13 +5,14 @@ require_once 'HTMLPurifier/DefinitionCacheFactory.php'; class HTMLPurifier_DefinitionCacheFactoryTest extends HTMLPurifier_Harness { - var $newFactory; + var $factory; var $oldFactory; function setup() { - $new = new HTMLPurifier_DefinitionCacheFactory(); + parent::setup(); + $this->factory = new HTMLPurifier_DefinitionCacheFactory(); $this->oldFactory = HTMLPurifier_DefinitionCacheFactory::instance(); - HTMLPurifier_DefinitionCacheFactory::instance($new); + HTMLPurifier_DefinitionCacheFactory::instance($this->factory); } function teardown() { @@ -19,46 +20,52 @@ class HTMLPurifier_DefinitionCacheFactoryTest extends HTMLPurifier_Harness } function test_create() { - $config = HTMLPurifier_Config::createDefault(); - $factory = HTMLPurifier_DefinitionCacheFactory::instance(); - $cache = $factory->create('Test', $config); + $cache = $this->factory->create('Test', $this->config); $this->assertEqual($cache, new HTMLPurifier_DefinitionCache_Serializer('Test')); } function test_create_withDecorator() { - $config = HTMLPurifier_Config::createDefault(); - $factory =& HTMLPurifier_DefinitionCacheFactory::instance(); - $factory->addDecorator('Memory'); - $cache =& $factory->create('Test', $config); + $this->factory->addDecorator('Memory'); + $cache = $this->factory->create('Test', $this->config); $cache_real = new HTMLPurifier_DefinitionCache_Decorator_Memory(); $cache_real = $cache_real->decorate(new HTMLPurifier_DefinitionCache_Serializer('Test')); $this->assertEqual($cache, $cache_real); } function test_create_withDecoratorObject() { - $config = HTMLPurifier_Config::createDefault(); - $factory =& HTMLPurifier_DefinitionCacheFactory::instance(); - $factory->addDecorator(new HTMLPurifier_DefinitionCache_Decorator_Memory()); - $cache =& $factory->create('Test', $config); + $this->factory->addDecorator(new HTMLPurifier_DefinitionCache_Decorator_Memory()); + $cache = $this->factory->create('Test', $this->config); $cache_real = new HTMLPurifier_DefinitionCache_Decorator_Memory(); $cache_real = $cache_real->decorate(new HTMLPurifier_DefinitionCache_Serializer('Test')); $this->assertEqual($cache, $cache_real); } function test_create_recycling() { - $config = HTMLPurifier_Config::createDefault(); - $factory =& HTMLPurifier_DefinitionCacheFactory::instance(); - $cache =& $factory->create('Test', $config); - $cache2 =& $factory->create('Test', $config); + $cache =& $this->factory->create('Test', $this->config); + $cache2 =& $this->factory->create('Test', $this->config); $this->assertReference($cache, $cache2); } + function test_create_invalid() { + $this->config->set('Core', 'DefinitionCache', 'Invalid'); + $this->expectError('Unrecognized DefinitionCache Invalid, using Serializer instead'); + $cache = $this->factory->create('Test', $this->config); + $this->assertIsA($cache, 'HTMLPurifier_DefinitionCache_Serializer'); + } + function test_null() { - $config = HTMLPurifier_Config::create(array('Core.DefinitionCache' => null)); - $factory =& HTMLPurifier_DefinitionCacheFactory::instance(); - $cache =& $factory->create('Test', $config); + $this->config->set('Core', 'DefinitionCache', null); + $cache = $this->factory->create('Test', $this->config); $this->assertEqual($cache, new HTMLPurifier_DefinitionCache_Null('Test')); } + function test_register() { + generate_mock_once('HTMLPurifier_DefinitionCache'); + $this->config->set('Core', 'DefinitionCache', 'TestCache'); + $this->factory->register('TestCache', $class = 'HTMLPurifier_DefinitionCacheMock'); + $cache = $this->factory->create('Test', $this->config); + $this->assertIsA($cache, $class); + } + }