0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-01-03 05:11:52 +00:00

Generic implementation of property-lists.

Signed-off-by: Edward Z. Yang <edwardzyang@thewritingpot.com>
This commit is contained in:
Edward Z. Yang 2008-12-06 00:43:42 -05:00
parent 90110a4e3a
commit 3a6b63dff1
4 changed files with 188 additions and 0 deletions

1
NEWS
View File

@ -11,6 +11,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
3.3.0, unknown release date 3.3.0, unknown release date
! Implement CSS property 'overflow' when %CSS.AllowTricky is true. ! Implement CSS property 'overflow' when %CSS.AllowTricky is true.
! Implement generic property list classess
- Fix bug with testEncodingSupportsASCII() algorithm when iconv() implementation - Fix bug with testEncodingSupportsASCII() algorithm when iconv() implementation
does not do the "right thing" with characters not supported in the output does not do the "right thing" with characters not supported in the output
set. set.

View File

@ -0,0 +1,72 @@
<?php
/**
* Generic property list implementation
*/
class HTMLPurifier_PropertyList
{
/**
* Internal data-structure for properties
*/
protected $data = array();
/**
* Parent plist
*/
protected $parent;
/**
* Recursively retrieves the value for a key
*/
public function get($name) {
if ($this->has($name)) return $this->data[$name];
if ($this->parent) return $this->parent->get($name);
throw new HTMLPurifier_Exception("Key '$name' not found");
}
/**
* Sets the value of a key, for this plist
*/
public function set($name, $value) {
$this->data[$name] = $value;
}
/**
* Returns true if a given key exists
*/
public function has($name) {
return array_key_exists($name, $this->data);
}
/**
* Resets a value to the value of it's parent, usually the default. If
* no value is specified, the entire plist is reset.
*/
public function reset($name = null) {
if ($name == null) $this->data = array();
else unset($this->data[$name]);
}
/**
* Returns an iterator for traversing this array, optionally filtering
* for a certain prefix.
*/
public function getIterator($filter = null) {
$a = new ArrayObject($this->data);
return new HTMLPurifier_PropertyListIterator($a->getIterator(), $filter);
}
/**
* Returns the parent plist.
*/
public function getParent() {
return $this->parent;
}
/**
* Sets the parent plist.
*/
public function setParent($plist) {
$this->parent = $plist;
}
}

View File

@ -0,0 +1,30 @@
<?php
/**
* Property list iterator. Do not instantiate this class directly.
*/
class HTMLPurifier_PropertyListIterator extends FilterIterator
{
protected $l;
protected $filter;
/**
* @param $data Array of data to iterate over
* @param $filter Optional prefix to only allow values of
*/
public function __construct(Iterator $iterator, $filter = null) {
parent::__construct($iterator);
$this->l = strlen($filter);
$this->filter = $filter;
}
public function accept() {
$key = $this->getInnerIterator()->key();
if( strncmp($key, $this->filter, $this->l) !== 0 ) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,85 @@
<?php
class HTMLPurifier_PropertyListTest extends UnitTestCase
{
function testBasic() {
$plist = new HTMLPurifier_PropertyList();
$plist->set('key', 'value');
$this->assertIdentical($plist->get('key'), 'value');
}
function testNotFound() {
$this->expectException(new HTMLPurifier_Exception("Key 'key' not found"));
$plist = new HTMLPurifier_PropertyList();
$plist->get('key');
}
function testRecursion() {
$parent_plist = new HTMLPurifier_PropertyList();
$parent_plist->set('key', 'value');
$plist = new HTMLPurifier_PropertyList();
$plist->setParent($parent_plist);
$this->assertIdentical($plist->get('key'), 'value');
}
function testOverride() {
$parent_plist = new HTMLPurifier_PropertyList();
$parent_plist->set('key', 'value');
$plist = new HTMLPurifier_PropertyList();
$plist->setParent($parent_plist);
$plist->set('key', 'value2');
$this->assertIdentical($plist->get('key'), 'value2');
}
function testRecursionNotFound() {
$this->expectException(new HTMLPurifier_Exception("Key 'key' not found"));
$parent_plist = new HTMLPurifier_PropertyList();
$plist = new HTMLPurifier_PropertyList();
$plist->setParent($parent_plist);
$this->assertIdentical($plist->get('key'), 'value');
}
function testHas() {
$plist = new HTMLPurifier_PropertyList();
$this->assertIdentical($plist->has('key'), false);
$plist->set('key', 'value');
$this->assertIdentical($plist->has('key'), true);
}
function testReset() {
$plist = new HTMLPurifier_PropertyList();
$plist->set('key1', 'value');
$plist->set('key2', 'value');
$plist->set('key3', 'value');
$this->assertIdentical($plist->has('key1'), true);
$this->assertIdentical($plist->has('key2'), true);
$this->assertIdentical($plist->has('key3'), true);
$plist->reset('key2');
$this->assertIdentical($plist->has('key1'), true);
$this->assertIdentical($plist->has('key2'), false);
$this->assertIdentical($plist->has('key3'), true);
$plist->reset();
$this->assertIdentical($plist->has('key1'), false);
$this->assertIdentical($plist->has('key2'), false);
$this->assertIdentical($plist->has('key3'), false);
}
function testIterator() {
$plist = new HTMLPurifier_PropertyList();
$plist->set('nkey1', 'v');
$plist->set('nkey2', 'v');
$plist->set('rkey3', 'v');
$a = array();
foreach ($plist->getIterator() as $key => $value) {
$a[$key] = $value;
}
$this->assertIdentical($a, array('nkey1' => 'v', 'nkey2' => 'v', 'rkey3' => 'v'));
$a = array();
foreach ($plist->getIterator('nkey') as $key => $value) {
$a[$key] = $value;
}
$this->assertIdentical($a, array('nkey1' => 'v', 'nkey2' => 'v'));
}
}