mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-08-02 12:21:09 +02:00
[1.7.0] Refactor HTMLModule unit tests
- AttrCollections does not barf when an inclusion is not present - HTMLDefinition configuration directives now use new syntax - Added %HTML.AllowedModules and %HTML.CoreModules for testing - Extend Harness so that it can accept a default configuration object member variable - Refactor modules to use Scaffolding, which defines some custom attributes that allows for the easy testing of attribute collections git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1082 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
@@ -63,6 +63,7 @@ class HTMLPurifier_AttrCollections
|
|||||||
if (isset($seen[$merge[$i]])) continue;
|
if (isset($seen[$merge[$i]])) continue;
|
||||||
$seen[$merge[$i]] = true;
|
$seen[$merge[$i]] = true;
|
||||||
// foreach attribute of the inclusion, copy it over
|
// foreach attribute of the inclusion, copy it over
|
||||||
|
if (!isset($this->info[$merge[$i]])) continue;
|
||||||
foreach ($this->info[$merge[$i]] as $key => $value) {
|
foreach ($this->info[$merge[$i]] as $key => $value) {
|
||||||
if (isset($attr[$key])) continue; // also catches more inclusions
|
if (isset($attr[$key])) continue; // also catches more inclusions
|
||||||
$attr[$key] = $value;
|
$attr[$key] = $value;
|
||||||
|
@@ -7,48 +7,63 @@ require_once 'HTMLPurifier/HTMLModuleManager.php';
|
|||||||
// outside of the HTML or Attr namespaces
|
// outside of the HTML or Attr namespaces
|
||||||
|
|
||||||
HTMLPurifier_ConfigSchema::define(
|
HTMLPurifier_ConfigSchema::define(
|
||||||
'HTML', 'BlockWrapper', 'p', 'string',
|
'HTML', 'BlockWrapper', 'p', 'string', '
|
||||||
'String name of element to wrap inline elements that are inside a block '.
|
<p>
|
||||||
'context. This only occurs in the children of blockquote in strict mode. '.
|
String name of element to wrap inline elements that are inside a block
|
||||||
'Example: by default value, <code><blockquote>Foo</blockquote></code> '.
|
context. This only occurs in the children of blockquote in strict mode.
|
||||||
'would become <code><blockquote><p>Foo</p></blockquote></code>. The '.
|
</p>
|
||||||
'<code><p></code> tags can be replaced '.
|
<p>
|
||||||
'with whatever you desire, as long as it is a block level element. '.
|
Example: by default value,
|
||||||
'This directive has been available since 1.3.0.'
|
<code><blockquote>Foo</blockquote></code> would become
|
||||||
);
|
<code><blockquote><p>Foo</p></blockquote></code>.
|
||||||
|
The <code><p></code> tags can be replaced with whatever you desire,
|
||||||
|
as long as it is a block level element. This directive has been available
|
||||||
|
since 1.3.0.
|
||||||
|
</p>
|
||||||
|
');
|
||||||
|
|
||||||
HTMLPurifier_ConfigSchema::define(
|
HTMLPurifier_ConfigSchema::define(
|
||||||
'HTML', 'Parent', 'div', 'string',
|
'HTML', 'Parent', 'div', 'string', '
|
||||||
'String name of element that HTML fragment passed to library will be '.
|
<p>
|
||||||
'inserted in. An interesting variation would be using span as the '.
|
String name of element that HTML fragment passed to library will be
|
||||||
'parent element, meaning that only inline tags would be allowed. '.
|
inserted in. An interesting variation would be using span as the
|
||||||
'This directive has been available since 1.3.0.'
|
parent element, meaning that only inline tags would be allowed.
|
||||||
);
|
This directive has been available since 1.3.0.
|
||||||
|
</p>
|
||||||
|
');
|
||||||
|
|
||||||
HTMLPurifier_ConfigSchema::define(
|
HTMLPurifier_ConfigSchema::define(
|
||||||
'HTML', 'AllowedElements', null, 'lookup/null',
|
'HTML', 'AllowedElements', null, 'lookup/null', '
|
||||||
'If HTML Purifier\'s tag set is unsatisfactory for your needs, you '.
|
<p>
|
||||||
'can overload it with your own list of tags to allow. Note that this '.
|
If HTML Purifier\'s tag set is unsatisfactory for your needs, you
|
||||||
'method is subtractive: it does its job by taking away from HTML Purifier '.
|
can overload it with your own list of tags to allow. Note that this
|
||||||
'usual feature set, so you cannot add a tag that HTML Purifier never '.
|
method is subtractive: it does its job by taking away from HTML Purifier
|
||||||
'supported in the first place (like embed, form or head). If you change this, you '.
|
usual feature set, so you cannot add a tag that HTML Purifier never
|
||||||
'probably also want to change %HTML.AllowedAttributes. '.
|
supported in the first place (like embed, form or head). If you
|
||||||
'<strong>Warning:</strong> If another directive conflicts with the '.
|
change this, you probably also want to change %HTML.AllowedAttributes.
|
||||||
'elements here, <em>that</em> directive will win and override. '.
|
</p>
|
||||||
'This directive has been available since 1.3.0.'
|
<p>
|
||||||
);
|
<strong>Warning:</strong> If another directive conflicts with the
|
||||||
|
elements here, <em>that</em> directive will win and override.
|
||||||
|
This directive has been available since 1.3.0.
|
||||||
|
</p>
|
||||||
|
');
|
||||||
|
|
||||||
HTMLPurifier_ConfigSchema::define(
|
HTMLPurifier_ConfigSchema::define(
|
||||||
'HTML', 'AllowedAttributes', null, 'lookup/null',
|
'HTML', 'AllowedAttributes', null, 'lookup/null', '
|
||||||
'IF HTML Purifier\'s attribute set is unsatisfactory, overload it! '.
|
<p>
|
||||||
'The syntax is \'tag.attr\' or \'*.attr\' for the global attributes '.
|
If HTML Purifier\'s attribute set is unsatisfactory, overload it!
|
||||||
'(style, id, class, dir, lang, xml:lang).'.
|
The syntax is "tag.attr" or "*.attr" for the global attributes
|
||||||
'<strong>Warning:</strong> If another directive conflicts with the '.
|
(style, id, class, dir, lang, xml:lang).
|
||||||
'elements here, <em>that</em> directive will win and override. For '.
|
</p>
|
||||||
'example, %HTML.EnableAttrID will take precedence over *.id in this '.
|
<p>
|
||||||
'directive. You must set that directive to true before you can use '.
|
<strong>Warning:</strong> If another directive conflicts with the
|
||||||
'IDs at all. This directive has been available since 1.3.0.'
|
elements here, <em>that</em> directive will win and override. For
|
||||||
);
|
example, %HTML.EnableAttrID will take precedence over *.id in this
|
||||||
|
directive. You must set that directive to true before you can use
|
||||||
|
IDs at all. This directive has been available since 1.3.0.
|
||||||
|
</p>
|
||||||
|
');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Definition of the purified HTML that describes allowed children,
|
* Definition of the purified HTML that describes allowed children,
|
||||||
|
@@ -53,6 +53,43 @@ HTMLPurifier_ConfigSchema::define(
|
|||||||
'will be used. This directive has been available since 1.7.0.'
|
'will be used. This directive has been available since 1.7.0.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
HTMLPurifier_ConfigSchema::define(
|
||||||
|
'HTML', 'AllowedModules', null, 'lookup/null', '
|
||||||
|
<p>
|
||||||
|
A doctype comes with a set of usual modules to use. Without having
|
||||||
|
to mucking about with the doctypes, you can quickly activate or
|
||||||
|
disable these modules by specifying which modules you wish to allow
|
||||||
|
with this directive. This is most useful for unit testing specific
|
||||||
|
modules, although end users may find it useful for their own ends.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you specify a module that does not exist, the manager will silently
|
||||||
|
fail to use it, so be careful! User-defined modules are not affected
|
||||||
|
by this directive. Modules defined in %HTML.CoreModules are not
|
||||||
|
affected by this directive. This directive has been available since 1.7.0.
|
||||||
|
</p>
|
||||||
|
');
|
||||||
|
|
||||||
|
HTMLPurifier_ConfigSchema::define(
|
||||||
|
'HTML', 'CoreModules', array(
|
||||||
|
'Structure' => true,
|
||||||
|
'Text' => true,
|
||||||
|
'Hypertext' => true,
|
||||||
|
'List' => true,
|
||||||
|
'NonXMLCommonAttributes' => true,
|
||||||
|
'XMLCommonAttributes' => true,
|
||||||
|
'CommonAttributes' => true
|
||||||
|
), 'lookup', '
|
||||||
|
<p>
|
||||||
|
Certain modularized doctypes (XHTML, namely), have certain modules
|
||||||
|
that must be included for the doctype to be an conforming document
|
||||||
|
type: put those modules here. By default, XHTML\'s core modules
|
||||||
|
are used. You can set this to a blank array to disable core module
|
||||||
|
protection, but this is not recommended. This directive has been
|
||||||
|
available since 1.7.0.
|
||||||
|
</p>
|
||||||
|
');
|
||||||
|
|
||||||
class HTMLPurifier_HTMLModuleManager
|
class HTMLPurifier_HTMLModuleManager
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -254,6 +291,17 @@ class HTMLPurifier_HTMLModuleManager
|
|||||||
$doctype = $this->doctypes->make($config);
|
$doctype = $this->doctypes->make($config);
|
||||||
$modules = $doctype->modules;
|
$modules = $doctype->modules;
|
||||||
|
|
||||||
|
// take out the default modules that aren't allowed
|
||||||
|
$lookup = $config->get('HTML', 'AllowedModules');
|
||||||
|
$special_cases = $config->get('HTML', 'CoreModules');
|
||||||
|
|
||||||
|
if (is_array($lookup)) {
|
||||||
|
foreach ($modules as $k => $m) {
|
||||||
|
if (isset($special_cases[$m])) continue;
|
||||||
|
if (!isset($lookup[$m])) unset($modules[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// merge in custom modules
|
// merge in custom modules
|
||||||
$modules = array_merge($modules, $this->userModules);
|
$modules = array_merge($modules, $this->userModules);
|
||||||
|
|
||||||
@@ -291,7 +339,6 @@ class HTMLPurifier_HTMLModuleManager
|
|||||||
// the module in your custom doctype should be sufficient
|
// the module in your custom doctype should be sufficient
|
||||||
$this->modules
|
$this->modules
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -70,7 +70,7 @@ class HTMLPurifier_AttrCollectionsTest extends UnitTestCase
|
|||||||
$types = new HTMLPurifier_AttrTypesMock($this);
|
$types = new HTMLPurifier_AttrTypesMock($this);
|
||||||
$collections = new HTMLPurifier_AttrCollections($types, array());
|
$collections = new HTMLPurifier_AttrCollections($types, array());
|
||||||
$collections->info = array(
|
$collections->info = array(
|
||||||
'Core' => array(0 => array('Inclusion'), 'attr-original' => 'Type'),
|
'Core' => array(0 => array('Inclusion', 'Undefined'), 'attr-original' => 'Type'),
|
||||||
'Inclusion' => array(0 => array('SubInclusion'), 'attr' => 'Type'),
|
'Inclusion' => array(0 => array('SubInclusion'), 'attr' => 'Type'),
|
||||||
'SubInclusion' => array('attr2' => 'Type')
|
'SubInclusion' => array('attr2' => 'Type')
|
||||||
);
|
);
|
||||||
|
@@ -7,21 +7,15 @@ class HTMLPurifier_HTMLModule_BdoTest extends HTMLPurifier_HTMLModuleHarness
|
|||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
|
||||||
|
$this->setupScaffold('Bdo');
|
||||||
|
|
||||||
// max
|
// max
|
||||||
$this->assertResult(
|
$this->assertResult(
|
||||||
'<span>
|
'<span>
|
||||||
<bdo
|
<bdo ac:core="yes" dir="rtl">
|
||||||
id="test-id"
|
|
||||||
class="class-name"
|
|
||||||
style="font-weight:bold;"
|
|
||||||
title="Title of tag"
|
|
||||||
lang="en"
|
|
||||||
xml:lang="en"
|
|
||||||
dir="rtl"
|
|
||||||
>
|
|
||||||
#PCDATA <span>Inline</span>
|
#PCDATA <span>Inline</span>
|
||||||
</bdo>
|
</bdo>
|
||||||
</span>', true, array('Attr.EnableID' => true)
|
</span>'
|
||||||
);
|
);
|
||||||
|
|
||||||
// min
|
// min
|
||||||
|
@@ -7,21 +7,23 @@ class HTMLPurifier_HTMLModule_EditTest extends HTMLPurifier_HTMLModuleHarness
|
|||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
|
||||||
|
$this->setupScaffold('Edit');
|
||||||
|
|
||||||
// max
|
// max
|
||||||
$this->assertResult(
|
$this->assertResult(
|
||||||
'<span>
|
'<span>
|
||||||
<ins cite="http://www.example.com/">
|
<ins cite="http://www.example.com/" ac:common="yes">
|
||||||
#PCDATA <span></span>
|
#PCDATA <span></span>
|
||||||
</ins>
|
</ins>
|
||||||
<del cite="http://www.example.com/">
|
<del cite="http://www.example.com/" ac:common="yes">
|
||||||
#PCDATA <span></span>
|
#PCDATA <span></span>
|
||||||
</del>
|
</del>
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<ins cite="http://www.example.com/">
|
<ins cite="http://www.example.com/" ac:common="yes">
|
||||||
#PCDATA <div></div> <span></span>
|
#PCDATA <div></div> <span></span>
|
||||||
</ins>
|
</ins>
|
||||||
<del cite="http://www.example.com/">
|
<del cite="http://www.example.com/" ac:common="yes">
|
||||||
#PCDATA <div></div> <span></span>
|
#PCDATA <div></div> <span></span>
|
||||||
</del>
|
</del>
|
||||||
</div>'
|
</div>'
|
||||||
|
@@ -7,6 +7,11 @@ class HTMLPurifier_HTMLModule_HypertextTest extends HTMLPurifier_HTMLModuleHarne
|
|||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
|
||||||
|
$this->setupScaffold('Hypertext', array(
|
||||||
|
'Attr.AllowedRel' => 'nofollow',
|
||||||
|
'Attr.AllowedRev' => 'index'
|
||||||
|
));
|
||||||
|
|
||||||
// max
|
// max
|
||||||
$this->assertResult(
|
$this->assertResult(
|
||||||
'<span>
|
'<span>
|
||||||
@@ -14,13 +19,11 @@ class HTMLPurifier_HTMLModule_HypertextTest extends HTMLPurifier_HTMLModuleHarne
|
|||||||
href="http://www.example.com/"
|
href="http://www.example.com/"
|
||||||
rel="nofollow"
|
rel="nofollow"
|
||||||
rev="index"
|
rev="index"
|
||||||
|
ac:common="true"
|
||||||
>
|
>
|
||||||
#PCDATA <span>Inline</span>
|
#PCDATA <span>Inline</span>
|
||||||
</a>
|
</a>
|
||||||
</span>', true, array(
|
</span>', true
|
||||||
'Attr.AllowedRel' => 'nofollow',
|
|
||||||
'Attr.AllowedRev' => 'index'
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// invalid children
|
// invalid children
|
||||||
|
@@ -7,6 +7,8 @@ class HTMLPurifier_HTMLModule_ImageTest extends HTMLPurifier_HTMLModuleHarness
|
|||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
|
||||||
|
$this->setupScaffold('Image');
|
||||||
|
|
||||||
// max
|
// max
|
||||||
$this->assertResult(
|
$this->assertResult(
|
||||||
'<span>
|
'<span>
|
||||||
@@ -16,6 +18,7 @@ class HTMLPurifier_HTMLModule_ImageTest extends HTMLPurifier_HTMLModuleHarness
|
|||||||
longdesc="example.description.txt"
|
longdesc="example.description.txt"
|
||||||
height="42"
|
height="42"
|
||||||
width="42"
|
width="42"
|
||||||
|
ac:common="yes"
|
||||||
/>
|
/>
|
||||||
</span>'
|
</span>'
|
||||||
);
|
);
|
||||||
|
@@ -7,12 +7,14 @@ class HTMLPurifier_HTMLModule_LegacyTest extends HTMLPurifier_HTMLModuleHarness
|
|||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
|
||||||
|
$this->setupScaffold('Legacy');
|
||||||
|
|
||||||
// max
|
// max
|
||||||
$this->assertResult(
|
$this->assertResult(
|
||||||
'<span>
|
'<span>
|
||||||
<u>Text<span></span></u>
|
<u ac:common="yes">Text<span></span></u>
|
||||||
<s>Text<span></span></s>
|
<s ac:common="yes">Text<span></span></s>
|
||||||
<strike>Text<span></span></strike>
|
<strike ac:common="yes">Text<span></span></strike>
|
||||||
</span>'
|
</span>'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -9,6 +9,27 @@ class HTMLPurifier_HTMLModuleHarness extends HTMLPurifier_StrategyHarness
|
|||||||
parent::setup();
|
parent::setup();
|
||||||
$this->obj = new HTMLPurifier_Strategy_Core();
|
$this->obj = new HTMLPurifier_Strategy_Core();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupScaffold($module, $config = array()) {
|
||||||
|
|
||||||
|
$this->config = HTMLPurifier_Config::create($config);
|
||||||
|
$this->config->set('HTML', 'AllowedModules', $module);
|
||||||
|
$def =& $this->config->getHTMLDefinition(true);
|
||||||
|
$def->manager->addModule(new HTMLPurifier_HTMLModuleHarness_Scaffold());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special module that defines scaffolding for easy unit testing
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_HTMLModuleHarness_Scaffold extends HTMLPurifier_HTMLModule
|
||||||
|
{
|
||||||
|
var $name = 'Scaffold';
|
||||||
|
var $attr_collections = array(
|
||||||
|
'Common' => array('ac:common' => 'Text'),
|
||||||
|
'Core' => array('ac:core' => 'Text')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@@ -72,6 +72,34 @@ class HTMLPurifier_HTMLModuleManagerTest extends UnitTestCase
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testAllowedModules() {
|
||||||
|
|
||||||
|
$manager = new HTMLPurifier_HTMLModuleManager();
|
||||||
|
$manager->doctypes->register(
|
||||||
|
'Fantasy Inventory 1.0', true,
|
||||||
|
array('Weapons', 'Magic')
|
||||||
|
);
|
||||||
|
|
||||||
|
// register these modules so it doesn't blow up
|
||||||
|
$weapons_module = new HTMLPurifier_HTMLModule();
|
||||||
|
$weapons_module->name = 'Weapons';
|
||||||
|
$manager->registerModule($weapons_module);
|
||||||
|
|
||||||
|
$magic_module = new HTMLPurifier_HTMLModule();
|
||||||
|
$magic_module->name = 'Magic';
|
||||||
|
$manager->registerModule($magic_module);
|
||||||
|
|
||||||
|
$config = HTMLPurifier_Config::create(array(
|
||||||
|
'HTML.Doctype' => 'Fantasy Inventory 1.0',
|
||||||
|
'HTML.AllowedModules' => 'Weapons'
|
||||||
|
));
|
||||||
|
$manager->setup($config);
|
||||||
|
|
||||||
|
$this->assertTrue( isset($manager->modules['Weapons']));
|
||||||
|
$this->assertFalse(isset($manager->modules['Magic']));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@@ -42,6 +42,11 @@ class HTMLPurifier_Harness extends UnitTestCase
|
|||||||
*/
|
*/
|
||||||
var $generator;
|
var $generator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default config to fall back on if no config is available
|
||||||
|
*/
|
||||||
|
var $config;
|
||||||
|
|
||||||
function HTMLPurifier_Harness() {
|
function HTMLPurifier_Harness() {
|
||||||
$this->lexer = new HTMLPurifier_Lexer_DirectLex();
|
$this->lexer = new HTMLPurifier_Lexer_DirectLex();
|
||||||
$this->generator = new HTMLPurifier_Generator();
|
$this->generator = new HTMLPurifier_Generator();
|
||||||
@@ -52,22 +57,24 @@ class HTMLPurifier_Harness extends UnitTestCase
|
|||||||
* Asserts a specific result from a one parameter + config/context function
|
* Asserts a specific result from a one parameter + config/context function
|
||||||
* @param $input Input parameter
|
* @param $input Input parameter
|
||||||
* @param $expect Expectation
|
* @param $expect Expectation
|
||||||
* @param $config_array Configuration array in form of
|
* @param $config Configuration array in form of Ns.Directive => Value.
|
||||||
* Namespace.Directive => Value or an actual config
|
* Has no effect if $this->config is set.
|
||||||
* object.
|
|
||||||
* @param $context_array Context array in form of Key => Value or an actual
|
* @param $context_array Context array in form of Key => Value or an actual
|
||||||
* context object.
|
* context object.
|
||||||
*/
|
*/
|
||||||
function assertResult($input, $expect = true,
|
function assertResult($input, $expect = true,
|
||||||
$config_array = array(), $context_array = array()
|
$config_array = false, $context_array = array()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// setup config object
|
// setup config
|
||||||
$config = HTMLPurifier_Config::createDefault();
|
if ($this->config) {
|
||||||
$config->loadArray($config_array);
|
$config = HTMLPurifier_Config::create($this->config);
|
||||||
|
} else {
|
||||||
|
$config = HTMLPurifier_Config::create($config_array);
|
||||||
|
}
|
||||||
|
|
||||||
// setup context object. Note that we are operating on a copy of it!
|
// setup context object. Note that we are operating on a copy of it!
|
||||||
// We will extend the test harness to allow you to do post-tests
|
// When necessary, extend the test harness to allow post-tests
|
||||||
// on the context object
|
// on the context object
|
||||||
$context = new HTMLPurifier_Context();
|
$context = new HTMLPurifier_Context();
|
||||||
$context->loadArray($context_array);
|
$context->loadArray($context_array);
|
||||||
|
Reference in New Issue
Block a user