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

Contents of /contributions/modules/drutex/drutex.module

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


Revision 1.23 - (show annotations) (download) (as text)
Sun Sep 9 19:02:44 2007 UTC (2 years, 2 months ago) by darthsteven
Branch: MAIN
CVS Tags: DRUPAL-5--1-2, HEAD
Branch point for: DRUPAL-5--2, DRUPAL-6--1
Changes since 1.22: +19 -18 lines
File MIME type: text/x-php
Only load the remote menu hooks if the module is active
1 <?php
2 // $Id: drutex.module,v 1.22 2007/09/09 18:57:38 darthsteven Exp $
3
4 /**
5 * @file
6 * DruTeX core functions and interaction interface with Drupal.
7 */
8
9 /**
10 * Implementation of hook_filter().
11 */
12 function drutex_filter($op, $delta = 0, $format = -1, $text = '') {
13 switch ($op) {
14 case 'list':
15 return array(0 => t('DruTeX'));
16
17 case 'description':
18 return t('Allows users to render LaTeX/TeX in many different ways.');
19
20 case "process":
21 return drutex_node2html($text, $format);
22
23 case 'settings':
24 return _drutex_filter_settings($format);
25
26 default:
27 return $text;
28 }
29 }
30
31 /**
32 * Implementation of hook_menu().
33 */
34 function drutex_menu($may_cache) {
35 $items = array();
36
37 if ($may_cache) {
38 if (drutex_submodule_is_active('remote')) {
39 $items[] = array(
40 'path' => 'drutex/remote',
41 'title' => 'Drutex Remote Rendering',
42 'access'=> TRUE,
43 'callback' => 'drutex_remote_do_render',
44 'type' => MENU_CALLBACK,
45 );
46
47 $items[] = array(
48 'path' => 'admin/settings/drutex/remote',
49 'title' => 'DruTeX Settings',
50 'description' => 'Adjusts the settings for the remote LaTeX rendering interface',
51 'callback' => 'drupal_get_form',
52 'access' => user_access('administer site configuration'),
53 'callback arguments' => array('drutex_remote_settings'),
54 );
55 }
56 }
57 else {
58 if (drutex_submodule_is_active('pdf')) {
59 $items[] = array(
60 'path' => 'drutex/pdf',
61 'title' => t('node2pdf'),
62 'callback' => 'drutex_node2pdf_wrapper',
63 'access' => user_access('access pdf files'),
64 'type' => MENU_CALLBACK);
65
66 $items[] = array(
67 'path' => 'drutex/latex',
68 'title' => t('node2latex'),
69 'callback' => 'drutex_node2latex_wrapper',
70 'access' => user_access('access latex source'),
71 'type' => MENU_CALLBACK);
72 }
73 }
74
75
76
77 drutex_set_stylesheet();
78
79 return $items;
80 }
81
82 /**
83 * Extended variable-get function.
84 *
85 * drutex_var_get('a_b_c') calls variable_get($ask, drutex_var_default($ask))
86 * with $ask = 'a_b_c', $ask = 'a_b', $ask = 'a' ... until a return value != null is found.
87 *
88 * @param $ask
89 * The query string, e.g. "drutex_dpi_$format".
90 */
91 function drutex_var_get($ask) {
92 while ($ask) {
93 $res = variable_get($ask, drutex_var_default($ask));
94
95 if (!is_null($res)) {
96 /* return drutex dirs and urls always without trailing slash */
97 if (strpos($ask, 'drutex_dir') === 0 || strpos($ask, 'drutex_url') === 0) {
98 return rtrim($res, '/');
99 }
100 else {
101 return $res;
102 }
103 }
104
105 $ask = substr($ask, 0, strrpos($ask, '_'));
106 }
107
108 return NULL;
109 }
110
111
112 /**
113 * DruTeX default values.
114 *
115 * @param $ask
116 * The query string, e.g. "drutex_dpi".
117 */
118 function drutex_var_default($ask) {
119 /* Defaults Array */
120 static $D = array();
121
122 if (empty($D)) {
123 $D['drutex'] = NULL;
124
125 /* Directories */
126 $D['drutex_dir'] = dirname(__FILE__);
127 $D['drutex_dir_images'] = variable_get('file_directory_path', 'files') .'/tex';
128 $D['drutex_dir_temporary'] = variable_get('file_directory_temp', FILE_DIRECTORY_TEMP);
129 $D['drutex_url_images'] = variable_get('file_directory_path', 'files') .'/tex';
130
131 /* other */
132 $D['drutex_dpi'] = '107';
133 $D['drutex_imagetype'] = 'png';
134 $D['drutex_stylesheet'] = drupal_get_path('module', 'drutex') .'/drutex.css';
135 $D['drutex_conversion'] = 'dvipng';
136
137 $D = array_merge($D, drutex_submodule_invoke_all('defaults'));
138 }
139
140 if (isset($D[$ask])) {
141 return $D[$ask];
142 }
143 else {
144 return NULL;
145 }
146 }
147
148 /**
149 * Filter-settings page.
150 */
151 function _drutex_filter_settings($format = -1) {
152 $form['drutex_submodules'] = array(
153 '#type' => 'fieldset',
154 '#title' => t('DruTeX :: Submodules'),
155 '#collapsible' => TRUE,
156 '#collapsed' => FALSE
157 );
158
159 $submodule_objects = drutex_submodule_objects($format);
160 usort($submodule_objects, '_drutex_weight_sort_cmp');
161
162 /* list all submodules that can be (de)activated */
163 foreach ($submodule_objects as $obj) {
164 if ($obj->toggle) {
165 $form['drutex_submodules']["drutex_{$obj->submodule}_active_{$format}"] = array(
166 '#type' => 'checkbox',
167 '#title' => $obj->title,
168 '#default_value' => $obj->active,
169 '#description' => $obj->description
170 );
171 }
172 }
173
174 /* try to create the image directory and set the rights
175 if not done already
176 */
177
178 $image_dir = drutex_var_get("drutex_dir_images_$format");
179
180 if (!is_writable($image_dir)) {
181 if (file_exists($image_dir)) {
182 chmod($image_dir, 0777);
183 }
184 else {
185 mkdir($image_dir);
186 }
187 }
188
189 /* global settings
190 that means: settings all submodules can share
191 but it remains filter specific
192 */
193
194 $form['drutex_base'] = array(
195 '#type' => 'fieldset',
196 '#title' => t('DruTeX :: Base Settings'),
197 '#collapsible' => TRUE,
198 '#collapsed' => FALSE
199 );
200
201 /* determine whether temporary dir is writeable */
202 $is_writable = is_writable(drutex_var_get("drutex_dir_temporary_$format"));
203
204 $form['drutex_base']["drutex_dir_temporary_$format"] = array(
205 '#type' => 'textfield',
206 '#title' => t('Temporary directory'),
207 '#size' => 80,
208 '#maxlength' => 100,
209 '#default_value' => drutex_var_get("drutex_dir_temporary_$format"),
210 '#description' => t('Directory for temporaray actions. Has to be writable by apache.'),
211 '#attributes' => $is_writable ? array() : array('style' => 'border-color:red')
212 );
213
214 /* determine whether image dir is writeable */
215 $is_writable = is_writable(drutex_var_get("drutex_dir_images_$format"));
216
217 $form['drutex_base']["drutex_dir_images_$format"] = array(
218 '#type' => 'textfield',
219 '#title' => t('Image directory'),
220 '#size' => 80,
221 '#maxlength' => 100,
222 '#default_value' => drutex_var_get("drutex_dir_images_$format"),
223 '#description' => t('Directory where images are saved. Has to be writable by apache.'),
224 '#attributes' => $is_writable ? array() : array('style' => 'border-color:red')
225 );
226
227
228
229 $form['drutex_base']["drutex_url_images_$format"] = array(
230 '#type' => 'textfield',
231 '#title' => t('Image URL'),
232 '#size' => 80,
233 '#maxlength' => 100,
234 '#default_value' => drutex_var_get("drutex_url_images_$format"),
235 '#description' => t('URL that points to the Image directory. Can be a complete URL or a path relative to the Drupal base dir (recommended).')
236 );
237
238 $form['drutex_base']['note2'] = array(
239 '#value' => t('The image directory may be used by some submodules to place
240 other files in there, e.g. pdf and tex files.')
241 );
242
243
244 /*
245 provide submodule-specific settings
246 */
247
248 foreach ($submodule_objects as $obj) {
249 if (drutex_submodule_hook($obj->submodule, 'filter_settings')) {
250 $form["drutex_{$obj->submodule}"] = array(
251 '#type' => 'fieldset',
252 '#title' => "DruTeX :: {$obj->title}",
253 '#collapsible' => TRUE,
254 '#collapsed' => !$obj->active
255 );
256
257 $form["drutex_{$obj->submodule}"] = array_merge(
258 $form["drutex_{$obj->submodule}"],
259 drutex_submodule_invoke($obj->submodule, 'filter_settings', $format)
260 );
261 }
262 }
263
264 return $form;
265 }
266
267 /**
268 * Set DruTeX stylesheet to HTML head.
269 */
270 function drutex_set_stylesheet() {
271 static $done = FALSE;
272
273 if (!$done) {
274 $css = drutex_var_get("drutex_stylesheet");
275 if (!empty($css)) {
276 drupal_add_css($css, 'module');
277 }
278 $done = TRUE;
279 }
280 }
281
282 /**
283 * Convert DruTeX content to HTML, applying LaTeX2HTML filters and so on.
284 *
285 * @param $text
286 * The text to convert to HTML, e.g. the content of a node.
287 * @param $format
288 * The input format to look for the DruTeX settings.
289 * @return
290 * The text after applying all transformation rules.
291 */
292 function drutex_node2html($text, $format = -1) {
293 /* preprocess */
294 foreach (drutex_submodule_implements('node2html_preprocess', $format) as $submodule) {
295 $text = drutex_submodule_invoke($submodule, 'node2html_preprocess', $text, $format);
296 }
297
298 /* main cycle */
299 $A = drutex_submodule_invoke_all('node2html', "format=$format");
300 $B = module_invoke_all('drutex2html');
301 $entities = array_merge($A, $B);
302 usort($entities, '_drutex_weight_sort_cmp');
303
304 foreach ($entities as $entity) {
305 list($pattern, $replacement) = _drutex_create_regex($entity, $format);
306 $text = preg_replace($pattern, $replacement, $text);
307 }
308
309 $text = _drutex_unhide_all($text);
310
311 /* postprocess */
312 foreach (drutex_submodule_implements('node2html_postprocess', $format) as $submodule) {
313 $text = drutex_submodule_invoke($submodule, 'node2html_postprocess', $text, $format);
314 }
315
316 return $text;
317 }
318
319 /**
320 * Helping function to sort a list of objects by their ->weight attributes.
321 */
322 function _drutex_weight_sort_cmp($a, $b) {
323 if (!isset($a->weight)) {
324 $a->weight = 1000;
325 }
326 if (!isset($b->weight)) {
327 $b->weight = 1000;
328 }
329 if ($a->weight == $b->weight) {
330 return 0;
331 }
332 return ($a->weight < $b->weight) ? -1 : 1;
333 }
334
335
336 /**
337 * Convert entity (transformation description) object to regular expression (pattern + replacement).
338 *
339 * @param $entity
340 * An entity object (this includes a transformation description).
341 * @param $format
342 * The input format to look for the DruTeX settings.
343 * @return
344 * array($pattern, $replacement)
345 */
346 function _drutex_create_regex($entity, $format = -1) {
347 $pattern = $entity->pattern;
348 $replacement = preg_replace('@<var>([^<]+)</var>@se', "$$1", $entity->replacement);
349
350 switch ($entity->type) {
351 case 'latex-command':
352 $pattern = "/\\\\$pattern\\{(.*?)\\}/s";
353 return array($pattern, $replacement);
354
355 case 'tag':
356 $pattern = "@<$pattern( [^>]*)?>(.*?)</$pattern>@s";
357 return array($pattern, $replacement);
358
359 case 'tag2command':
360 $pattern = "@<$pattern( [^>]*)?>(.*?)</$pattern>@s";
361 $replacement = "\\\\$replacement\{\$2}";
362 return array($pattern, $replacement);
363
364 case 'regex':
365 default:
366 return array($pattern, $replacement);
367 }
368 }
369
370 /**
371 * Convert string with XML style attributes to array.
372 *
373 * For instance drutex_parse_attributes('dpi="100" cLaSs="Math"') will give
374 * array('dpi' => '100', 'class' => 'Math').
375 *
376 * @param $entity
377 * An entity object (this includes a transformation description).
378 * @param $format
379 * The input format to look for the DruTeX settings.
380 * @return
381 * Array with attribute-names as keys and attribute-values as values.
382 */
383 function drutex_parse_attributes($subject) {
384 $matches = array();
385 preg_match_all('/([a-zA-Z]+)="([^"]*)"/', $subject, $matches, PREG_SET_ORDER);
386
387 $attributes = array();
388 foreach ($matches as $match) {
389 $attributes[strtolower($match[1])] = $match[2];
390 }
391
392 return $attributes;
393 }
394
395 /**
396 * Do the reverse of drutex_parse_attributes().
397 *
398 * For instance drutex_merge_attributes(array('dpi' => '100', 'cLaSs' => 'Math')) will give
399 * 'dpi="100" class="Math"'.
400 */
401 function drutex_merge_attributes($A) {
402 $str = '';
403 foreach ($A as $key => $val) {
404 $str .= strtolower($key) . "=\"$val\" ";
405 }
406 return trim($str);
407 }
408
409 /**
410 * Hide some chunks of text from further processing.
411 *
412 * This is an important function to aim the parsing process.
413 * Let's say, you want to replace [tex]$x^2$[/tex] by
414 * [img src="xxx.png" alt="[tex]$x^2$[/tex]" /].
415 * This would result in a failure, when the $xyz$ environment is processed now.
416 *
417 * The solution is to hide "[tex]$x^2$[/tex]" from further processing.
418 * Just write:
419 * '[img src="xxx.png" alt="' . _drutex_hide('set', '[tex]$x^2$[/tex]') . '" /]'
420 *
421 * This would result in something like:
422 * [img src="xxx.png" alt="1f3870be274f6c49b3e31a0c6728957f:5:" /]
423 *
424 * The subject is saved, e.g. in the above example _drutex_hide('get', 5) is == '[tex]$x^2$[/tex]'.
425 *
426 * All hidden strings are automatically unhidden by DruTeX after the main processing is done.
427 *
428 * @param $cmd
429 * Either 'set' a string to hide or 'get' the string corresponding to a number.
430 * @param $subject
431 * If 'set', the text to hide. If 'get', the number that identifies the string (without the secret hash key).
432 * @return
433 * If 'set', a string of the form "secret:number:". If 'get', the originally hidden text.
434 */
435 function _drutex_hide($cmd = 'get', $subject = '') {
436 static $hidden = array();
437 static $count = 0;
438
439 if ($cmd == 'set') {
440 $hidden[$count] = _drutex_unescape($subject);
441 return _drutex_secret() . ':' . $count++ . ':';
442 }
443 else if ($cmd == 'get') {
444 $subject = (int)$subject;
445 return $hidden[$subject];
446 }
447 }
448
449 /**
450 * Unhide all hidden strings.
451 *
452 * @param $text
453 * The $text in which to replace the hidden-keys by the originally hidden strings.
454 * This is normally the node's content after applying all transformation rules.
455 * @return
456 * The text with the original strings.
457 */
458 function _drutex_unhide_all($text) {
459 $key = _drutex_secret();
460 return preg_replace("/$key:(\\d+):/se", "_drutex_hide('get', '$1')", $text);
461 }
462
463 /**
464 * Generate a secret (unguessable) key.
465 *
466 * This is used for some parsing, see _drutex_hide().
467 *
468 * @return
469 * The secret key. It remains the same within one Drupal instance.
470 */
471 function _drutex_secret() {
472 static $key = '';
473
474 if (empty($key)) {
475 for ($i = 0; $i < 10; $i++) {
476 $key .= mt_rand();
477 }
478 $key = md5($key);
479 }
480
481 return $key;
482 }
483
484 /**
485 * Unescape what was escaped by preg_replace() when using the 'e' flag.
486 *
487 * E.g. print preg_replace('/(.*)/se', "'$1'", '\'hi\' "mum"') yields 'hi' \"mum\"
488 * and print preg_replace('/(.*)/se', '"$1"', '\'hi\' "mum"') yields \'hi\' "mum".
489 *
490 * In DruTeX we should always use the first variant to avoid confusion.
491 *
492 * @param $text
493 * The text to unescape.
494 * @param $quote
495 * Either "'" or '"'.
496 * @return
497 * The unescaped text.
498 */
499 function _drutex_unescape($text, $quote = '"') {
500 return str_replace("\\$quote", "$quote", $text);
501 }
502
503 /**
504 * Create temporary directory.
505 *
506 * This directory should normally be deleted automatically.
507 */
508 function _drutex_create_temporary_dir($format = -1) {
509 static $n = 1;
510 $dir = drutex_var_get("drutex_dir_temporary_$format") . '/drutex-' . _drutex_secret() . '-' . $n++;
511 mkdir($dir);
512 return $dir;
513 }
514
515 /**
516 * Delete directory with contents.
517 *
518 * No subfolders are supported since DruTeX doesn't needs this.
519 */
520 function _drutex_delete_dir($dir) {
521 if ($handle = opendir($dir)) {
522 while ($item = readdir($handle)) {
523 if ($item != '.' && $item != '..') {
524 unlink("$dir/$item");
525 }
526 }
527 closedir($handle);
528 rmdir($dir);
529 }
530 }
531
532 /**
533 * Copy the contents (only files) of one directory to another.
534 */
535 function _drutex_copy_dir($source, $dest) {
536 if ($handle = opendir($source)) {
537 while ($item = readdir($handle)) {
538 if ($item != '.' && $item != '..') {
539 if(is_file("$source/$item")) {
540 copy("$source/$item", "$dest/$item");
541 }
542 }
543 }
544 closedir($handle);
545 }
546 }
547
548 /**
549 * Get URL where the images are saved.
550 */
551 function drutex_get_image_url($format = -1) {
552 $path = drutex_var_get("drutex_url_images_$format");
553
554 /* different behaviour for absolute and relative paths */
555 if (strpos($path, 'http') === 0) {
556 return rtrim($path, '/');
557 }
558 else {
559 return base_path() . trim($path, '/');
560 }
561 }
562
563 /**
564 * Implementation of hook_nodeapi().
565 *
566 * Notify all submodules when a node changed.
567 */
568 function drutex_nodeapi(&$node, $op, $arg) {
569 drutex_submodule_invoke_all('nodeapi', $node, $op, $arg, "format={$node->format}");
570 }
571
572 /**
573 * Implementation of hook_perm().
574 */
575 function drutex_perm() {
576 return drutex_submodule_invoke_all('perm');
577 }
578
579 /**
580 * Test if a DruTeX submodule is marked active in a given input format.
581 *
582 * @param $submodule
583 * Name of the submodule, e.g. "latex".
584 * @param $format
585 * ID of the input format.
586 * @return
587 * If $format is -1, the submodule only needs to be installed to make the function return TRUE.
588 * If the input format specified by $format doesn't use DruTeX at all, the result will be FALSE.
589 * In every other case, the function returns TRUE, if the submodule is installed and
590 * marked active in the specified input format.
591 */
592 function drutex_submodule_is_active($submodule, $format = -1) {
593 if (is_file(drupal_get_path('module', 'drutex') . "/drutex_{$submodule}.inc")) {
594 if ($format == -1) {
595 return true;
596 }
597 else if (_format_uses_drutex($format) && drutex_var_get("drutex_{$submodule}_active_{$format}")) {
598 return true;
599 }
600 }
601
602 return false;
603 }
604
605 /**
606 * Test if a given input format uses DruTeX at all.
607 *
608 * The format '-1' always 'uses' DruTeX.
609 */
610 function _format_uses_drutex($format = -1) {
611 static $cache;
612
613 if (!isset($cache)) {
614 $cache = array();
615 $result = db_query("SELECT format from {filters} WHERE module = 'drutex'");
616
617 while ($obj = db_fetch_object($result)) {
618 $cache[$obj->format] = true;
619 }
620
621 /* the format -1 always 'uses' DruTeX */
622 $cache[-1] = true;
623 }
624
625 return isset($cache[$format]);
626 }
627
628
629 /**
630 * Collect a list of submodule object.
631 *
632 * This is done by hooking over the subhook 'info'.
633 *
634 * If $format is specified, the objects will have an ->active attribute
635 * that states if the submodule is active in the given input format.
636 *
637 * @param $format
638 * The optional input format id.
639 * @return
640 * Array of info objects.
641 */
642 function drutex_submodule_objects($format = -1) {
643 static $objects;
644
645 if (!isset($objects[$format])) {
646 $objects[$format] = array();
647
648 foreach (drutex_submodule_implements('info') as $submodule) {
649 $obj = drutex_submodule_invoke($submodule, 'info', $format);
650 $obj->submodule = $submodule;
651 $obj->active = drutex_submodule_is_active($submodule, $format);
652 $objects[$format][] = $obj;
653 }
654 }
655
656 return $objects[$format];
657 }
658
659 /**
660 * Determine whether a submodule implements a hook.
661 *
662 * @param $submodule
663 * The name of the submodule (without the .inc extension).
664 * @param $hook
665 * The name of the hook (e.g. "info").
666 * @return
667 * TRUE if the submodule is installed and the hook is implemented.
668 */
669 function drutex_submodule_hook($submodule, $hook) {
670 return function_exists("drutex_{$submodule}_{$hook}");
671 }
672
673 /**
674 * Invoke a hook in a particular submodule.
675 *
676 * @param $submodule
677 * The name of the submodule (without the .inc extension).
678 * @param $hook
679 * The name of the hook to invoke.
680 * @param ...
681 * Arguments to pass to the hook implementation.
682 * @return
683 * The return value of the hook implementation.
684 */
685 function drutex_submodule_invoke() {
686 $args = func_get_args();
687 $submodule = array_shift($args);
688 $hook = array_shift($args);
689
690 if (drutex_submodule_hook($submodule, $hook)) {
691 return call_user_func_array("drutex_{$submodule}_{$hook}", $args);
692 }
693 }
694
695 /**
696 * Collect a list of all DruTeX submodules.
697 *
698 * Submodules have the form drutex_submodulename.inc and reside in the DruTeX directory.
699 *
700 * @param $format
701 * If $format is specified, only the active submodules in this input format will be listed.
702 * If $format is -1, all installed submodules are listed.
703 * @return
704 * An associative array whose keys and values are the names of the submodules.
705 */
706 function drutex_submodule_list($format = -1) {
707 static $list;
708
709 if (!isset($list[$format])) {
710 $list[$format] = array();
711 $path = drupal_get_path('module', 'drutex');
712 $files = file_scan_directory($path, '^drutex_.*\.inc$');
713
714 foreach ($files as $file) {
715 $submodule = substr($file->name, strlen('drutex_'));
716 if (drutex_submodule_is_active($submodule, $format)) {
717 $list[$format][$submodule] = $submodule;
718 }
719 }
720 }
721
722 return $list[$format];
723 }
724
725 /**
726 * Determine which submodules are implementing a hook.
727 *
728 * @param $hook
729 * The name of the hook (e.g. "defaults").
730 * @param $format
731 * ...
732 * @return
733 * An array with the names of the modules which are implementing this hook.
734 */
735 function drutex_submodule_implements($hook, $format = -1) {
736 static $implementations;
737
738 if (!isset($implementations[$hook][$format])) {
739 $implementations[$hook][$format] = array();
740
741 foreach (drutex_submodule_list($format) as $submodule) {
742 if (drutex_submodule_hook($submodule, $hook)) {
743 $implementations[$hook][$format][] = $submodule;
744 }
745 }
746 }
747
748 return $implementations[$hook][$format];
749 }
750
751 /**
752 * Invoke a hook in all (active) submodules that implement it.
753 *
754 * @param $hook
755 * The name of the hook to invoke.
756 * @param ...
757 * Arguments to pass to the hook.
758 * @return
759 * An array of return values of the hook implementations. If submodules return
760 * arrays from their implementations, those are merged into one array.
761 */
762 function drutex_submodule_invoke_all() {
763 $args = func_get_args();
764 $hook = array_shift($args);
765 $return = array();
766 $format = _drutex_rewrite_format_call($args);
767
768 foreach (drutex_submodule_implements($hook, $format) as $submodule) {
769 $result = call_user_func_array("drutex_{$submodule}_{$hook}", $args);
770 if (isset($result) && is_array($result)) {
771 $return = array_merge($return, $result);
772 }
773 else if (isset($result)) {
774 $return[] = $result;
775 }
776 }
777
778 return $return;
779 }
780
781
782 function _drutex_rewrite_format_call(&$args) {
783 $last = array_pop($args);
784 $matches = array();
785
786 if (is_string($last) && preg_match('/^format=([-]?\d+)$/', $last, $matches)) {
787 return $matches[1];
788 }
789 else {
790 array_push($args, $last);
791 return -1; // no filter
792 }
793 }
794
795 $path = drupal_get_path('module', 'drutex');
796
797
798 /* load the submodules */
799 foreach (drutex_submodule_list() as $submodule) {
800 include_once("{$path}/drutex_{$submodule}.inc");
801 }

  ViewVC Help
Powered by ViewVC 1.1.2