0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-03-23 14:27:02 +00:00

Convert HTMLPurifier_Config to use property list backend.

Signed-off-by: Edward Z. Yang <edwardzyang@thewritingpot.com>
This commit is contained in:
Edward Z. Yang 2009-02-02 18:42:23 -05:00
parent b31f280d41
commit b9094d5ec8
6 changed files with 71 additions and 36 deletions

1
NEWS
View File

@ -28,6 +28,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
tested on Linux. tested on Linux.
. Removed trailing whitespace from all text files, see . Removed trailing whitespace from all text files, see
remote-trailing-whitespace.php maintenance script. remote-trailing-whitespace.php maintenance script.
. Convert configuration to use property list backend.
3.2.0, released 2008-10-31 3.2.0, released 2008-10-31
# Using %Core.CollectErrors forces line number/column tracking on, whereas # Using %Core.CollectErrors forces line number/column tracking on, whereas

View File

@ -41,11 +41,6 @@ class HTMLPurifier_Config
*/ */
protected $serial; protected $serial;
/**
* Two-level associative array of configuration directives
*/
protected $conf;
/** /**
* Parser for variables * Parser for variables
*/ */
@ -68,13 +63,18 @@ class HTMLPurifier_Config
*/ */
protected $finalized = false; protected $finalized = false;
/**
* Property list containing configuration directives.
*/
protected $plist;
/** /**
* @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) {
$this->conf = $definition->defaults; // set up, copy in defaults $this->plist = new HTMLPurifier_PropertyList($definition->defaultPlist);
$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();
} }
@ -118,7 +118,7 @@ class HTMLPurifier_Config
* @param $key String key * @param $key String key
*/ */
public function get($namespace, $key) { public function get($namespace, $key) {
if (!$this->finalized && $this->autoFinalize) $this->finalize(); if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
if (!isset($this->def->info[$namespace][$key])) { if (!isset($this->def->info[$namespace][$key])) {
// can't add % due to SimpleTest bug // can't add % due to SimpleTest bug
trigger_error('Cannot retrieve value of undefined directive ' . htmlspecialchars("$namespace.$key"), trigger_error('Cannot retrieve value of undefined directive ' . htmlspecialchars("$namespace.$key"),
@ -131,7 +131,7 @@ class HTMLPurifier_Config
E_USER_ERROR); E_USER_ERROR);
return; return;
} }
return $this->conf[$namespace][$key]; return $this->plist->get("$namespace.$key");
} }
/** /**
@ -139,13 +139,14 @@ 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(); if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
if (!isset($this->def->info[$namespace])) { if (!isset($this->def->info[$namespace])) {
trigger_error('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace), trigger_error('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace),
E_USER_WARNING); E_USER_WARNING);
return; return;
} }
return $this->conf[$namespace]; $full = $this->getAll();
return $full[$namespace];
} }
/** /**
@ -179,8 +180,13 @@ 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(); if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
return $this->conf; $ret = array();
foreach ($this->plist->squash() as $name => $value) {
list($ns, $key) = explode('.', $name, 2);
$ret[$ns][$key] = $value;
}
return $ret;
} }
/** /**
@ -240,7 +246,7 @@ class HTMLPurifier_Config
return; return;
} }
} }
$this->conf[$namespace][$key] = $value; $this->plist->set("$namespace.$key", $value);
// reset definitions if the directives they depend on changed // reset definitions if the directives they depend on changed
// this is a very costly process, so it's discouraged // this is a very costly process, so it's discouraged
@ -285,7 +291,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(); if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true);
$factory = HTMLPurifier_DefinitionCacheFactory::instance(); $factory = HTMLPurifier_DefinitionCacheFactory::instance();
$cache = $factory->create($type, $this); $cache = $factory->create($type, $this);
if (!$raw) { if (!$raw) {

View File

@ -11,6 +11,11 @@ class HTMLPurifier_ConfigSchema {
*/ */
public $defaults = array(); public $defaults = array();
/**
* The default property list. Do not edit this property list.
*/
public $defaultPlist;
/** /**
* Definition of the directives. The structure of this is: * Definition of the directives. The structure of this is:
* *
@ -47,6 +52,10 @@ class HTMLPurifier_ConfigSchema {
*/ */
static protected $singleton; static protected $singleton;
public function __construct() {
$this->defaultPlist = new HTMLPurifier_PropertyList();
}
/** /**
* Unserializes the default ConfigSchema. * Unserializes the default ConfigSchema.
*/ */
@ -84,6 +93,7 @@ class HTMLPurifier_ConfigSchema {
if ($allow_null) $obj->allow_null = true; if ($allow_null) $obj->allow_null = true;
$this->info[$namespace][$name] = $obj; $this->info[$namespace][$name] = $obj;
$this->defaults[$namespace][$name] = $default; $this->defaults[$namespace][$name] = $default;
$this->defaultPlist->set("$namespace.$name", $default);
} }
/** /**

View File

@ -15,11 +15,18 @@ class HTMLPurifier_PropertyList
*/ */
protected $parent; protected $parent;
protected $cache;
public function __construct($parent = null) {
$this->parent = $parent;
}
/** /**
* Recursively retrieves the value for a key * Recursively retrieves the value for a key
*/ */
public function get($name) { public function get($name) {
if ($this->has($name)) return $this->data[$name]; if ($this->has($name)) return $this->data[$name];
// possible performance bottleneck, convert to iterative if necessary
if ($this->parent) return $this->parent->get($name); if ($this->parent) return $this->parent->get($name);
throw new HTMLPurifier_Exception("Key '$name' not found"); throw new HTMLPurifier_Exception("Key '$name' not found");
} }
@ -48,12 +55,17 @@ class HTMLPurifier_PropertyList
} }
/** /**
* Returns an iterator for traversing this array, optionally filtering * Squashes this property list and all of its property lists into a single
* for a certain prefix. * array, and returns the array. This value is cached by default.
* @param $force If true, ignores the cache and regenerates the array.
*/ */
public function getIterator($filter = null) { public function squash($force = false) {
$a = new ArrayObject($this->data); if ($this->cache !== null && !$force) return $this->cache;
return new HTMLPurifier_PropertyListIterator($a->getIterator(), $filter); if ($this->parent) {
return $this->cache = array_merge($this->parent->squash($force), $this->data);
} else {
return $this->cache = $this->data;
}
} }
/** /**

View File

@ -65,23 +65,29 @@ class HTMLPurifier_PropertyListTest extends UnitTestCase
$this->assertIdentical($plist->has('key3'), false); $this->assertIdentical($plist->has('key3'), false);
} }
function testIterator() { function testSquash() {
$plist = new HTMLPurifier_PropertyList(); $parent = new HTMLPurifier_PropertyList();
$plist->set('nkey1', 'v'); $parent->set('key1', 'hidden');
$plist->set('nkey2', 'v'); $parent->set('key2', 2);
$plist->set('rkey3', 'v'); $plist = new HTMLPurifier_PropertyList($parent);
$a = array(); $plist->set('key1', 1);
foreach ($plist->getIterator() as $key => $value) { $plist->set('key3', 3);
$a[$key] = $value; $this->assertIdentical(
} $plist->squash(),
$this->assertIdentical($a, array('nkey1' => 'v', 'nkey2' => 'v', 'rkey3' => 'v')); array('key1' => 1, 'key2' => 2, 'key3' => 3)
$a = array(); );
foreach ($plist->getIterator('nkey') as $key => $value) { // updates don't show up...
$a[$key] = $value; $plist->set('key2', 22);
} $this->assertIdentical(
$this->assertIdentical($a, array('nkey1' => 'v', 'nkey2' => 'v')); $plist->squash(),
array('key1' => 1, 'key2' => 2, 'key3' => 3)
);
// until you force
$this->assertIdentical(
$plist->squash(true),
array('key1' => 1, 'key2' => 22, 'key3' => 3)
);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4