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:
@@ -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
|
||||||
|
114
library/HTMLPurifier/ContentSets.php
Normal file
114
library/HTMLPurifier/ContentSets.php
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@@ -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.
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user