]>
Commit | Line | Data |
---|---|---|
d4949327 NL |
1 | <?php\r |
2 | \r | |
3 | /**\r | |
4 | * @todo Unit test\r | |
5 | */\r | |
6 | class HTMLPurifier_ContentSets\r | |
7 | {\r | |
8 | \r | |
9 | /**\r | |
10 | * List of content set strings (pipe separators) indexed by name.\r | |
11 | * @type array\r | |
12 | */\r | |
13 | public $info = array();\r | |
14 | \r | |
15 | /**\r | |
16 | * List of content set lookups (element => true) indexed by name.\r | |
17 | * @type array\r | |
18 | * @note This is in HTMLPurifier_HTMLDefinition->info_content_sets\r | |
19 | */\r | |
20 | public $lookup = array();\r | |
21 | \r | |
22 | /**\r | |
23 | * Synchronized list of defined content sets (keys of info).\r | |
24 | * @type array\r | |
25 | */\r | |
26 | protected $keys = array();\r | |
27 | /**\r | |
28 | * Synchronized list of defined content values (values of info).\r | |
29 | * @type array\r | |
30 | */\r | |
31 | protected $values = array();\r | |
32 | \r | |
33 | /**\r | |
34 | * Merges in module's content sets, expands identifiers in the content\r | |
35 | * sets and populates the keys, values and lookup member variables.\r | |
36 | * @param HTMLPurifier_HTMLModule[] $modules List of HTMLPurifier_HTMLModule\r | |
37 | */\r | |
38 | public function __construct($modules)\r | |
39 | {\r | |
40 | if (!is_array($modules)) {\r | |
41 | $modules = array($modules);\r | |
42 | }\r | |
43 | // populate content_sets based on module hints\r | |
44 | // sorry, no way of overloading\r | |
45 | foreach ($modules as $module) {\r | |
46 | foreach ($module->content_sets as $key => $value) {\r | |
47 | $temp = $this->convertToLookup($value);\r | |
48 | if (isset($this->lookup[$key])) {\r | |
49 | // add it into the existing content set\r | |
50 | $this->lookup[$key] = array_merge($this->lookup[$key], $temp);\r | |
51 | } else {\r | |
52 | $this->lookup[$key] = $temp;\r | |
53 | }\r | |
54 | }\r | |
55 | }\r | |
56 | $old_lookup = false;\r | |
57 | while ($old_lookup !== $this->lookup) {\r | |
58 | $old_lookup = $this->lookup;\r | |
59 | foreach ($this->lookup as $i => $set) {\r | |
60 | $add = array();\r | |
61 | foreach ($set as $element => $x) {\r | |
62 | if (isset($this->lookup[$element])) {\r | |
63 | $add += $this->lookup[$element];\r | |
64 | unset($this->lookup[$i][$element]);\r | |
65 | }\r | |
66 | }\r | |
67 | $this->lookup[$i] += $add;\r | |
68 | }\r | |
69 | }\r | |
70 | \r | |
71 | foreach ($this->lookup as $key => $lookup) {\r | |
72 | $this->info[$key] = implode(' | ', array_keys($lookup));\r | |
73 | }\r | |
74 | $this->keys = array_keys($this->info);\r | |
75 | $this->values = array_values($this->info);\r | |
76 | }\r | |
77 | \r | |
78 | /**\r | |
79 | * Accepts a definition; generates and assigns a ChildDef for it\r | |
80 | * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef reference\r | |
81 | * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef\r | |
82 | */\r | |
83 | public function generateChildDef(&$def, $module)\r | |
84 | {\r | |
85 | if (!empty($def->child)) { // already done!\r | |
86 | return;\r | |
87 | }\r | |
88 | $content_model = $def->content_model;\r | |
89 | if (is_string($content_model)) {\r | |
90 | // Assume that $this->keys is alphanumeric\r | |
91 | $def->content_model = preg_replace_callback(\r | |
92 | '/\b(' . implode('|', $this->keys) . ')\b/',\r | |
93 | array($this, 'generateChildDefCallback'),\r | |
94 | $content_model\r | |
95 | );\r | |
96 | //$def->content_model = str_replace(\r | |
97 | // $this->keys, $this->values, $content_model);\r | |
98 | }\r | |
99 | $def->child = $this->getChildDef($def, $module);\r | |
100 | }\r | |
101 | \r | |
102 | public function generateChildDefCallback($matches)\r | |
103 | {\r | |
104 | return $this->info[$matches[0]];\r | |
105 | }\r | |
106 | \r | |
107 | /**\r | |
108 | * Instantiates a ChildDef based on content_model and content_model_type\r | |
109 | * member variables in HTMLPurifier_ElementDef\r | |
110 | * @note This will also defer to modules for custom HTMLPurifier_ChildDef\r | |
111 | * subclasses that need content set expansion\r | |
112 | * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef to have ChildDef extracted\r | |
113 | * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef\r | |
114 | * @return HTMLPurifier_ChildDef corresponding to ElementDef\r | |
115 | */\r | |
116 | public function getChildDef($def, $module)\r | |
117 | {\r | |
118 | $value = $def->content_model;\r | |
119 | if (is_object($value)) {\r | |
120 | trigger_error(\r | |
121 | 'Literal object child definitions should be stored in '.\r | |
122 | 'ElementDef->child not ElementDef->content_model',\r | |
123 | E_USER_NOTICE\r | |
124 | );\r | |
125 | return $value;\r | |
126 | }\r | |
127 | switch ($def->content_model_type) {\r | |
128 | case 'required':\r | |
129 | return new HTMLPurifier_ChildDef_Required($value);\r | |
130 | case 'optional':\r | |
131 | return new HTMLPurifier_ChildDef_Optional($value);\r | |
132 | case 'empty':\r | |
133 | return new HTMLPurifier_ChildDef_Empty();\r | |
134 | case 'custom':\r | |
135 | return new HTMLPurifier_ChildDef_Custom($value);\r | |
136 | }\r | |
137 | // defer to its module\r | |
138 | $return = false;\r | |
139 | if ($module->defines_child_def) { // save a func call\r | |
140 | $return = $module->getChildDef($def);\r | |
141 | }\r | |
142 | if ($return !== false) {\r | |
143 | return $return;\r | |
144 | }\r | |
145 | // error-out\r | |
146 | trigger_error(\r | |
147 | 'Could not determine which ChildDef class to instantiate',\r | |
148 | E_USER_ERROR\r | |
149 | );\r | |
150 | return false;\r | |
151 | }\r | |
152 | \r | |
153 | /**\r | |
154 | * Converts a string list of elements separated by pipes into\r | |
155 | * a lookup array.\r | |
156 | * @param string $string List of elements\r | |
157 | * @return array Lookup array of elements\r | |
158 | */\r | |
159 | protected function convertToLookup($string)\r | |
160 | {\r | |
161 | $array = explode('|', str_replace(' ', '', $string));\r | |
162 | $ret = array();\r | |
163 | foreach ($array as $k) {\r | |
164 | $ret[$k] = true;\r | |
165 | }\r | |
166 | return $ret;\r | |
167 | }\r | |
168 | }\r | |
169 | \r | |
170 | // vim: et sw=4 sts=4\r |