Implement Tables Module.
[htmlpurifier.git] / library / HTMLPurifier / XHTMLDefinition.php
blob2cd72d672258e1e6cd2cfb925e33b9835ae00f78
1 <?php
3 require_once 'HTMLPurifier/HTMLDefinition.php';
5 require_once 'HTMLPurifier/AttrTypes.php';
6 require_once 'HTMLPurifier/AttrCollection.php';
8 require_once 'HTMLPurifier/HTMLModule.php';
9 require_once 'HTMLPurifier/HTMLModule/Text.php';
10 require_once 'HTMLPurifier/HTMLModule/Hypertext.php';
11 require_once 'HTMLPurifier/HTMLModule/List.php';
12 require_once 'HTMLPurifier/HTMLModule/Presentation.php';
13 require_once 'HTMLPurifier/HTMLModule/Edit.php';
14 require_once 'HTMLPurifier/HTMLModule/Bdo.php';
15 require_once 'HTMLPurifier/HTMLModule/Tables.php';
17 /**
18 * Next-generation HTML definition that will supplant HTMLPurifier_HTMLDefinition
20 class HTMLPurifier_XHTMLDefinition extends HTMLPurifier_HTMLDefinition
23 var $modules = array();
24 var $attr_types;
25 var $attr_collection;
26 var $content_sets;
28 function HTMLPurifier_XHTMLDefinition($config) {
30 $this->modules['Text'] = new HTMLPurifier_HTMLModule_Text();
31 $this->modules['Hypertext'] = new HTMLPurifier_HTMLModule_Hypertext();
32 $this->modules['List'] = new HTMLPurifier_HTMLModule_List();
33 $this->modules['Presentation'] = new HTMLPurifier_HTMLModule_Presentation();
34 $this->modules['Edit'] = new HTMLPurifier_HTMLModule_Edit();
35 $this->modules['Bdo'] = new HTMLPurifier_HTMLModule_Bdo();
36 $this->modules['Tables'] = new HTMLPurifier_HTMLModule_Tables();
38 $this->attr_types = new HTMLPurifier_AttrTypes();
39 $this->attr_collection = new HTMLPurifier_AttrCollection();
43 function setup($config) {
45 // perform attribute collection substitutions
46 $this->attr_collection->setup($this->attr_types, $this->modules);
48 // populate content_sets based on module hints
49 $content_sets = array();
50 foreach ($this->modules as $module_i => $module) {
51 foreach ($module->content_sets as $key => $value) {
52 if (isset($content_sets[$key])) {
53 // add it into the existing content set
54 $content_sets[$key] = $content_sets[$key] . ' | ' . $value;
55 } else {
56 $content_sets[$key] = $value;
61 // perform content_set expansions
62 foreach ($content_sets as $i => $set) {
63 // only performed once, so infinite recursion is not
64 // a problem, you'll just have a stray $Set lying around
65 // at the end
66 $content_sets[$i] =
67 str_replace(
68 array_keys($content_sets),
69 array_values($content_sets),
70 $set);
72 // define convenient variables
73 $content_sets_keys = array_keys($content_sets);
74 $content_sets_values = array_values($content_sets);
75 foreach ($content_sets as $name => $set) {
76 $this->content_sets[$name] = $this->convertToLookup($set);
79 foreach ($this->modules as $module_i => $module) {
80 foreach ($module->info as $name => $def) {
81 $def =& $this->modules[$module_i]->info[$name];
83 // attribute value expansions
84 $this->attr_collection->performInclusions($def->attr);
85 $this->attr_collection->expandIdentifiers(
86 $def->attr, $this->attr_types);
88 // perform content model expansions
89 $content_model = $def->content_model;
90 if (is_string($content_model)) {
91 if (strpos($content_model, 'Inline') !== false) {
92 $def->descendants_are_inline = true;
94 $def->content_model = str_replace(
95 $content_sets_keys, $content_sets_values, $content_model);
98 // get child def from content model
99 $def->child = $this->getChildDef($def);
101 // setup info
102 $this->info[$name] = $def;
103 if ($this->info_parent == $name) {
104 $this->info_parent_def = $this->info[$name];
109 $this->setupAttrTransform($config);
110 $this->setupBlockWrapper($config);
111 $this->setupParent($config);
115 function setupAttrTransform($config) {
116 $this->info_attr_transform_post[] = new HTMLPurifier_AttrTransform_Lang();
119 function setupBlockWrapper($config) {
120 $block_wrapper = $config->get('HTML', 'BlockWrapper');
121 if (isset($this->content_sets['Block'][$block_wrapper])) {
122 $this->info_block_wrapper = $block_wrapper;
123 } else {
124 trigger_error('Cannot use non-block element as block wrapper.',
125 E_USER_ERROR);
129 function setupParent($config) {
130 $parent = $config->get('HTML', 'Parent');
131 if (isset($this->info[$parent])) {
132 $this->info_parent = $parent;
133 } else {
134 trigger_error('Cannot use unrecognized element as parent.',
135 E_USER_ERROR);
137 $this->info_parent_def = $this->info[$this->info_parent];
140 function getChildDef($def) {
141 $value = $def->content_model;
142 $type = $def->content_model_type;
143 switch ($type) {
144 case 'required':
145 return new HTMLPurifier_ChildDef_Required($value);
146 case 'optional':
147 return new HTMLPurifier_ChildDef_Optional($value);
148 case 'empty':
149 return new HTMLPurifier_ChildDef_Empty();
150 case 'strictblockquote':
151 return new HTMLPurifier_ChildDef_StrictBlockquote($value);
152 case 'table':
153 return new HTMLPurifier_ChildDef_Table();
154 case 'chameleon':
155 $value = explode('!', $value);
156 return new HTMLPurifier_ChildDef_Chameleon($value[0], $value[1]);
157 case 'custom':
158 return new HTMLPurifier_ChildDef_Custom($value);
160 if ($value) return new HTMLPurifier_ChildDef_Optional($value);
161 return new HTMLPurifier_ChildDef_Empty();
164 function convertToLookup($string) {
165 $array = explode('|', str_replace(' ', '', $string));
166 $ret = array();
167 foreach ($array as $i => $k) {
168 $ret[$k] = true;
170 return $ret;