]>
Commit | Line | Data |
---|---|---|
d4949327 NL |
1 | <?php\r |
2 | \r | |
3 | /**\r | |
4 | * Structure that stores an HTML element definition. Used by\r | |
5 | * HTMLPurifier_HTMLDefinition and HTMLPurifier_HTMLModule.\r | |
6 | * @note This class is inspected by HTMLPurifier_Printer_HTMLDefinition.\r | |
7 | * Please update that class too.\r | |
8 | * @warning If you add new properties to this class, you MUST update\r | |
9 | * the mergeIn() method.\r | |
10 | */\r | |
11 | class HTMLPurifier_ElementDef\r | |
12 | {\r | |
13 | /**\r | |
14 | * Does the definition work by itself, or is it created solely\r | |
15 | * for the purpose of merging into another definition?\r | |
16 | * @type bool\r | |
17 | */\r | |
18 | public $standalone = true;\r | |
19 | \r | |
20 | /**\r | |
21 | * Associative array of attribute name to HTMLPurifier_AttrDef.\r | |
22 | * @type array\r | |
23 | * @note Before being processed by HTMLPurifier_AttrCollections\r | |
24 | * when modules are finalized during\r | |
25 | * HTMLPurifier_HTMLDefinition->setup(), this array may also\r | |
26 | * contain an array at index 0 that indicates which attribute\r | |
27 | * collections to load into the full array. It may also\r | |
28 | * contain string indentifiers in lieu of HTMLPurifier_AttrDef,\r | |
29 | * see HTMLPurifier_AttrTypes on how they are expanded during\r | |
30 | * HTMLPurifier_HTMLDefinition->setup() processing.\r | |
31 | */\r | |
32 | public $attr = array();\r | |
33 | \r | |
34 | // XXX: Design note: currently, it's not possible to override\r | |
35 | // previously defined AttrTransforms without messing around with\r | |
36 | // the final generated config. This is by design; a previous version\r | |
37 | // used an associated list of attr_transform, but it was extremely\r | |
38 | // easy to accidentally override other attribute transforms by\r | |
39 | // forgetting to specify an index (and just using 0.) While we\r | |
40 | // could check this by checking the index number and complaining,\r | |
41 | // there is a second problem which is that it is not at all easy to\r | |
42 | // tell when something is getting overridden. Combine this with a\r | |
43 | // codebase where this isn't really being used, and it's perfect for\r | |
44 | // nuking.\r | |
45 | \r | |
46 | /**\r | |
47 | * List of tags HTMLPurifier_AttrTransform to be done before validation.\r | |
48 | * @type array\r | |
49 | */\r | |
50 | public $attr_transform_pre = array();\r | |
51 | \r | |
52 | /**\r | |
53 | * List of tags HTMLPurifier_AttrTransform to be done after validation.\r | |
54 | * @type array\r | |
55 | */\r | |
56 | public $attr_transform_post = array();\r | |
57 | \r | |
58 | /**\r | |
59 | * HTMLPurifier_ChildDef of this tag.\r | |
60 | * @type HTMLPurifier_ChildDef\r | |
61 | */\r | |
62 | public $child;\r | |
63 | \r | |
64 | /**\r | |
65 | * Abstract string representation of internal ChildDef rules.\r | |
66 | * @see HTMLPurifier_ContentSets for how this is parsed and then transformed\r | |
67 | * into an HTMLPurifier_ChildDef.\r | |
68 | * @warning This is a temporary variable that is not available after\r | |
69 | * being processed by HTMLDefinition\r | |
70 | * @type string\r | |
71 | */\r | |
72 | public $content_model;\r | |
73 | \r | |
74 | /**\r | |
75 | * Value of $child->type, used to determine which ChildDef to use,\r | |
76 | * used in combination with $content_model.\r | |
77 | * @warning This must be lowercase\r | |
78 | * @warning This is a temporary variable that is not available after\r | |
79 | * being processed by HTMLDefinition\r | |
80 | * @type string\r | |
81 | */\r | |
82 | public $content_model_type;\r | |
83 | \r | |
84 | /**\r | |
85 | * Does the element have a content model (#PCDATA | Inline)*? This\r | |
86 | * is important for chameleon ins and del processing in\r | |
87 | * HTMLPurifier_ChildDef_Chameleon. Dynamically set: modules don't\r | |
88 | * have to worry about this one.\r | |
89 | * @type bool\r | |
90 | */\r | |
91 | public $descendants_are_inline = false;\r | |
92 | \r | |
93 | /**\r | |
94 | * List of the names of required attributes this element has.\r | |
95 | * Dynamically populated by HTMLPurifier_HTMLDefinition::getElement()\r | |
96 | * @type array\r | |
97 | */\r | |
98 | public $required_attr = array();\r | |
99 | \r | |
100 | /**\r | |
101 | * Lookup table of tags excluded from all descendants of this tag.\r | |
102 | * @type array\r | |
103 | * @note SGML permits exclusions for all descendants, but this is\r | |
104 | * not possible with DTDs or XML Schemas. W3C has elected to\r | |
105 | * use complicated compositions of content_models to simulate\r | |
106 | * exclusion for children, but we go the simpler, SGML-style\r | |
107 | * route of flat-out exclusions, which correctly apply to\r | |
108 | * all descendants and not just children. Note that the XHTML\r | |
109 | * Modularization Abstract Modules are blithely unaware of such\r | |
110 | * distinctions.\r | |
111 | */\r | |
112 | public $excludes = array();\r | |
113 | \r | |
114 | /**\r | |
115 | * This tag is explicitly auto-closed by the following tags.\r | |
116 | * @type array\r | |
117 | */\r | |
118 | public $autoclose = array();\r | |
119 | \r | |
120 | /**\r | |
121 | * If a foreign element is found in this element, test if it is\r | |
122 | * allowed by this sub-element; if it is, instead of closing the\r | |
123 | * current element, place it inside this element.\r | |
124 | * @type string\r | |
125 | */\r | |
126 | public $wrap;\r | |
127 | \r | |
128 | /**\r | |
129 | * Whether or not this is a formatting element affected by the\r | |
130 | * "Active Formatting Elements" algorithm.\r | |
131 | * @type bool\r | |
132 | */\r | |
133 | public $formatting;\r | |
134 | \r | |
135 | /**\r | |
136 | * Low-level factory constructor for creating new standalone element defs\r | |
137 | */\r | |
138 | public static function create($content_model, $content_model_type, $attr)\r | |
139 | {\r | |
140 | $def = new HTMLPurifier_ElementDef();\r | |
141 | $def->content_model = $content_model;\r | |
142 | $def->content_model_type = $content_model_type;\r | |
143 | $def->attr = $attr;\r | |
144 | return $def;\r | |
145 | }\r | |
146 | \r | |
147 | /**\r | |
148 | * Merges the values of another element definition into this one.\r | |
149 | * Values from the new element def take precedence if a value is\r | |
150 | * not mergeable.\r | |
151 | * @param HTMLPurifier_ElementDef $def\r | |
152 | */\r | |
153 | public function mergeIn($def)\r | |
154 | {\r | |
155 | // later keys takes precedence\r | |
156 | foreach ($def->attr as $k => $v) {\r | |
157 | if ($k === 0) {\r | |
158 | // merge in the includes\r | |
159 | // sorry, no way to override an include\r | |
160 | foreach ($v as $v2) {\r | |
161 | $this->attr[0][] = $v2;\r | |
162 | }\r | |
163 | continue;\r | |
164 | }\r | |
165 | if ($v === false) {\r | |
166 | if (isset($this->attr[$k])) {\r | |
167 | unset($this->attr[$k]);\r | |
168 | }\r | |
169 | continue;\r | |
170 | }\r | |
171 | $this->attr[$k] = $v;\r | |
172 | }\r | |
173 | $this->_mergeAssocArray($this->excludes, $def->excludes);\r | |
174 | $this->attr_transform_pre = array_merge($this->attr_transform_pre, $def->attr_transform_pre);\r | |
175 | $this->attr_transform_post = array_merge($this->attr_transform_post, $def->attr_transform_post);\r | |
176 | \r | |
177 | if (!empty($def->content_model)) {\r | |
178 | $this->content_model =\r | |
179 | str_replace("#SUPER", $this->content_model, $def->content_model);\r | |
180 | $this->child = false;\r | |
181 | }\r | |
182 | if (!empty($def->content_model_type)) {\r | |
183 | $this->content_model_type = $def->content_model_type;\r | |
184 | $this->child = false;\r | |
185 | }\r | |
186 | if (!is_null($def->child)) {\r | |
187 | $this->child = $def->child;\r | |
188 | }\r | |
189 | if (!is_null($def->formatting)) {\r | |
190 | $this->formatting = $def->formatting;\r | |
191 | }\r | |
192 | if ($def->descendants_are_inline) {\r | |
193 | $this->descendants_are_inline = $def->descendants_are_inline;\r | |
194 | }\r | |
195 | }\r | |
196 | \r | |
197 | /**\r | |
198 | * Merges one array into another, removes values which equal false\r | |
199 | * @param $a1 Array by reference that is merged into\r | |
200 | * @param $a2 Array that merges into $a1\r | |
201 | */\r | |
202 | private function _mergeAssocArray(&$a1, $a2)\r | |
203 | {\r | |
204 | foreach ($a2 as $k => $v) {\r | |
205 | if ($v === false) {\r | |
206 | if (isset($a1[$k])) {\r | |
207 | unset($a1[$k]);\r | |
208 | }\r | |
209 | continue;\r | |
210 | }\r | |
211 | $a1[$k] = $v;\r | |
212 | }\r | |
213 | }\r | |
214 | }\r | |
215 | \r | |
216 | // vim: et sw=4 sts=4\r |