/[drupal]/contributions/modules/xmlcontent/xmlcontent.module
ViewVC logotype

Contents of /contributions/modules/xmlcontent/xmlcontent.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.10 - (show annotations) (download) (as text)
Sun Mar 29 02:20:25 2009 UTC (7 months, 4 weeks ago) by weam
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +0 -3 lines
File MIME type: text/x-php
bug #417056 removed ending ?> and extra line
1 <?php
2 // $Id$
3
4 /**
5 * The XML Content module enables you to store XML content
6 * in a node body and use the drupal built-in filter system
7 * to transform it to HTML with a pre-configured XSLT
8 * script of your choice.
9 *
10 * It also provides optional XML input (on-submit) checks for
11 * well-formedness and schema-validation.
12 *
13 * @version $Id$
14 * @author Weam Abu Zaki
15 */
16
17 /**
18 * Implementation of hook_enable().
19 */
20 function xmlcontent_enable() {
21 // until hook_requirements works reliably!
22 if (!_xmlcontent_check_xml_support()) {
23 drupal_set_message(t('XML Content: Your instalation of PHP does not have appropriate XML/XSL support. <b>XML Content should be disabled</b>.'), 'error');
24 }
25 }
26
27 /**
28 * Implementation of hook_filter().
29 */
30 function xmlcontent_filter($op, $delta = 0, $format = -1, $text = '') {
31 switch ($op) {
32 case 'list':
33 return array(0 => t('XML Content XSLT filter'));
34
35 case 'no cache':
36 return true; // still in development stage, remove this in production site
37
38 case 'description':
39 return t('Allows users to post XML node content and get it transformed through a configured XSLT script');
40
41 case 'process':
42 $xslt_path = drupal_get_path('module', 'xmlcontent'). '/' . variable_get("xmlcontent_xslt_path_$format", '');
43 return _xmlcontent_transform($text, $xslt_path);
44
45 case 'settings':
46 return _xmlcontent_filter_settings($format);
47 default:
48 return $text;
49 }
50 }
51
52 /**
53 * Implementation of hook_filter_tips().
54 */
55 function xmlcontent_filter_tips($delta, $format, $long = false) {
56 if ($long) {
57 return t('The whole node body must be a valid XML document. Schema validation and XSLT file path are configured from the Input Format configuration page.');
58 } else {
59 return t('You can use <b>XML Content XSLT Filter</b> to set the whole node body to a valid XML document and transform it to HTML with XSLT.');
60 }
61 }
62
63 /**
64 * Implementation of hook_nodeapi()
65 */
66 function xmlcontent_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
67 switch ($op) {
68 case 'validate':
69 // check for PHP Dom support
70 if (!_xmlcontent_check_xml_support()) {
71 return;
72 }
73 // Does the input format of this node use XML Content filter?
74 $format = filter_resolve_format($node->format);
75 $module = db_result(db_query('SELECT module FROM {filters} WHERE format = %d', $format));
76 if ($module != 'xmlcontent') {
77 return;
78 }
79
80 // Get the validation type configured for this format
81 $validation = variable_get("xmlcontent_schema_type_$format", 'none');
82 if ($validation == 'none') {
83 return;
84 }
85
86 $schema_path = drupal_get_path('module', 'xmlcontent'). '/' . variable_get("xmlcontent_schema_path_$format",'');
87 if (!is_file($schema_path) && ($validation == 'xsd' or $validation == 'rng')) {
88 $schema_path = null;
89 watchdog( 'xmlcontent', t('Validation required but no schema file'), WATCHDOG_WARNING );
90 }
91
92 // initialize libxml error handling
93 libxml_clear_errors();
94 libxml_use_internal_errors(true);
95
96 if (!_xmlcontent_validate($node->body, $validation, $schema_path)) {
97 form_set_error('body', t('XML Content: Invalid XML') . _xmlcontent_libxml_errors_string());
98 }
99
100 libxml_clear_errors();
101 break;
102 }
103 }
104
105 /**
106 * Validates the sent XML according to the specified validation type.
107 * @param xml
108 * The XML content to be validated as a string
109 * @param validation
110 * The validation type required (string): possible values are (none, wellformed,dtd,xsd,rng)
111 * @param schema_path
112 * The path to the schema file
113 */
114 function _xmlcontent_validate($xml, $validation = 'wellformed', $schema_path = null) {
115 if (!$xml) {
116 return false;
117 }
118 $dom = new DomDocument('1.0', 'UTF-8');
119 switch ($validation) {
120 case 'none':
121 $ok = true;
122 break;
123
124 case 'wellformed':
125 $ok = $dom->loadXML($xml);
126 break;
127
128 case 'dtd':
129 if ($ok = $dom->loadXML($xml)) {
130 $ok = $dom->validate();
131 }
132 break;
133
134 case 'xsd':
135 if ($ok = $dom->loadXML($xml)) {
136 $ok = $dom->schemaValidate($schema_path);
137 }
138 break;
139
140 case 'rng':
141 if ($ok = $dom->loadXML($xml)) {
142 $ok = $dom->relaxNGValidate($schema_path);
143 }
144 break;
145 }
146 return $ok;
147 }
148
149 /**
150 * Settings for the filter.
151 */
152 function _xmlcontent_filter_settings($format) {
153 $form['xmlcontent'] = array(
154 '#type' => 'fieldset',
155 '#title' => t('XML Content'),
156 '#collapsible' => TRUE,
157 '#collapsed' => FALSE,
158 );
159 $form['xmlcontent']["xmlcontent_xslt_path_$format"] = array(
160 '#type' => 'textfield',
161 '#title' => t('XSLT Script File Path'),
162 '#default_value' => variable_get("xmlcontent_xslt_path_$format", ''),
163 '#field_prefix' => drupal_get_path('module', 'xmlcontent'). '/',
164 '#description' => t('The file path to the XSLT script to be used for this format.'),
165 );
166 $form['xmlcontent']['validation'] = array(
167 '#type' => 'fieldset',
168 '#title' => t('XML Validation'),
169 '#collapsible' => TRUE,
170 '#collapsed' => FALSE,
171 );
172 $form['xmlcontent']['validation']["xmlcontent_schema_type_$format"] = array(
173 '#type' => 'select',
174 '#title' => t('Validation Type'),
175 '#default_value' => variable_get("xmlcontent_schema_type_$format", 'wellformed'),
176 '#options' => array('none' => '[None]', 'wellformed' => 'Well-formedness Only', 'dtd' => 'DTD Validation', 'xsd' => 'XML Schema Validation', 'rng' => 'RNG Schema Validation') ,
177 '#description' => t('The level of validation required on this format.'),
178 );
179
180 $form['xmlcontent']['validation']["xmlcontent_schema_path_$format"] = array(
181 '#type' => 'textfield',
182 '#title' => t('Schema File Path'),
183 '#default_value' => variable_get("xmlcontent_schema_path_$format", ''),
184 '#field_prefix' => drupal_get_path('module', 'xmlcontent'). '/',
185 '#description' => t('The file path to the XSD/RNG schema to be used for validating this format. <b>Leave blank if you do not need schema validation</b>'),
186 );
187 return $form;
188 }
189
190 /**
191 * Performs the XML to HTML processing operation.
192 * @param xml
193 * The xml document as a text string (mostly obtained from the body of a node)
194 * @param path_to_xslt
195 * The file path to the XSLT script to be used for processing
196 * @param params
197 * An array of name-value pairs for special parameters to be passed to the XSLT processor
198 * before invoking it on the XML data document. Examples include namespace settings and
199 * XSL parameters.
200 */
201 function _xmlcontent_transform($xml, $path_to_xslt, $params = array()) {
202 if (!$xml) {
203 watchdog('xmlcontent',"Empty XML content", WATCHDOG_WARNING);
204 return $xml;
205 }
206
207 // make sure that PHP has the required XSLT support, and failsafe if not
208 if (!_xmlcontent_check_xml_support()) {
209 watchdog('xmlcontent',"XML/XSLT PHP support misconfigured", WATCHDOG_ERROR);
210 return $xml;
211 }
212
213 // check that the XSLT file exists
214 if (!is_file($path_to_xslt)) {
215 watchdog('xmlcontent',"XSLT unavailable, invalid file or path: '$path_to_xslt'", WATCHDOG_ERROR);
216 return $xml;
217 }
218
219 // Load the XML document
220 $dom = new DomDocument('1.0', 'UTF-8');
221 $valid = $dom->loadXML($xml);
222 if (!$valid) {
223 watchdog('xmlcontent', "Invalid XML Content", WATCHDOG_WARNING);
224 return $xml;
225 }
226
227 // Load the XSLT script
228 // TODO: is there a way to cache it, or not necessary
229 $xsl = new DomDocument('1.0', 'UTF-8');
230 $xsl->load($path_to_xslt);
231
232 // Create the XSLT processor
233 $proc = new XsltProcessor();
234 $xsl = $proc->importStylesheet($xsl);
235
236 // Currently the empty &quot;&quot; namespace is used.
237 define (XMLCONTENT_DFLT_NS, '');
238
239 // initialize the processor with the parameters when defined
240 foreach($params as $key => $value) {
241 $proc->setParameter(XMLCONTENT_DFLT_NS, $key, $value);
242 }
243
244 // Transform
245 $newdom = $proc->transformToDoc($dom);
246
247 // Return the output as XML text (in fact subset of XHTML, depending on the XSLT script)
248 return $newdom->saveXML();
249 }
250
251
252 /*
253 * Formats and returns libxml errors as a ul
254 */
255 function _xmlcontent_libxml_errors_string() {
256 $errors = libxml_get_errors();
257 $errstr = '<ul>';
258 foreach ($errors as $error) {
259 $errstr .= '<li>';
260 switch ($error->level) {
261 case LIBXML_ERR_WARNING:
262 $errstr .= "<b>Warning $error->code</b>: ";
263 break;
264 case LIBXML_ERR_ERROR:
265 $errstr .= "<b>Error $error->code</b>: ";
266 break;
267 case LIBXML_ERR_FATAL:
268 $errstr .= "<b>Fatal Error $error->code</b>: ";
269 break;
270 }
271 /* if ($error->file) {
272 $return .= " in <b>$error->file</b>";
273 }*/
274 $errstr .= trim($error->message);
275 $errstr .= '</li>';
276 }
277 return $errstr . '</ul>';
278 }
279
280
281 /**
282 * Checks if the running PHP installation has Dom support.
283 * TODO: needs more advanced checks
284 */
285 function _xmlcontent_check_xml_support() {
286 if (!class_exists('DomDocument') || !class_exists('XsltProcessor') || !function_exists('libxml_get_errors')) {
287 return false;
288 } else {
289 return true;
290 }
291 }

  ViewVC Help
Powered by ViewVC 1.1.2