0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-12-22 16:31:53 +00:00

Implement configuration inheritance.

Signed-off-by: Edward Z. Yang <edwardzyang@thewritingpot.com>
This commit is contained in:
Edward Z. Yang 2009-02-20 00:13:09 -05:00
parent 86ca784da3
commit eaa906f8fc
4 changed files with 39 additions and 12 deletions

3
NEWS
View File

@ -14,6 +14,9 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
docs/dev-config-bcbreaks.txt for details; in essence, anything that docs/dev-config-bcbreaks.txt for details; in essence, anything that
had both namespace and directive now have a single unified key. had both namespace and directive now have a single unified key.
! More robust support for name="" and id="" ! More robust support for name="" and id=""
! HTMLPurifier_Config::inherit($config) allows you to inherit one
configuration, and have changes to that configuration be propagated
to all of its children.
3.3.0, released 2009-02-16 3.3.0, released 2009-02-16
! Implement CSS property 'overflow' when %CSS.AllowTricky is true. ! Implement CSS property 'overflow' when %CSS.AllowTricky is true.

2
TODO
View File

@ -14,8 +14,6 @@ afraid to cast your vote for the next feature to be implemented!
- Investigate how early internal structures can be accessed; this would - Investigate how early internal structures can be accessed; this would
prevent structures from being parsed and serialized multiple times. prevent structures from being parsed and serialized multiple times.
- Built-in support for target="_blank" on all external links - Built-in support for target="_blank" on all external links
- Convert configuration to allow an arbitrary number of namespaces;
then rename as appropriate.
FUTURE VERSIONS FUTURE VERSIONS
--------------- ---------------

View File

@ -84,8 +84,9 @@ class HTMLPurifier_Config
* @param $definition HTMLPurifier_ConfigSchema that defines what directives * @param $definition HTMLPurifier_ConfigSchema that defines what directives
* are allowed. * are allowed.
*/ */
public function __construct($definition) { public function __construct($definition, $parent = null) {
$this->plist = new HTMLPurifier_PropertyList($definition->defaultPlist); $parent = $parent ? $parent : $definition->defaultPlist;
$this->plist = new HTMLPurifier_PropertyList($parent);
$this->def = $definition; // keep a copy around for checking $this->def = $definition; // keep a copy around for checking
$this->parser = new HTMLPurifier_VarParser_Flexible(); $this->parser = new HTMLPurifier_VarParser_Flexible();
} }
@ -114,6 +115,16 @@ class HTMLPurifier_Config
return $ret; return $ret;
} }
/**
* Creates a new config object that inherits from a previous one.
* @param HTMLPurifier_Config $config Configuration object to inherit
* from.
* @return HTMLPurifier_Config object with $config as its parent.
*/
public static function inherit(HTMLPurifier_Config $config) {
return new HTMLPurifier_Config($config->def, $config->plist);
}
/** /**
* Convenience constructor that creates a default configuration object. * Convenience constructor that creates a default configuration object.
* @return Default HTMLPurifier_Config object. * @return Default HTMLPurifier_Config object.
@ -126,7 +137,6 @@ class HTMLPurifier_Config
/** /**
* Retreives a value from the configuration. * Retreives a value from the configuration.
* @param $namespace String namespace
* @param $key String key * @param $key String key
*/ */
public function get($key, $a = null) { public function get($key, $a = null) {
@ -134,7 +144,7 @@ class HTMLPurifier_Config
$this->triggerError("Using deprecated API: use \$config->get('$key.$a') instead", E_USER_WARNING); $this->triggerError("Using deprecated API: use \$config->get('$key.$a') instead", E_USER_WARNING);
$key = "$key.$a"; $key = "$key.$a";
} }
if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); if (!$this->finalized) $this->autoFinalize();
if (!isset($this->def->info[$key])) { if (!isset($this->def->info[$key])) {
// can't add % due to SimpleTest bug // can't add % due to SimpleTest bug
$this->triggerError('Cannot retrieve value of undefined directive ' . htmlspecialchars($key), $this->triggerError('Cannot retrieve value of undefined directive ' . htmlspecialchars($key),
@ -155,7 +165,7 @@ class HTMLPurifier_Config
* @param $namespace String namespace * @param $namespace String namespace
*/ */
public function getBatch($namespace) { public function getBatch($namespace) {
if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); if (!$this->finalized) $this->autoFinalize();
$full = $this->getAll(); $full = $this->getAll();
if (!isset($full[$namespace])) { if (!isset($full[$namespace])) {
$this->triggerError('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace), $this->triggerError('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace),
@ -196,7 +206,7 @@ class HTMLPurifier_Config
* Retrieves all directives, organized by namespace * Retrieves all directives, organized by namespace
*/ */
public function getAll() { public function getAll() {
if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); if (!$this->finalized) $this->autoFinalize();
$ret = array(); $ret = array();
foreach ($this->plist->squash() as $name => $value) { foreach ($this->plist->squash() as $name => $value) {
list($ns, $key) = explode('.', $name, 2); list($ns, $key) = explode('.', $name, 2);
@ -207,7 +217,6 @@ class HTMLPurifier_Config
/** /**
* Sets a value to configuration. * Sets a value to configuration.
* @param $namespace String namespace
* @param $key String key * @param $key String key
* @param $value Mixed value * @param $value Mixed value
*/ */
@ -316,7 +325,7 @@ class HTMLPurifier_Config
* @param $raw Whether or not definition should be returned raw * @param $raw Whether or not definition should be returned raw
*/ */
public function getDefinition($type, $raw = false) { public function getDefinition($type, $raw = false) {
if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); if (!$this->finalized) $this->autoFinalize();
$factory = HTMLPurifier_DefinitionCacheFactory::instance(); $factory = HTMLPurifier_DefinitionCacheFactory::instance();
$cache = $factory->create($type, $this); $cache = $factory->create($type, $this);
if (!$raw) { if (!$raw) {
@ -376,7 +385,6 @@ class HTMLPurifier_Config
foreach ($config_array as $key => $value) { foreach ($config_array as $key => $value) {
$key = str_replace('_', '.', $key); $key = str_replace('_', '.', $key);
if (strpos($key, '.') !== false) { if (strpos($key, '.') !== false) {
list($namespace, $directive) = explode(".", $key, 2);
$this->set($key, $value); $this->set($key, $value);
} else { } else {
$namespace = $key; $namespace = $key;
@ -505,7 +513,11 @@ class HTMLPurifier_Config
* already finalized * already finalized
*/ */
public function autoFinalize() { public function autoFinalize() {
if (!$this->finalized && $this->autoFinalize) $this->finalize(); if ($this->autoFinalize) {
$this->finalize();
} else {
$this->plist->squash(true);
}
} }
/** /**

View File

@ -437,6 +437,20 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
$this->expectError('Using deprecated API: use $config->get(\'Foo.Bar\') instead'); $this->expectError('Using deprecated API: use $config->get(\'Foo.Bar\') instead');
$this->assertIdentical($config->get('Foo', 'Bar'), 4); $this->assertIdentical($config->get('Foo', 'Bar'), 4);
} }
function testInherit() {
$this->schema->add('Phantom.Masked', 25, 'int', false);
$this->schema->add('Phantom.Unmasked', 89, 'int', false);
$this->schema->add('Phantom.Latemasked', 11, 'int', false);
$config = new HTMLPurifier_Config($this->schema);
$config->set('Phantom.Masked', 800);
$subconfig = HTMLPurifier_Config::inherit($config);
$config->set('Phantom.Latemasked', 100, 'int', false);
$this->assertIdentical($subconfig->get('Phantom.Masked'), 800);
$this->assertIdentical($subconfig->get('Phantom.Unmasked'), 89);
$this->assertIdentical($subconfig->get('Phantom.Latemasked'), 100);
}
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4