Minor dependency updates
[yaffs-website] / vendor / ezyang / htmlpurifier / library / HTMLPurifier / ConfigSchema / InterchangeBuilder.php
1 <?php
2
3 class HTMLPurifier_ConfigSchema_InterchangeBuilder
4 {
5
6     /**
7      * Used for processing DEFAULT, nothing else.
8      * @type HTMLPurifier_VarParser
9      */
10     protected $varParser;
11
12     /**
13      * @param HTMLPurifier_VarParser $varParser
14      */
15     public function __construct($varParser = null)
16     {
17         $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
18     }
19
20     /**
21      * @param string $dir
22      * @return HTMLPurifier_ConfigSchema_Interchange
23      */
24     public static function buildFromDirectory($dir = null)
25     {
26         $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
27         $interchange = new HTMLPurifier_ConfigSchema_Interchange();
28         return $builder->buildDir($interchange, $dir);
29     }
30
31     /**
32      * @param HTMLPurifier_ConfigSchema_Interchange $interchange
33      * @param string $dir
34      * @return HTMLPurifier_ConfigSchema_Interchange
35      */
36     public function buildDir($interchange, $dir = null)
37     {
38         if (!$dir) {
39             $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
40         }
41         if (file_exists($dir . '/info.ini')) {
42             $info = parse_ini_file($dir . '/info.ini');
43             $interchange->name = $info['name'];
44         }
45
46         $files = array();
47         $dh = opendir($dir);
48         while (false !== ($file = readdir($dh))) {
49             if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') {
50                 continue;
51             }
52             $files[] = $file;
53         }
54         closedir($dh);
55
56         sort($files);
57         foreach ($files as $file) {
58             $this->buildFile($interchange, $dir . '/' . $file);
59         }
60         return $interchange;
61     }
62
63     /**
64      * @param HTMLPurifier_ConfigSchema_Interchange $interchange
65      * @param string $file
66      */
67     public function buildFile($interchange, $file)
68     {
69         $parser = new HTMLPurifier_StringHashParser();
70         $this->build(
71             $interchange,
72             new HTMLPurifier_StringHash($parser->parseFile($file))
73         );
74     }
75
76     /**
77      * Builds an interchange object based on a hash.
78      * @param HTMLPurifier_ConfigSchema_Interchange $interchange HTMLPurifier_ConfigSchema_Interchange object to build
79      * @param HTMLPurifier_StringHash $hash source data
80      * @throws HTMLPurifier_ConfigSchema_Exception
81      */
82     public function build($interchange, $hash)
83     {
84         if (!$hash instanceof HTMLPurifier_StringHash) {
85             $hash = new HTMLPurifier_StringHash($hash);
86         }
87         if (!isset($hash['ID'])) {
88             throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID');
89         }
90         if (strpos($hash['ID'], '.') === false) {
91             if (count($hash) == 2 && isset($hash['DESCRIPTION'])) {
92                 $hash->offsetGet('DESCRIPTION'); // prevent complaining
93             } else {
94                 throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace');
95             }
96         } else {
97             $this->buildDirective($interchange, $hash);
98         }
99         $this->_findUnused($hash);
100     }
101
102     /**
103      * @param HTMLPurifier_ConfigSchema_Interchange $interchange
104      * @param HTMLPurifier_StringHash $hash
105      * @throws HTMLPurifier_ConfigSchema_Exception
106      */
107     public function buildDirective($interchange, $hash)
108     {
109         $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
110
111         // These are required elements:
112         $directive->id = $this->id($hash->offsetGet('ID'));
113         $id = $directive->id->toString(); // convenience
114
115         if (isset($hash['TYPE'])) {
116             $type = explode('/', $hash->offsetGet('TYPE'));
117             if (isset($type[1])) {
118                 $directive->typeAllowsNull = true;
119             }
120             $directive->type = $type[0];
121         } else {
122             throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined");
123         }
124
125         if (isset($hash['DEFAULT'])) {
126             try {
127                 $directive->default = $this->varParser->parse(
128                     $hash->offsetGet('DEFAULT'),
129                     $directive->type,
130                     $directive->typeAllowsNull
131                 );
132             } catch (HTMLPurifier_VarParserException $e) {
133                 throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'");
134             }
135         }
136
137         if (isset($hash['DESCRIPTION'])) {
138             $directive->description = $hash->offsetGet('DESCRIPTION');
139         }
140
141         if (isset($hash['ALLOWED'])) {
142             $directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED')));
143         }
144
145         if (isset($hash['VALUE-ALIASES'])) {
146             $directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
147         }
148
149         if (isset($hash['ALIASES'])) {
150             $raw_aliases = trim($hash->offsetGet('ALIASES'));
151             $aliases = preg_split('/\s*,\s*/', $raw_aliases);
152             foreach ($aliases as $alias) {
153                 $directive->aliases[] = $this->id($alias);
154             }
155         }
156
157         if (isset($hash['VERSION'])) {
158             $directive->version = $hash->offsetGet('VERSION');
159         }
160
161         if (isset($hash['DEPRECATED-USE'])) {
162             $directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE'));
163         }
164
165         if (isset($hash['DEPRECATED-VERSION'])) {
166             $directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION');
167         }
168
169         if (isset($hash['EXTERNAL'])) {
170             $directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL')));
171         }
172
173         $interchange->addDirective($directive);
174     }
175
176     /**
177      * Evaluates an array PHP code string without array() wrapper
178      * @param string $contents
179      */
180     protected function evalArray($contents)
181     {
182         return eval('return array(' . $contents . ');');
183     }
184
185     /**
186      * Converts an array list into a lookup array.
187      * @param array $array
188      * @return array
189      */
190     protected function lookup($array)
191     {
192         $ret = array();
193         foreach ($array as $val) {
194             $ret[$val] = true;
195         }
196         return $ret;
197     }
198
199     /**
200      * Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id
201      * object based on a string Id.
202      * @param string $id
203      * @return HTMLPurifier_ConfigSchema_Interchange_Id
204      */
205     protected function id($id)
206     {
207         return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
208     }
209
210     /**
211      * Triggers errors for any unused keys passed in the hash; such keys
212      * may indicate typos, missing values, etc.
213      * @param HTMLPurifier_StringHash $hash Hash to check.
214      */
215     protected function _findUnused($hash)
216     {
217         $accessed = $hash->getAccessed();
218         foreach ($hash as $k => $v) {
219             if (!isset($accessed[$k])) {
220                 trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE);
221             }
222         }
223     }
224 }
225
226 // vim: et sw=4 sts=4