[1.2.0] Allow configuration directives to permit null values. ConfigDoc updated accor...
[htmlpurifier.git] / configdoc / generate.php
blob9332835680c6122111a7bfeca560d9529e2cc007
1 <?php
3 /**
4 * Generates XML and HTML documents describing configuration.
5 */
7 /*
8 TODO:
9 - make XML format richer (see below)
10 - extend XSLT transformation (see the corresponding XSLT file)
11 - allow generation of packaged docs that can be easily moved
12 - multipage documentation
13 - determine how to multilingualize
14 - factor out code into classes
17 // ---------------------------------------------------------------------------
18 // Check and configure environment
20 if (version_compare('5', PHP_VERSION, '>')) exit('Requires PHP 5 or higher.');
21 error_reporting(E_ALL);
24 // ---------------------------------------------------------------------------
25 // Include HTML Purifier library
27 set_include_path('../library' . PATH_SEPARATOR . get_include_path());
28 require_once 'HTMLPurifier.php';
31 // ---------------------------------------------------------------------------
32 // Setup convenience functions
34 function appendHTMLDiv($document, $node, $html) {
35 global $purifier;
36 $html = $purifier->purify($html);
37 $dom_html = $document->createDocumentFragment();
38 $dom_html->appendXML($html);
40 $dom_div = $document->createElement('div');
41 $dom_div->setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
42 $dom_div->appendChild($dom_html);
44 $node->appendChild($dom_div);
48 // ---------------------------------------------------------------------------
49 // Load copies of HTMLPurifier_ConfigDef and HTMLPurifier
51 $schema = HTMLPurifier_ConfigSchema::instance();
52 $purifier = new HTMLPurifier();
55 // ---------------------------------------------------------------------------
56 // Generate types.xml, a document describing the constraint "type"
58 $types_document = new DOMDocument('1.0', 'UTF-8');
59 $types_root = $types_document->createElement('types');
60 $types_document->appendChild($types_root);
61 $types_document->formatOutput = true;
62 foreach ($schema->types as $name => $expanded_name) {
63 $types_type = $types_document->createElement('type', $expanded_name);
64 $types_type->setAttribute('id', $name);
65 $types_root->appendChild($types_type);
67 $types_document->save('types.xml');
70 // ---------------------------------------------------------------------------
71 // Generate configdoc.xml, a document documenting configuration directives
73 $dom_document = new DOMDocument('1.0', 'UTF-8');
74 $dom_root = $dom_document->createElement('configdoc');
75 $dom_document->appendChild($dom_root);
76 $dom_document->formatOutput = true;
78 // add the name of the application
79 $dom_root->appendChild($dom_document->createElement('title', 'HTML Purifier'));
82 TODO for XML format:
83 - create a definition (DTD or other) once interface stabilizes
86 foreach($schema->info as $namespace_name => $namespace_info) {
88 $dom_namespace = $dom_document->createElement('namespace');
89 $dom_root->appendChild($dom_namespace);
91 $dom_namespace->setAttribute('id', $namespace_name);
92 $dom_namespace->appendChild(
93 $dom_document->createElement('name', $namespace_name)
95 $dom_namespace_description = $dom_document->createElement('description');
96 $dom_namespace->appendChild($dom_namespace_description);
97 appendHTMLDiv($dom_document, $dom_namespace_description,
98 $schema->info_namespace[$namespace_name]->description);
100 foreach ($namespace_info as $name => $info) {
102 $dom_directive = $dom_document->createElement('directive');
103 $dom_namespace->appendChild($dom_directive);
105 $dom_directive->setAttribute('id', $namespace_name . '.' . $name);
106 $dom_directive->appendChild(
107 $dom_document->createElement('name', $name)
110 $dom_constraints = $dom_document->createElement('constraints');
111 $dom_directive->appendChild($dom_constraints);
113 $dom_type = $dom_document->createElement('type', $info->type);
114 if ($info->allow_null) {
115 $dom_type->setAttribute('allow-null', 'yes');
117 $dom_constraints->appendChild($dom_type);
119 if ($info->allowed !== true) {
120 $dom_allowed = $dom_document->createElement('allowed');
121 $dom_constraints->appendChild($dom_allowed);
122 foreach ($info->allowed as $allowed => $bool) {
123 $dom_allowed->appendChild(
124 $dom_document->createElement('value', $allowed)
129 $raw_default = $schema->defaults[$namespace_name][$name];
130 if (is_bool($raw_default)) {
131 $default = $raw_default ? 'true' : 'false';
132 } elseif (is_string($raw_default)) {
133 $default = "\"$raw_default\"";
134 } elseif (is_null($raw_default)) {
135 $default = 'null';
136 } else {
137 $default = print_r(
138 $schema->defaults[$namespace_name][$name], true
142 $dom_default = $dom_document->createElement('default', $default);
144 // remove this once we get a DTD
145 $dom_default->setAttribute('xml:space', 'preserve');
147 $dom_constraints->appendChild($dom_default);
149 $dom_descriptions = $dom_document->createElement('descriptions');
150 $dom_directive->appendChild($dom_descriptions);
152 foreach ($info->descriptions as $file => $file_descriptions) {
153 foreach ($file_descriptions as $line => $description) {
154 $dom_description = $dom_document->createElement('description');
155 $dom_description->setAttribute('file', $file);
156 $dom_description->setAttribute('line', $line);
157 appendHTMLDiv($dom_document, $dom_description, $description);
158 $dom_descriptions->appendChild($dom_description);
166 // print_r($dom_document->saveXML());
168 // save a copy of the raw XML
169 $dom_document->save('configdoc.xml');
172 // ---------------------------------------------------------------------------
173 // Generate final output using XSLT
175 // load the stylesheet
176 $xsl_stylesheet_name = 'plain';
177 $xsl_stylesheet = "styles/$xsl_stylesheet_name.xsl";
178 $xsl_dom_stylesheet = new DOMDocument();
179 $xsl_dom_stylesheet->load($xsl_stylesheet);
181 // setup the XSLT processor
182 $xsl_processor = new XSLTProcessor();
184 // perform the transformation
185 $xsl_processor->importStylesheet($xsl_dom_stylesheet);
186 $html_output = $xsl_processor->transformToXML($dom_document);
188 // some slight fudges to preserve backwards compatibility
189 $html_output = str_replace('/>', ' />', $html_output); // <br /> not <br>
190 $html_output = str_replace(' xmlns=""', '', $html_output); // rm unnecessary xmlns
192 if (class_exists('Tidy')) {
193 // cleanup output
194 $config = array(
195 'indent' => true,
196 'output-xhtml' => true,
197 'wrap' => 80
199 $tidy = new Tidy;
200 $tidy->parseString($html_output, $config, 'utf8');
201 $tidy->cleanRepair();
202 $html_output = (string) $tidy;
205 // write it to a file (todo: parse into seperate pages)
206 file_put_contents("$xsl_stylesheet_name.html", $html_output);
209 // ---------------------------------------------------------------------------
210 // Output for instant feedback
212 if (php_sapi_name() != 'cli') {
213 echo $html_output;
214 } else {
215 echo 'Files generated successfully.';