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