1<?php
2/**
3 * DokuWiki Plugin mellelexport (Renderer Component)
4 *
5 * @author  Simon Brüchner <powtac at gmx dot de>
6 */
7
8// must be run within Dokuwiki
9if (!defined('DOKU_INC')) die();
10
11if (!defined('DOKU_LF')) define('DOKU_LF', "\n");
12if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t");
13
14require_once DOKU_INC . 'inc/parser/renderer.php';
15require_once DOKU_INC . 'inc/html.php';
16
17define('DEBUG', isset($_REQUEST['debug']));
18
19function callback_marker($a) {
20    //                          Wiki ID     Wiki Intention          Mellel Name     Mellel Number
21    $colorMap['ffff00'] = 1; // ffff00      Yellow  Bible           Banana          1
22    $colorMap['dda0dd'] = 2; // ff0000      Red                     Salmon          2
23    $colorMap['ffa500'] = 3; // ffa500      Orange                  Cantaloupe      3
24    $colorMap['008000'] = 4; // 008000      Green   Rashi           Lime            4
25    $colorMap['6495ed'] = 5; // 6495ed      Blue    Rashbam         Sky             5
26    $colorMap['ff00ff'] = 6; // ff00ff      Pink    Rut Rabba       Light Lavender  6
27    $colorMap['87ceeb'] = 7; // 87ceeb      Gray    Quara           Magnesium       7
28    $colorMap['00ffff'] = 8; // 00ffff      Black   Other Sirection Midnight        8
29
30
31    $colorMap['ff0000'] = 2;
32    $colorMap['008080'] = 4;
33
34    if (isset($colorMap[$a[1]])) {
35        $result = $colorMap[$a[1]];
36    } else {
37        $result = 1;
38    }
39
40    return 'marker=\''.$result.'\'';
41}
42
43class renderer_plugin_mellelexport extends Doku_Renderer {
44    public $info = array(
45        'cache' => false, // may the rendered result cached?
46        'toc'   => false, // render the TOC?
47    );
48
49    public $opened = 0;
50
51    function getInfo() {
52        return confToHash(dirname(__FILE__).'/plugin.info.txt');
53    }
54
55    function getFormat() {
56        return 'mellelexport';
57    }
58
59    function isSingleton() {
60        return false;
61    }
62
63    function __construct() {
64        require_once dirname(__FILE__).'/mapping.php';
65        $this->conf['m'] = $m;
66    }
67
68    function document_start() {
69
70
71
72        if (!defined('RECURSIVE_MELLEL')) {
73            define('RECURSIVE_MELLEL', TRUE);
74            if (!defined('DEBUG')) {
75                define('DEBUG', TRUE);
76            }
77
78            set_time_limit(60*5);
79
80            if (isset($_REQUEST['list'])) {
81                $dirs = glob('/var/www/kolchose.org/inge/wiki/data/pages/*');
82
83
84                echo '<h1>No files</h1>';
85                foreach ($dirs as $dir) {
86                    if (is_file($dir)) {
87                        $new_dir = $dir;
88//                      $new_dir = str_replace('/var/www/kolchose.org/inge/wiki/data/pages/', '', $new_dir);
89//                      $new_dir = str_replace('.txt', '', $new_dir);
90                        $new_dirs[] = $new_dir;
91                    } else {
92                        echo $dir.'<br />';
93                    }
94                }
95
96                unset($dirs);
97
98                echo '<h1>Formatation ok?</h1>';
99//                $test_file = $new_dirs[1];
100//
101//                echo $test_file.'<br />';
102
103                #var_dump(
104                #self::render(file_get_contents($test_file), 'mellelexport');
105                #);
106
107                $i = 0;
108                foreach($new_dirs as $file) {
109                    echo $file.'<br />';
110                    self::render(file_get_contents($file), 'mellelexport');
111
112                    ob_flush();
113
114                    $i++;
115                    if ($i > 50) {
116                        exit;
117                    }
118                }
119
120                exit;
121            }
122        }
123
124
125
126        plugin_disable('highlight');
127        if (in_array('highlight', plugin_list())) {
128            die('ERROR: highlight loaded 1');
129        }
130
131        global $ID;
132
133        parent::document_start();
134
135        // If older or equal to 2007-06-26, we need to disable caching
136        $dw_version = preg_replace('/[^\d]/', '', getversion());
137        if (version_compare($dw_version, "20070626", "<=")) {
138            $this->info["cache"] = false;
139        }
140
141        $contentType        = class_exists('ZipArchive') ? 'application/zip'    : 'text/xml';
142        $contentFileName    = class_exists('ZipArchive') ? noNS($ID).'.mellel'  : 'main.xml';
143
144        // TODO configuration
145        if (class_exists('ZipArchive') AND true) {
146            $contentFileName = date('Y-m-d_').$contentFileName;
147        }
148
149        // send the content type header, new method after 2007-06-26 (handles caching)
150        if (!DEBUG) {
151            if (version_compare($dw_version, "20070626")) {
152                // store the content type headers in metadata
153                $headers = array(
154                    'Content-Type' => $contentType,
155                    'Content-Disposition' => 'attachment; filename="'.$contentFileName.'";',
156                );
157                p_set_metadata($ID, array('format' => array('mellelexport' => $headers) ));
158            } else {
159                // older method
160                header('Content-Type: '.$contentType);
161                header('Content-Disposition: attachment; filename="'.$contentFileName.'";');
162            }
163        } else {
164            header('Content-Type: text/html; charset=utf-8');
165            echo '<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>'; #<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
166            echo '<table>';
167            echo '<tr><th></th><th>Tag<br />(Wiki)</th><th></th><th>Type</th><th></th><th>Args</th><th>Output<br />(Mellel)</th></tr>';
168        }
169    }
170
171    function document_end() {
172        if (in_array('highlight', plugin_list())) {
173            die('ERROR: highlight loaded '.__FUNCTION__);
174        }
175        global $ID, $INFO;
176
177        // Remove trailing empty pharentis, they can case crashes
178        $this->doc = trim($this->doc);
179
180
181        $pattern = '<p style="ps-0" dir="ltr"></p>';
182        while (substr($this->doc, 0, strlen($pattern)) == $pattern) {
183            $this->doc = substr($this->doc, strlen($pattern));
184        }
185
186        $pattern2 = '<p style="ps-0" dir="ltr"><c style="cs-0"></c></p>';
187        while (substr($this->doc, 0, strlen($pattern2)) == $pattern2) {
188            $this->doc = substr($this->doc, strlen($pattern2));
189        }
190
191
192
193
194        // http://stackoverflow.com/a/14464026/22470
195        $this->doc = preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $this->doc);
196
197        // Global replacements
198
199        // General replace for empty tags?
200        // TODO They do now work properly!
201        #$this->doc = str_replace(array('<c style=\'cs-0\'></c>', '<c style="cs-0"></c>', '<c style="\'cs-0\'"></c>', "<c style=\"\'cs-0\'\"></c>"), '', $this->doc);
202        #$this->doc = str_replace(array('<p style=\'ps-0\' dir=\'ltr\'></p>', '<c style="cs-0" dir="ltr"></c>', '<c style="\'cs-0\'" dir="\'ltr\'"></c>', "<c style=\"\'cs-0\'\" dir=\"'ltr'\"></c>"), '', $this->doc);
203        #$this->doc = str_replace('<p style=\'ps-0\' dir=\'ltr\'></p>', '', $this->doc);
204
205
206
207        if (DEBUG) {
208            // $this->doc = self::remove_whitespace('<?xml version="1.0" encoding="utf-8" ? >'.$this->doc); // does not work.
209            $this->doc = htmlentities($this->doc);
210            echo '</table>';
211            echo '<pre>'.$this->doc.'</pre>';
212        }
213
214
215
216        $template = file_get_contents(dirname(__FILE__).'/template.txt');
217        $this->doc = str_replace('{{CONTENT}}', $this->doc, $template);
218
219
220        // $this->doc = str_replace('{{WIKIPAGE}}', str_replace(array('http://', 'https://'), '', DOKU_URL).'/'.$ID, $this->doc);
221        // $this->doc = str_replace('{{WIKIDATE}}', date('d.m.Y', $INFO['meta']['date']['created']).' by '.$INFO['meta']['last_change']['user'], $this->doc);
222
223        $user       = $INFO['meta']['last_change']['user'];
224        setlocale (LC_TIME, 'de_DE@euro', 'de_DE', 'de', 'ge');
225        $changed_at = date('D d.m.Y', $INFO['meta']['date']['modified']);
226
227        $this->doc = str_replace('{{EDITED_AT}}', $changed_at,  $this->doc);
228        $this->doc = str_replace('{{EDITED_BY}}', $user,        $this->doc);
229
230        $url = str_replace(array('http://', 'https://'), '', DOKU_URL).'/'.$ID;
231        if (strlen($url) > 86) {
232            $url = str_pad($url, 86, '', STR_PAD_LEFT);
233        }
234        $this->doc = str_replace('{{WIKIURL}}',   $url, $this->doc);
235        // $this->doc = str_replace();
236
237
238        self::xml_errors($this->doc);
239        $this->doc = self::remove_whitespace($this->doc);
240
241        $zip = !DEBUG;
242
243        if ($zip AND class_exists('ZipArchive')) {
244
245            $zip = new ZipArchive();
246
247            $tmpZipFile = tempnam(sys_get_temp_dir().'/', 'aaa_inge_wiki_2_mellel_render_');
248            $res = $zip->open($tmpZipFile, ZipArchive::CREATE);
249            if ($res === TRUE) {
250                $zip->addFromString('main.xml', $this->doc);
251                $zip->addFromString('.redlex', '');
252                $zip->close();
253
254                $this->doc = file_get_contents($tmpZipFile);
255                @unlink($tmpZipFile);
256            }
257        }
258
259        // This does not work properly
260        #plugin_enable('highlight');
261
262        if ($this->opened != 0) {
263            die('Wrong number of opened and closed tags!');
264        }
265
266        if (DEBUG) {
267            exit;
268        }
269    }
270
271    function __call($name, $arguments) {
272        if (in_array('highlight', plugin_list())) {
273            die('ERROR: highlight loaded');
274        }
275
276
277        require dirname(__FILE__).'/mapping.php';
278        $this->conf['m'] = $m;
279
280        $m      = $this->conf['m'];
281        $args   = func_get_args();
282
283        array_shift($args);
284        $args   = $args[0];
285
286        if (substr($name, -5) === '_open') {
287            $type   = 'OPEN';
288            $multi  = true;
289            $this->opened++;
290        } elseif (substr($name, -6) === '_close') {
291            $type   = 'CLOSE';
292            $multi  = true;
293            $this->opened--;
294        } else {
295            $type = 'SINGLE';
296            $multi  = false;
297        }
298
299        $tag = str_replace(array('_open', '_close'), '', $name); // not nice but short
300
301
302        // Footnote
303        if (!isset($this->footnote_open)) {
304            $this->footnote_open = false;
305        }
306        if ($tag == 'footnote') {
307            $this->footnote_open  = $type == 'OPEN';
308        }
309
310
311        if (isset($m[$tag])) {
312            $mapping = $m[$tag];
313        } else {
314            foreach ($m as $key => $value) {
315                if (in_array($tag, $value['alias'])) {
316                    $mapping = $m[$key];
317                    break;
318                }
319            }
320        }
321
322
323        if (!is_array($mapping)) {
324            echo '<span style="color:red; display:block">No mapping found for function "'.$name.'()" and tag "'.$tag.'"</span>'.PHP_EOL;
325            $this->doc = 'NO MAPPING FOUND'.$this->doc;
326            exit;
327        }
328
329        // Use different template when p tag (paragraph) is open
330        if (($this->pTagOpen OR $this->sectionTagOpen) AND isset($mapping['template_p_open'])) {
331            $mapping['template'] = $mapping['template_p_open'];
332        }
333
334        // Special template for Headline level 1
335        if (in_array($name, array('header', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) {
336            if ($args[1] == 1) {
337                $mapping['template'] = $mapping['template_level_0'];
338            } else {
339                // Reduce level by 1
340                $args[1]--;
341            }
342        }
343
344        // Get the corresponding part of the template
345        $templateParts = explode($mapping['replacement'], $mapping['template']);
346
347
348        switch ($type) {
349            case 'OPEN':
350                $doc = self::cleanTemplate($templateParts[0]);
351            break;
352
353            case 'CLOSE':
354                $doc = self::cleanTemplate($templateParts[1]);
355            break;
356
357            case 'SINGLE':
358                // $args[0] = str_replace('"',      '&quot;',   $args[0]); // seems not to work in headlines
359                $args[0] = str_replace('&',     '&amp;',    $args[0]);
360                $args[0] = str_replace('\'',    '&apos;',   $args[0]);
361                $args[0] = str_replace('<',     '&lt;',     $args[0]);
362                $args[0] = str_replace('>',     '&gt;',     $args[0]);
363
364                if (isset($args[1]) AND (strpos($name, 'link') != false)) {
365                    $args[1] = str_replace('&',     '&amp;',    $args[1]);
366                    $args[1] = str_replace('\'',    '&apos;',   $args[1]);
367                    $args[1] = str_replace('<',     '&lt;',     $args[1]);
368                    $args[1] = str_replace('>',     '&gt;',     $args[1]);
369                }
370
371                if ($name == 'emaillink') {
372                    $args[0] = 'mailto:'.$args[0];
373                }
374
375                // Add link text if there is none
376                if (($name === 'internallink' OR $name === 'externallink' OR $name === 'emaillink') AND empty($args[1])) {
377                    $args[1] = $args[0];
378                }
379
380                // Link text " -> &qout;
381                if (($name === 'internallink' OR $name === 'externallink' OR $name === 'emaillink') AND empty($args[1])) {
382                    $args[1] = str_replace('"', '&quot;', $args[1]);
383                }
384
385                // Full URL for internal links
386                if ($name === 'internallink') {
387                    $args[0] = DOKU_URL.$args[0];
388                }
389
390                // Code linebreaks
391                if ($name === 'code') {
392                    $args[0] = str_replace("\n", '<dir-break-space/>', $args[0]);
393                }
394
395                // Replace linebreaks with a single space
396                // <line-break/> ???
397                $args[0] = preg_replace("~ {0,1}\n~", ' ', $args[0]);
398
399                // Geschützte Leerzeichen für "S. 1234"
400                // $args[0] = preg_replace('~\sS\.([ ]{1})\d+~', '<dir-break-space/>', $args[0]); // Seems not to work
401
402                // Geviertstrich und Halbgeviertstrich
403                // TODO utf8 codes possible?
404                // TODO longer lines like "hr" should be rendered first to not confuse this
405                $args[0] = str_replace(array('---', '--'), array('—', '–'), $args[0]);
406
407                // Auslassungspunkte
408                $args[0] = str_replace(array('...'), array('…'), $args[0]);
409
410                // If not header do replace
411                if (!in_array($name, array('header', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) {
412                    $args[0] = str_replace('"', '&quot;',   $args[0]); // This might depend on the way " are used in the XML template!!!
413                }
414
415                // Highlight
416                // This is incompatible with the highlight plugin.
417                // make sure in /lib/plugins/highlight/syntax.php
418                // "if (strpos($_SERVER['REQUEST_URI'], '_export/mellelexport') !== false) {} else {" is added at the top!
419                // There might be a caching problem! When it does not show the highlighted text try to add "&dummy=123" to the download URL
420                if (preg_match('~&lt;hi ~', $args[0])) {
421                    // &lt;hi #ff4500&gt;bunt&lt;/hi&gt;
422                    // U = not greedy
423                    $args[0] = preg_replace('~&lt;hi #([a-zA-Z0-9]+)&gt;(.*)&lt;/hi&gt;~Ui',  '</c><c style=\'cs-0\' marker=\'$1\'>$2</c><c style=\'cs-0\'>', $args[0]);
424                    // $args[0] = preg_replace('~&lt;hi #[a-zA-Z0-9]+&gt;~',                   '</c><c style=\'cs-0\' marker=\'1\'>', $args[0]);
425
426                    // Replace marker with Mellel marker ids
427                    $args[0] = preg_replace_callback('~marker=\'([a-zA-Z0-9]+)\'~', 'callback_marker', $args[0]);
428                }
429
430                $args[0] = str_replace('&lt;/hi&gt;', '</c><c style=\'cs-0\'>', $args[0]);
431
432                $string = str_replace($mapping['replacement'], $args[0], self::cleanTemplate($mapping['template']));
433
434                $doc = $string;
435            break;
436
437            default:
438                die('No type set');
439        }
440
441
442        // Formating within footnote text
443        if ($this->footnote_open AND $tag != 'footnote') {
444            $doc = str_replace(' style="cs-0"', ' style="cs-6"', $doc);
445        }
446
447
448
449        // Check the given arguments and parse additional information
450        if (!$multi) {
451            array_shift($args); // remove the first entry
452        }
453
454        if (isset($args)) {
455            $doc = str_replace($mapping['subpattern'], $args, $doc);
456        }
457
458        // Set header length
459        if ($tag === 'header' OR (isset($key) AND $key === 'header')) {
460            if (function_exists('mb_strlen')) {
461                $hederLength = mb_strlen($arguments[0]);
462            } else {
463                $hederLength = strlen($arguments[0]);
464            }
465
466            $doc = str_replace('{{LENGTH}}', $hederLength + 10 /* don't know the algorithmus, 10 is an assumption */, $doc);
467        }
468
469        // :?: --> rendered as a yellow questionmark image
470        $doc = str_replace(array(':?:'), array('<c style=\'cs-0\' marker=\'1\'>?</c>'), $doc);
471
472
473        if (DEBUG) {
474            // all args excluded the first one
475            $tmp_args = func_get_args();
476            array_shift($tmp_args);
477            $tmp_args = $tmp_args[0];
478            echo '<tr><td></td><td style="vertical-align: top;">'.$tag.'</td><td></td><td style="vertical-align: top;">'.$type.'</td><td>&nbsp;&nbsp;</td><td style="vertical-align: top;">'.var_export($tmp_args, 1).'</td><td style="font-family: monospace;">'.trim(htmlentities($doc, NULL, 'UTF-8')).'</td></tr>';
479        }
480
481        $this->doc .= $doc;
482
483        $this->lastTag = $name;
484
485        if ($tag == 'p') {
486            if ($type == 'OPEN') {
487                $this->pTagOpen = TRUE;
488            } else {
489                $this->pTagOpen = FALSE;
490            }
491        }
492
493        if ($tag == 'section') {
494            if ($type == 'OPEN') {
495                $this->sectionTagOpen = TRUE;
496            } else {
497                $this->sectionTagOpen = FALSE;
498            }
499        }
500    }
501
502    static function cleanTemplate($xml) {
503        return preg_replace('~>[\r\n]\s*<~', '><', $xml); // no trim()! trim here deletes valid whitespaces
504    }
505
506    static function xml_errors ($xml) {
507        libxml_use_internal_errors(true);
508        $doc = new DOMDocument('1.0', 'utf-8');
509        $doc->loadXML( $xml );
510        $errors = libxml_get_errors();
511
512        if (count($errors) > 0) {
513            echo 'Details';
514            echo '<pre style="border: 1px solid red; border-radius:2px; padding:5px">';
515            $lines = explode("\n", $xml);
516            $padding = 70;
517            foreach($errors as $error) {
518                $line = $lines[($error->line - 1)];
519
520                $start = ($error->column - $padding) > 0 ? ($error->column - $padding) : 0;
521
522                echo trim($error->message).'<br />';
523                echo htmlentities(substr($line, $start, $padding * 2)).'...<br />';
524
525                $column = $error->column - $start - 1;
526                echo str_pad('', $column, '-').'^';
527                echo '<br /><br />';
528            }
529            echo '</pre>';
530
531            echo 'XML Error(s):';
532            echo '<pre style="border: 1px solid red; border-radius:2px; padding:5px">';
533            echo var_export($errors, 1);
534            echo '</pre>';
535
536            echo 'Plain XML:';
537            echo '<pre style="border: 1px solid black; border-radius:2px; padding:5px">';
538            echo htmlentities($xml);
539            echo '</pre>';
540            exit;
541        }
542    }
543
544    static function remove_whitespace($xml) {
545        libxml_use_internal_errors(true);
546        $doc = new DOMDocument('1.0', 'utf-8');
547        $doc->loadXML( $xml );
548
549        if (!DEBUG) {
550            $doc->preserveWhiteSpace    = FALSE;
551            $doc->formatOutput          = FALSE;
552        } else {
553            $doc->preserveWhiteSpace    = FALSE;
554            $doc->formatOutput          = TRUE;
555        }
556
557        return self::cleanTemplate($doc->saveXML());
558    }
559
560
561
562    // Dummy mappings of method to __call()
563    function render_TOC() { return ''; }
564
565    function toc_additem($id, $text, $level) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
566
567    function header($text, $level, $pos) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
568
569    function section_open($level) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
570
571    function section_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
572
573    function cdata($text) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
574
575    function p_open() {
576        #var_dump(func_get_args());
577
578        call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));
579
580
581    }
582
583    function p_close() {#var_dump(func_get_args());
584        call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
585
586    function linebreak() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
587
588    function hr() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
589
590    function strong_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
591
592    function strong_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
593
594    function emphasis_open() {
595
596        #var_dump(__FUNCTION__);
597
598        call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
599
600    function emphasis_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
601
602    function underline_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
603
604    function underline_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
605
606    function monospace_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
607
608    function monospace_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
609
610    function subscript_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
611
612    function subscript_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
613
614    function superscript_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
615
616    function superscript_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
617
618    function deleted_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
619
620    function deleted_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
621
622    function footnote_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
623
624    function footnote_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
625
626    function listu_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
627
628    function listu_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
629
630    function listo_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
631
632    function listo_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
633
634    function listitem_open($level) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
635
636    function listitem_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
637
638    function listcontent_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
639
640    function listcontent_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
641
642    function unformatted($text) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
643
644    function php($text) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
645
646    function phpblock($text) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
647
648    function html($text) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
649
650    function htmlblock($text) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
651
652    function preformatted($text) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
653
654    function quote_open() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
655
656    function quote_close() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
657
658    function file($text, $lang = null, $file = null ) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
659
660    function code($text, $lang = null, $file = null ) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
661
662    function acronym($acronym) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
663
664    function smiley($smiley) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
665
666    function wordblock($word) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
667
668    function entity($entity) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
669
670    // 640x480 ($x=640, $y=480)
671    function multiplyentity($x, $y) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
672
673    function singlequoteopening() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
674
675    function singlequoteclosing() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
676
677    function apostrophe() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
678
679    function doublequoteopening() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
680
681    function doublequoteclosing() {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
682
683    // $link like 'SomePage'
684    function camelcaselink($link) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
685
686    function locallink($hash, $name = NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
687
688    // $link like 'wiki:syntax', $title could be an array (media)
689    function internallink($link, $title = NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
690
691    // $link is full URL with scheme, $title could be an array (media)
692    function externallink($link, $title = NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
693
694    function rss ($url,$params) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
695
696    // $link is the original link - probably not much use
697    // $wikiName is an indentifier for the wiki
698    // $wikiUri is the URL fragment to append to some known URL
699    function interwikilink($link, $title = NULL, $wikiName, $wikiUri) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
700
701    // Link to file on users OS, $title could be an array (media)
702    function filelink($link, $title = NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
703
704    // Link to a Windows share, , $title could be an array (media)
705    function windowssharelink($link, $title = NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
706
707//  function email($address, $title = NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
708    function emaillink($address, $name = NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
709
710    function internalmedia ($src, $title=NULL, $align=NULL, $width=NULL,
711                            $height=NULL, $cache=NULL, $linking=NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
712
713    function externalmedia ($src, $title=NULL, $align=NULL, $width=NULL,
714                            $height=NULL, $cache=NULL, $linking=NULL) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
715
716    function internalmedialink (
717        $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL
718        ) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
719
720    function externalmedialink(
721        $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL
722        ) {call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
723
724    function table_open($maxcols = null, $numrows = null, $pos = null){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
725
726    function table_close($pos = null){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
727
728    function tablerow_open(){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
729
730    function tablerow_close(){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
731
732    function tableheader_open($colspan = 1, $align = NULL, $rowspan = 1){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
733
734    function tableheader_close(){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
735
736    function tablecell_open($colspan = 1, $align = NULL, $rowspan = 1){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
737
738    function tablecell_close(){call_user_func_array(array($this, '__call'), array(__FUNCTION__, func_get_args()));}
739
740}