1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-08-01 11:50:28 +02:00

Factor out content set and childdef functionality to ContentSets. Remove redundant info suffix from attr_collections.

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@725 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang
2007-02-05 03:05:46 +00:00
parent 219902ebff
commit e2103ce0f2
5 changed files with 592 additions and 566 deletions

View File

@@ -53,7 +53,7 @@ class HTMLPurifier_AttrCollections
$info =& $this->info; $info =& $this->info;
// load extensions from the modules // load extensions from the modules
foreach ($modules as $module) { foreach ($modules as $module) {
foreach ($module->attr_collections_info as $coll_i => $coll) { foreach ($module->attr_collections as $coll_i => $coll) {
foreach ($coll as $attr_i => $attr) { foreach ($coll as $attr_i => $attr) {
if ($attr_i === 0 && isset($info[$coll_i][$attr_i])) { if ($attr_i === 0 && isset($info[$coll_i][$attr_i])) {
// merge in includes // merge in includes

View File

@@ -0,0 +1,114 @@
<?php
// common defs that we'll support by default
require_once 'HTMLPurifier/ChildDef.php';
require_once 'HTMLPurifier/ChildDef/Empty.php';
require_once 'HTMLPurifier/ChildDef/Required.php';
require_once 'HTMLPurifier/ChildDef/Optional.php';
require_once 'HTMLPurifier/ChildDef/StrictBlockquote.php'; // transform
class HTMLPurifier_ContentSets
{
var $info = array();
var $lookup = array();
var $keys = array();
var $values = array();
function setup($modules) {
// populate content_sets based on module hints
foreach ($modules as $module_i => $module) {
foreach ($module->content_sets as $key => $value) {
if (isset($this->info[$key])) {
// add it into the existing content set
$this->info[$key] = $this->info[$key] . ' | ' . $value;
} else {
$this->info[$key] = $value;
}
}
}
// perform content_set expansions
$this->keys = array_keys($this->info);
foreach ($this->info as $i => $set) {
// only performed once, so infinite recursion is not
// a problem
$this->info[$i] =
str_replace(
$this->keys,
// must be recalculated each time due to
// changing substitutions
array_values($this->info),
$set);
}
$this->values = array_values($this->info);
// generate lookup tables
foreach ($this->info as $name => $set) {
$this->lookup[$name] = $this->convertToLookup($set);
}
}
function generateChildDef(&$def, $module) {
$content_model = $def->content_model;
if (is_string($content_model)) {
$def->content_model = str_replace(
$this->keys, $this->values, $content_model);
}
$def->child = $this->getChildDef($def, $module);
}
/**
* Instantiates a ChildDef based on content_model and content_model_type
* member variables in HTMLPurifier_ElementDef
* @note This will also defer to modules for custom HTMLPurifier_ChildDef
* subclasses that need content set expansion
* @param $def HTMLPurifier_ElementDef to have ChildDef extracted
* @return HTMLPurifier_ChildDef corresponding to ElementDef
*/
function getChildDef($def, $module) {
$value = $def->content_model;
if (is_object($value)) return $value; // direct object, return
switch ($def->content_model_type) {
case 'required':
return new HTMLPurifier_ChildDef_Required($value);
case 'optional':
return new HTMLPurifier_ChildDef_Optional($value);
case 'empty':
return new HTMLPurifier_ChildDef_Empty();
case 'strictblockquote':
return new HTMLPurifier_ChildDef_StrictBlockquote($value);
case 'custom':
return new HTMLPurifier_ChildDef_Custom($value);
}
// defer to its module
if (!$module->defines_child_def) continue; // save a func call
$return = $module->getChildDef($def);
if ($return !== false) return $return;
// error-out
trigger_error(
'Could not determine which ChildDef class to instantiate',
E_USER_ERROR
);
return false;
}
/**
* Converts a string list of elements separated by pipes into
* a lookup array.
* @param $string List of elements
* @return Lookup array of elements
*/
function convertToLookup($string) {
$array = explode('|', str_replace(' ', '', $string));
$ret = array();
foreach ($array as $i => $k) {
$ret[$k] = true;
}
return $ret;
}
}
?>

View File

@@ -1,36 +1,25 @@
<?php <?php
// components
require_once 'HTMLPurifier/AttrTypes.php'; require_once 'HTMLPurifier/AttrTypes.php';
require_once 'HTMLPurifier/AttrCollections.php'; require_once 'HTMLPurifier/AttrCollections.php';
require_once 'HTMLPurifier/ContentSets.php';
require_once 'HTMLPurifier/ElementDef.php'; require_once 'HTMLPurifier/ElementDef.php';
// we'll manage loading extremely commonly used attr definitions
require_once 'HTMLPurifier/AttrDef.php'; require_once 'HTMLPurifier/AttrDef.php';
require_once 'HTMLPurifier/AttrDef/Enum.php'; require_once 'HTMLPurifier/AttrDef/Enum.php'; // common
// technically speaking, these includes would be more appropriate for // temporary: attribute transformations
// other modules, but we're going to include all the common ones. A
// custom one would have to be fed in as an actual object
require_once 'HTMLPurifier/ChildDef.php';
require_once 'HTMLPurifier/ChildDef/Empty.php';
require_once 'HTMLPurifier/ChildDef/Required.php';
require_once 'HTMLPurifier/ChildDef/Optional.php';
require_once 'HTMLPurifier/ChildDef/StrictBlockquote.php';
// handling attribute transformations until modules gain the capability
require_once 'HTMLPurifier/AttrTransform.php'; require_once 'HTMLPurifier/AttrTransform.php';
require_once 'HTMLPurifier/AttrTransform/Lang.php'; require_once 'HTMLPurifier/AttrTransform/Lang.php';
require_once 'HTMLPurifier/AttrTransform/TextAlign.php'; require_once 'HTMLPurifier/AttrTransform/TextAlign.php';
require_once 'HTMLPurifier/AttrTransform/BdoDir.php'; require_once 'HTMLPurifier/AttrTransform/BdoDir.php';
require_once 'HTMLPurifier/AttrTransform/ImgRequired.php'; require_once 'HTMLPurifier/AttrTransform/ImgRequired.php';
// handling tag transformations until modules gain the capability // temporary: tag transformations
require_once 'HTMLPurifier/TagTransform.php'; require_once 'HTMLPurifier/TagTransform.php';
// utility classes that are necessary (?) // default modules
require_once 'HTMLPurifier/Generator.php';
require_once 'HTMLPurifier/Token.php';
require_once 'HTMLPurifier/HTMLModule.php'; require_once 'HTMLPurifier/HTMLModule.php';
require_once 'HTMLPurifier/HTMLModule/Text.php'; require_once 'HTMLPurifier/HTMLModule/Text.php';
require_once 'HTMLPurifier/HTMLModule/Hypertext.php'; require_once 'HTMLPurifier/HTMLModule/Hypertext.php';
@@ -232,6 +221,11 @@ class HTMLPurifier_HTMLDefinition
*/ */
var $setup = false; var $setup = false;
/**
* Instance of HTMLPurifier_ContentSets
* @public
*/
var $content_sets;
/** /**
@@ -256,6 +250,7 @@ class HTMLPurifier_HTMLDefinition
$this->attr_types = new HTMLPurifier_AttrTypes(); $this->attr_types = new HTMLPurifier_AttrTypes();
$this->attr_collections = new HTMLPurifier_AttrCollections(); $this->attr_collections = new HTMLPurifier_AttrCollections();
$this->content_sets = new HTMLPurifier_ContentSets();
// some compat stuff, will be factored to modules // some compat stuff, will be factored to modules
@@ -277,68 +272,43 @@ class HTMLPurifier_HTMLDefinition
function setup($config) { function setup($config) {
// multiple call guard // multiple call guard
if ($this->setup) return; if ($this->setup) {return;} else {$this->setup = true;}
$this->setup = true;
// perform attribute collection substitutions // would be nice if we could put each of these in their
// own object, would make this hookable too!
$this->setupInfo($config);
$this->setupAttrTransform($config);
$this->setupBlockWrapper($config);
$this->setupParent($config);
$this->setupCompat($config);
}
function setupInfo() {
$this->attr_collections->setup($this->attr_types, $this->modules); $this->attr_collections->setup($this->attr_types, $this->modules);
$this->content_sets->setup($this->modules);
// populate content_sets based on module hints $this->info_content_sets = $this->content_sets->lookup;
$content_sets = array();
foreach ($this->modules as $module_i => $module) {
foreach ($module->content_sets as $key => $value) {
if (isset($content_sets[$key])) {
// add it into the existing content set
$content_sets[$key] = $content_sets[$key] . ' | ' . $value;
} else {
$content_sets[$key] = $value;
}
}
}
// perform content_set expansions
foreach ($content_sets as $i => $set) {
// only performed once, so infinite recursion is not
// a problem, you'll just have a stray $Set lying around
// at the end
$content_sets[$i] =
str_replace(
array_keys($content_sets),
array_values($content_sets),
$set);
}
// define convenient variables
$content_sets_keys = array_keys($content_sets);
$content_sets_values = array_values($content_sets);
foreach ($content_sets as $name => $set) {
$this->info_content_sets[$name] = $this->convertToLookup($set);
}
foreach ($this->modules as $module_i => $module) { foreach ($this->modules as $module_i => $module) {
foreach ($module->info as $name => $def) { foreach ($module->info as $name => $def) {
$def =& $this->modules[$module_i]->info[$name]; $def =& $this->modules[$module_i]->info[$name];
// attribute value expansions // attribute value expansions
$this->attr_collections->performInclusions($def->attr); $this->attr_collections->performInclusions($def->attr);
$this->attr_collections->expandIdentifiers( $this->attr_collections->expandIdentifiers(
$def->attr, $this->attr_types); $def->attr, $this->attr_types);
// perform content model expansions // chameleon data, set descendants_are_inline
$content_model = $def->content_model; if (is_string($def->content_model) &&
if (is_string($content_model)) { strpos($def->content_model, 'Inline') !== false) {
if (strpos($content_model, 'Inline') !== false) {
if ($name != 'del' && $name != 'ins') { if ($name != 'del' && $name != 'ins') {
// this is for you, ins/del // this is for you, ins/del
$def->descendants_are_inline = true; $def->descendants_are_inline = true;
} }
} }
$def->content_model = str_replace(
$content_sets_keys, $content_sets_values, $content_model);
}
// get child def from content model // set child def from content model
$def->child = $this->getChildDef($def); $this->content_sets->generateChildDef($def, $module);
// setup info // setup info
$this->info[$name] = $def; $this->info[$name] = $def;
@@ -347,12 +317,6 @@ class HTMLPurifier_HTMLDefinition
} }
} }
} }
$this->setupAttrTransform($config);
$this->setupBlockWrapper($config);
$this->setupParent($config);
$this->setupCompat($config);
} }
/** /**
@@ -502,58 +466,6 @@ class HTMLPurifier_HTMLDefinition
} }
/**
* Instantiates a ChildDef based on content_model and content_model_type
* member variables in HTMLPurifier_ElementDef
* @note This will also defer to modules for custom HTMLPurifier_ChildDef
* subclasses that need content set expansion
* @param $def HTMLPurifier_ElementDef to have ChildDef extracted
* @return HTMLPurifier_ChildDef corresponding to ElementDef
*/
function getChildDef($def) {
$value = $def->content_model;
if (is_object($value)) return $value; // direct object, return
switch ($def->content_model_type) {
case 'required':
return new HTMLPurifier_ChildDef_Required($value);
case 'optional':
return new HTMLPurifier_ChildDef_Optional($value);
case 'empty':
return new HTMLPurifier_ChildDef_Empty();
case 'strictblockquote':
return new HTMLPurifier_ChildDef_StrictBlockquote($value);
case 'custom':
return new HTMLPurifier_ChildDef_Custom($value);
}
// defer to modules, see if they know what child_def to use
foreach ($this->modules as $module) {
if (!$module->defines_child_def) continue; // save a func call
$return = $module->getChildDef($def);
if ($return !== false) return $return;
}
// error-out
trigger_error(
'Could not determine which ChildDef class to instantiate',
E_USER_ERROR
);
return false;
}
/**
* Converts a string list of elements separated by pipes into
* a lookup array.
* @param $string List of elements
* @return Lookup array of elements
*/
function convertToLookup($string) {
$array = explode('|', str_replace(' ', '', $string));
$ret = array();
foreach ($array as $i => $k) {
$ret[$k] = true;
}
return $ret;
}
} }
?> ?>

View File

@@ -46,12 +46,12 @@ class HTMLPurifier_HTMLModule
* Associative array of attribute collection names to attribute * Associative array of attribute collection names to attribute
* collection additions. More rarely used for adding attributes to * collection additions. More rarely used for adding attributes to
* the global collections. Example is the StyleAttribute module adding * the global collections. Example is the StyleAttribute module adding
* the style attribute to the Core. Corresponds to attr_collections * the style attribute to the Core. Corresponds to HTMLDefinition's
* attr_collections->info, as only one object with behavior is * attr_collections->info, since the object's data is only info,
* necessary. * with extra behavior associated with it.
* @public * @public
*/ */
var $attr_collections_info = array(); var $attr_collections = array();
/** /**
* Boolean flag that indicates whether or not getChildDef is implemented. * Boolean flag that indicates whether or not getChildDef is implemented.

View File

@@ -9,7 +9,7 @@ require_once 'HTMLPurifier/AttrDef/CSS.php';
*/ */
class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule
{ {
var $attr_collections_info = array( var $attr_collections = array(
// The inclusion routine differs from the Abstract Modules but // The inclusion routine differs from the Abstract Modules but
// is in line with the DTD and XML Schemas. // is in line with the DTD and XML Schemas.
'Style' => array('style' => false), // see constructor 'Style' => array('style' => false), // see constructor
@@ -17,7 +17,7 @@ class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule
); );
function HTMLPurifier_HTMLModule_StyleAttribute() { function HTMLPurifier_HTMLModule_StyleAttribute() {
$this->attr_collections_info['Style']['style'] = new HTMLPurifier_AttrDef_CSS(); $this->attr_collections['Style']['style'] = new HTMLPurifier_AttrDef_CSS();
} }
} }