xref: /dokuwiki/inc/parser/xhtml.php (revision b625487d2258a6f1f875813206adc9a5857dab24)
1<?php
2/**
3 * Renderer for XHTML output
4 *
5 * @author Harry Fuecks <hfuecks@gmail.com>
6 * @author Andreas Gohr <andi@splitbrain.org>
7 */
8
9if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
10
11if ( !defined('DOKU_LF') ) {
12    // Some whitespace to help View > Source
13    define ('DOKU_LF',"\n");
14}
15
16if ( !defined('DOKU_TAB') ) {
17    // Some whitespace to help View > Source
18    define ('DOKU_TAB',"\t");
19}
20
21require_once DOKU_INC . 'inc/parser/renderer.php';
22
23/**
24 * The Renderer
25 */
26class Doku_Renderer_XHTML extends Doku_Renderer {
27
28    var $doc = '';
29
30    var $headers = array();
31
32    var $footnotes = array();
33
34    var $footnoteIdStack = array();
35
36    var $acronyms = array();
37    var $smileys = array();
38    var $badwords = array();
39    var $entities = array();
40    var $interwiki = array();
41
42    var $lastsec = 0;
43
44    function document_start() {
45        ob_start();
46    }
47
48    function document_end() {
49        // add button for last section if any
50        if($this->lastsec) $this->__secedit($this->lastsec,'');
51
52        if ( count ($this->footnotes) > 0 ) {
53            echo '<div class="footnotes">'.DOKU_LF;
54            foreach ( $this->footnotes as $footnote ) {
55                echo $footnote;
56            }
57            echo '</div>'.DOKU_LF;
58        }
59
60        $this->doc .= ob_get_contents();
61        ob_end_clean();
62
63    }
64
65    function toc_open() {
66        echo '<div class="toc">'.DOKU_LF;
67        echo '<div class="tocheader">Table of Contents <script type="text/javascript">showTocToggle("+","-")</script></div>'.DOKU_LF;
68        echo '<div id="tocinside">'.DOKU_LF;
69    }
70
71    function tocbranch_open($level) {
72        echo '<ul class="toc">'.DOKU_LF;
73    }
74
75    function tocitem_open($level, $empty = FALSE) {
76        if ( !$empty ) {
77            echo '<li class="level'.$level.'">';
78        } else {
79            echo '<li class="clear">';
80        }
81    }
82
83    function tocelement($level, $title) {
84        echo '<span class="li"><a href="#'.$this->__headerToLink($title).'" class="toc">';
85        echo $this->__xmlEntities($title);
86        echo '</a></span>';
87    }
88
89    function tocitem_close($level) {
90        echo '</li>'.DOKU_LF;
91    }
92
93    function tocbranch_close($level) {
94        echo '</ul>'.DOKU_LF;
95    }
96
97    function toc_close() {
98        echo '</div>'.DOKU_LF.'</div>'.DOKU_LF;
99    }
100
101    function header($text, $level, $pos) {
102        global $conf;
103        //handle section editing
104        if($level <= $conf['maxseclevel']){
105            // add button for last section if any
106            if($this->lastsec) $this->__secedit($this->lastsec,$pos-1);
107            // remember current position
108            $this->lastsec = $pos;
109        }
110
111        echo DOKU_LF.'<a name="'.$this->__headerToLink($text).'"></a><h'.$level.'>';
112        echo $this->__xmlEntities($text);
113        echo "</h$level>".DOKU_LF;
114    }
115
116    function section_open($level) {
117        echo "<div class=\"level$level\">".DOKU_LF;
118    }
119
120    function section_close() {
121        echo DOKU_LF.'</div>'.DOKU_LF;
122    }
123
124    function cdata($text) {
125        echo $this->__xmlEntities($text);
126    }
127
128    function p_open() {
129        echo DOKU_LF.'<p>'.DOKU_LF;
130    }
131
132    function p_close() {
133        echo DOKU_LF.'</p>'.DOKU_LF;
134    }
135
136    function linebreak() {
137        echo '<br/>'.DOKU_LF;
138    }
139
140    function hr() {
141        echo '<hr noshade="noshade" size="1" />'.DOKU_LF;
142    }
143
144    function strong_open() {
145        echo '<strong>';
146    }
147
148    function strong_close() {
149        echo '</strong>';
150    }
151
152    function emphasis_open() {
153        echo '<em>';
154    }
155
156    function emphasis_close() {
157        echo '</em>';
158    }
159
160    function underline_open() {
161        echo '<u>';
162    }
163
164    function underline_close() {
165        echo '</u>';
166    }
167
168    function monospace_open() {
169        echo '<code>';
170    }
171
172    function monospace_close() {
173        echo '</code>';
174    }
175
176    function subscript_open() {
177        echo '<sub>';
178    }
179
180    function subscript_close() {
181        echo '</sub>';
182    }
183
184    function superscript_open() {
185        echo '<sup>';
186    }
187
188    function superscript_close() {
189        echo '</sup>';
190    }
191
192    function deleted_open() {
193        echo '<del>';
194    }
195
196    function deleted_close() {
197        echo '</del>';
198    }
199
200    function footnote_open() {
201        $id = $this->__newFootnoteId();
202        echo '<a href="#fn'.$id.'" name="fnt'.$id.'" class="fn_top">'.$id.')</a>';
203        $this->footnoteIdStack[] = $id;
204        ob_start();
205    }
206
207    function footnote_close() {
208        $contents = ob_get_contents();
209        ob_end_clean();
210        $id = array_pop($this->footnoteIdStack);
211
212        $contents = '<div class="fn"><a href="#fnt'.
213            $id.'" name="fn'.$id.'" class="fn_bot">'.
214                $id.')</a> ' .DOKU_LF .$contents. "\n" . '</div>' . DOKU_LF;
215        $this->footnotes[$id] = $contents;
216    }
217
218    function listu_open() {
219        echo '<ul>'.DOKU_LF;
220    }
221
222    function listu_close() {
223        echo '</ul>'.DOKU_LF;
224    }
225
226    function listo_open() {
227        echo '<ol>'.DOKU_LF;
228    }
229
230    function listo_close() {
231        echo '</ol>'.DOKU_LF;
232    }
233
234    function listitem_open($level) {
235        echo '<li class="level'.$level.'">';
236    }
237
238    function listitem_close() {
239        echo '</li>'.DOKU_LF;
240    }
241
242    function listcontent_open() {
243        echo '<span class="li">';
244    }
245
246    function listcontent_close() {
247        echo '</span>'.DOKU_LF;
248    }
249
250    function unformatted($text) {
251        echo $this->__xmlEntities($text);
252    }
253
254    /**
255    */
256    function php($text) {
257        global $conf;
258        if($conf['phpok']){
259            eval($text);
260        }else{
261            $this->file($text);
262        }
263    }
264
265    /**
266    */
267    function html($text) {
268        global $conf;
269        if($conf['htmlok']){
270          echo $text;
271        }else{
272          $this->file($text);
273        }
274    }
275
276    function preformatted($text) {
277        echo '<pre class="code">' . $this->__xmlEntities($text) . '</pre>'. DOKU_LF;
278    }
279
280    function file($text) {
281        echo '<pre class="file">' . $this->__xmlEntities($text). '</pre>'. DOKU_LF;
282    }
283
284    /**
285    * @TODO Shouldn't this output <blockquote??
286    */
287    function quote_open() {
288        echo '<div class="quote">'.DOKU_LF;
289    }
290
291    /**
292    * @TODO Shouldn't this output </blockquote>?
293    */
294    function quote_close() {
295        echo '</div>'.DOKU_LF;
296    }
297
298    /**
299    */
300    function code($text, $language = NULL) {
301        global $conf;
302
303        if ( is_null($language) ) {
304            $this->preformatted($text);
305        } else {
306            // Handle with Geshi here FIXME: strip first beginning newline
307            require_once(DOKU_INC . 'inc/geshi.php');
308            $geshi = new GeSHi($text, strtolower($language), DOKU_INC . 'inc/geshi');
309            $geshi->enable_classes();
310            $geshi->set_header_type(GESHI_HEADER_PRE);
311            $geshi->set_overall_class('code');
312            $geshi->set_link_target($conf['target']['extern']);
313
314            $text = $geshi->parse_code();
315            echo $text;
316        }
317    }
318
319    function acronym($acronym) {
320
321        if ( array_key_exists($acronym, $this->acronyms) ) {
322
323            $title = $this->__xmlEntities($this->acronyms[$acronym]);
324
325            echo '<acronym title="'.$title
326                .'">'.$this->__xmlEntities($acronym).'</acronym>';
327
328        } else {
329            echo $this->__xmlEntities($acronym);
330        }
331    }
332
333    /**
334    */
335    function smiley($smiley) {
336        if ( array_key_exists($smiley, $this->smileys) ) {
337            $title = $this->__xmlEntities($this->smileys[$smiley]);
338            echo '<img src="'.DOKU_BASE.'smileys/'.$this->smileys[$smiley].
339                '" align="middle" alt="'.
340                    $this->__xmlEntities($smiley).'" />';
341        } else {
342            echo $this->__xmlEntities($smiley);
343        }
344    }
345
346    /**
347    * not used
348    function wordblock($word) {
349        if ( array_key_exists($word, $this->badwords) ) {
350            echo '** BLEEP **';
351        } else {
352            echo $this->__xmlEntities($word);
353        }
354    }
355    */
356
357    function entity($entity) {
358        if ( array_key_exists($entity, $this->entities) ) {
359            echo $this->entities[$entity];
360        } else {
361            echo $this->__xmlEntities($entity);
362        }
363    }
364
365    function multiplyentity($x, $y) {
366        echo "$x&times;$y";
367    }
368
369    function singlequoteopening() {
370        echo "&lsquo;";
371    }
372
373    function singlequoteclosing() {
374        echo "&rsquo;";
375    }
376
377    function doublequoteopening() {
378        echo "&ldquo;";
379    }
380
381    function doublequoteclosing() {
382        echo "&rdquo;";
383    }
384
385    /**
386    */
387    function camelcaselink($link) {
388      $this->internallink($link,$link);
389    }
390
391    function internallink($id, $name = NULL) {
392        global $conf;
393
394        $name = $this->__getLinkTitle($name, $this->__simpleTitle($id), $isImage);
395        resolve_pageid($id,$exists);
396
397        if ( !$isImage ) {
398            if ( $exists ) {
399                $class='wikilink1';
400            } else {
401                $class='wikilink2';
402            }
403        } else {
404            $class='media';
405        }
406
407        //prepare for formating
408        $link['target'] = $conf['target']['wiki'];
409        $link['style']  = '';
410        $link['pre']    = '';
411        $link['suf']    = '';
412        $link['more']   = 'onclick="return svchk()" onkeypress="return svchk()"';
413        $link['class']  = $class;
414        $link['url']    = wl($id);
415        $link['name']   = $name;
416        $link['title']  = $id;
417
418        //output formatted
419        echo $this->__formatLink($link);
420    }
421
422    function externallink($url, $name = NULL) {
423        global $conf;
424
425        $name = $this->__getLinkTitle($name, $url, $isImage);
426
427        if ( !$isImage ) {
428            $class='urlextern';
429        } else {
430            $class='media';
431        }
432
433        //prepare for formating
434        $link['target'] = $conf['target']['extern'];
435        $link['style']  = '';
436        $link['pre']    = '';
437        $link['suf']    = '';
438        $link['more']   = 'onclick="return svchk()" onkeypress="return svchk()"';
439        $link['class']  = $class;
440        $link['url']    = $url;
441        $link['name']   = $name;
442        $link['title']  = $this->__xmlEntities($url);
443        if($conf['relnofollow']) $link['more'] .= ' rel="nofollow"';
444
445        //output formatted
446        echo $this->__formatLink($link);
447    }
448
449    /**
450    * @TODO Remove hard coded link to splitbrain.org on style
451    */
452    function interwikilink($link, $title = NULL, $wikiName, $wikiUri) {
453        global $conf;
454
455        // RESOLVE THE URL
456        if ( isset($this->interwiki[$wikiName]) ) {
457
458            $wikiUriEnc = urlencode($wikiUri);
459
460            if ( strstr($this->interwiki[$wikiName],'{URL}' ) !== FALSE ) {
461
462                $url = str_replace('{URL}', $wikiUriEnc, $this->interwiki[$wikiName] );
463
464            } else if ( strstr($this->interwiki[$wikiName],'{NAME}' ) !== FALSE ) {
465
466                $url = str_replace('{NAME}', $wikiUriEnc, $this->interwiki[$wikiName] );
467
468            } else {
469
470                $url = $this->interwiki[$wikiName] . urlencode($wikiUri);
471
472            }
473
474        } else {
475            // Default to Google I'm feeling lucky
476            $url = 'http://www.google.com/search?q='.urlencode($wikiUri).'&amp;btnI=lucky';
477        }
478
479        // BUILD THE LINK
480        echo '<a';
481
482        $title = $this->__getLinkTitle($title, $wikiUri, $isImage);
483
484        if ( !$isImage ) {
485            echo ' class="interwiki"';
486        } else {
487            echo ' class="media"';
488        }
489
490        echo ' href="'.$this->__xmlEntities($url).'"';
491
492        if ( FALSE !== ( $type = interwikiImgExists($wikiName) ) ) {
493            echo ' style="background: transparent url(http://wiki.splitbrain.org/interwiki/'.
494                $wikiName.'.'.$type.') 0px 1px no-repeat;"';
495        }
496
497        echo ' onclick="return svchk()" onkeypress="return svchk()">';
498
499        echo $title;
500
501        echo '</a>';
502    }
503
504    /**
505    * @TODO Correct the CSS class for files? (not windows)
506    * @TODO Remove hard coded URL to splitbrain.org
507    */
508    function filelink($link, $title = NULL) {
509        echo '<a';
510
511        $title = $this->__getLinkTitle($title, $link, $isImage);
512
513        if ( !$isImage ) {
514            echo ' class="windows"';
515        } else {
516            echo ' class="media"';
517        }
518
519        echo ' href="'.$this->__xmlEntities($link).'"';
520
521        echo ' style="background: transparent url(http://wiki.splitbrain.org/images/windows.gif) 0px 1px no-repeat;"';
522
523        echo ' onclick="return svchk()" onkeypress="return svchk()">';
524
525        echo $title;
526
527        echo '</a>';
528    }
529
530    /**
531    * @TODO Remove hard coded URL to splitbrain.org
532    * @TODO Add error message for non-IE users
533    */
534    function windowssharelink($link, $title = NULL) {
535        echo '<a';
536
537        $title = $this->__getLinkTitle($title, $link, $isImage);
538
539        if ( !$isImage ) {
540            echo ' class="windows"';
541        } else {
542            echo ' class="media"';
543        }
544
545        $link = str_replace('\\','/',$link);
546        $link = 'file:///'.$link;
547        echo ' href="'.$this->__xmlEntities($link).'"';
548
549        echo ' style="background: transparent url(http://wiki.splitbrain.org/images/windows.gif) 0px 1px no-repeat;"';
550
551        echo ' onclick="return svchk()" onkeypress="return svchk()">';
552
553        echo $title;
554
555        echo '</a>';
556    }
557
558    /**
559    * @TODO Protect email address from harvesters
560    * @TODO Remove hard coded link to splitbrain.org
561    */
562    function email($address, $title = NULL) {
563        echo '<a';
564
565        $title = $this->__getLinkTitle($title, $address, $isImage);
566
567        if ( !$isImage ) {
568            echo ' class="mail"';
569        } else {
570            echo ' class="media"';
571        }
572
573        echo ' href="mailto:'.$this->__xmlEntities($address).'"';
574
575        echo ' style="background: transparent url(http://wiki.splitbrain.org/images/mail_icon.gif) 0px 1px no-repeat;"';
576
577        echo ' onclick="return svchk()" onkeypress="return svchk()">';
578
579        echo $title;
580
581        echo '</a>';
582
583    }
584
585    /**
586     * @todo don't add link for flash
587     */
588    function internalmedia ($src, $title=NULL, $align=NULL, $width=NULL,
589                            $height=NULL, $cache=NULL) {
590
591        resolve_mediaid($src, $exists);
592
593        $this->internallink($src, $title =
594                                    array( 'type'   => 'internalmedia',
595                                           'src'    => $src,
596                                           'title'  => $title,
597                                           'align'  => $align,
598                                           'width'  => $width,
599                                           'height' => $height,
600                                           'cache'  => $cache,
601                                           'link'   => $link ));
602    }
603
604    /**
605     * @todo don't add link for flash
606     */
607    function externalmedia ($src, $title=NULL, $align=NULL, $width=NULL,
608                            $height=NULL, $cache=NULL) {
609
610        $this->externallink($src, $title =
611                                    array( 'type'   => 'externalmedia',
612                                           'src'    => $src,
613                                           'title'  => $title,
614                                           'align'  => $align,
615                                           'width'  => $width,
616                                           'height' => $height,
617                                           'cache'  => $cache,
618                                           'link'   => $link ));
619    }
620
621    /**
622     * Renders an RSS feed using magpie
623     *
624     * @author Andreas Gohr <andi@splitbrain.org>
625     */
626    function rss ($url){
627        global $lang;
628        define('MAGPIE_CACHE_ON', false); //we do our own caching
629        define('MAGPIE_DIR', DOKU_INC.'inc/magpie/');
630        define('MAGPIE_OUTPUT_ENCODING','UTF-8'); //return all feeds as UTF-8
631        require_once(MAGPIE_DIR.'/rss_fetch.inc');
632
633        //disable warning while fetching
634        $elvl = error_reporting(E_ERROR);
635        $rss  = fetch_rss($url);
636        error_reporting($elvl);
637
638        print '<ul class="rss">';
639        if($rss){
640            foreach ($rss->items as $item ) {
641                print '<li>';
642                $this->externallink($item['link'],$item['title']);
643                print '</li>';
644            }
645        }else{
646            print '<li>';
647            print '<em>'.$lang['rssfailed'].'</em>';
648            $this->externallink($url);
649            print '</li>';
650        }
651        print '</ul>';
652    }
653
654    /**
655     * Renders internal and external media
656     *
657     * @author Andreas Gohr <andi@splitbrain.org>
658     * @todo   handle center align
659     * @todo   move to bottom
660     */
661    function __media ($src, $title=NULL, $align=NULL, $width=NULL,
662                      $height=NULL, $cache=NULL) {
663
664        $ret = '';
665
666        list($ext,$mime) = mimetype($src);
667        if(substr($mime,0,5) == 'image'){
668            //add image tag
669            $ret .= '<img class="media" src="'.
670                    DOKU_BASE.'fetch.php?w='.$width.'&amp;h='.$height.
671                    '&amp;cache='.$cache.'&amp;media='.urlencode($src).'"';
672
673            if (!is_null($title))
674                $ret .= ' title="'.$this->__xmlEntities($title).'"';
675
676
677            if (!is_null($align))
678                $ret .= ' align="'.$align.'"'; #FIXME use class!
679
680            if ( !is_null($width) )
681                $ret .= ' width="'.$this->__xmlEntities($width).'"';
682
683            if ( !is_null($height) )
684                $ret .= ' height="'.$this->__xmlEntities($height).'"';
685
686            $ret .= ' />';
687
688        }elseif($mime == 'application/x-shockwave-flash'){
689            //FIXME default to a higher flash version?
690
691            $ret .= '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'.
692                    ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"';
693            if ( !is_null($width) ) $ret .= ' width="'.$this->__xmlEntities($width).'"';
694            if ( !is_null($height) ) $ret .= ' height="'.$this->__xmlEntities($height).'"';
695            $ret .= '>'.DOKU_LF;
696            $ret .= '<param name="movie" value="'.DOKU_BASE.'fetch.php?media='.urlencode($src).'" />'.DOKU_LF;
697            $ret .= '<param name="quality" value="high" />'.DOKU_LF;
698            $ret .= '<embed src="'.DOKU_BASE.'fetch.php?media='.urlencode($src).'"'.
699                    ' quality="high" bgcolor="#000000"';
700            if ( !is_null($width) ) $ret .= ' width="'.$this->__xmlEntities($width).'"';
701            if ( !is_null($height) ) $ret .= ' height="'.$this->__xmlEntities($height).'"';
702            $ret .= ' type="application/x-shockwave-flash"'.
703                    ' pluginspage="http://www.macromedia.com/shockwave/download/index.cgi'.
704                    '?P1_Prod_Version=ShockwaveFlash"></embed>'.DOKU_LF;
705            $ret .= '</object>'.DOKU_LF;
706
707        }elseif(!is_null($title)){
708            // well at least we have a title to display
709            $ret .= $this->__xmlEntities($title);
710        }else{
711            // just show the source
712            $ret .= $this->__xmlEntities($src);
713        }
714
715        return $ret;
716    }
717
718    // $numrows not yet implemented
719    function table_open($maxcols = NULL, $numrows = NULL){
720        echo '<table class="inline">'.DOKU_LF;
721    }
722
723    function table_close(){
724        echo '</table>'.DOKU_LF.'<br />'.DOKU_LF;
725    }
726
727    function tablerow_open(){
728        echo DOKU_TAB . '<tr>' . DOKU_LF . DOKU_TAB . DOKU_TAB;
729    }
730
731    function tablerow_close(){
732        echo DOKU_LF . DOKU_TAB . '</tr>' . DOKU_LF;
733    }
734
735    function tableheader_open($colspan = 1, $align = NULL){
736        echo '<th';
737        if ( !is_null($align) ) {
738            echo ' class="'.$align.'align"';
739        }
740        if ( $colspan > 1 ) {
741            echo ' colspan="'.$colspan.'"';
742        }
743        echo '>';
744    }
745
746    function tableheader_close(){
747        echo '</th>';
748    }
749
750    function tablecell_open($colspan = 1, $align = NULL){
751        echo '<td';
752        if ( !is_null($align) ) {
753            echo ' class="'.$align.'align"';
754        }
755        if ( $colspan > 1 ) {
756            echo ' colspan="'.$colspan.'"';
757        }
758        echo '>';
759    }
760
761    function tablecell_close(){
762        echo '</td>';
763    }
764
765    //----------------------------------------------------------
766    // Utils
767
768    /**
769     * Assembles all parts defined by the link formater below
770     * Returns HTML for the link
771     *
772     * @author Andreas Gohr <andi@splitbrain.org>
773     */
774    function __formatLink($link){
775        //make sure the url is XHTML compliant (skip mailto)
776        if(substr($link['url'],0,7) != 'mailto:'){
777            $link['url'] = str_replace('&','&amp;',$link['url']);
778            $link['url'] = str_replace('&amp;amp;','&amp;',$link['url']);
779        }
780        //remove double encodings in titles
781        $link['title'] = str_replace('&amp;amp;','&amp;',$link['title']);
782
783        $ret  = '';
784        $ret .= $link['pre'];
785        $ret .= '<a href="'.$link['url'].'"';
786        if($link['class'])  $ret .= ' class="'.$link['class'].'"';
787        if($link['target']) $ret .= ' target="'.$link['target'].'"';
788        if($link['title'])  $ret .= ' title="'.$link['title'].'"';
789        if($link['style'])  $ret .= ' style="'.$link['style'].'"';
790        if($link['more'])   $ret .= ' '.$link['more'];
791        $ret .= '>';
792        $ret .= $link['name'];
793        $ret .= '</a>';
794        $ret .= $link['suf'];
795        return $ret;
796    }
797
798    /**
799     * Removes any Namespace from the given name but keeps
800     * casing and special chars
801     *
802     * @author Andreas Gohr <andi@splitbrain.org>
803     */
804    function __simpleTitle($name){
805        global $conf;
806        if($conf['useslash']){
807            $nssep = '[:;/]';
808        }else{
809            $nssep = '[:;]';
810        }
811        return preg_replace('!.*'.$nssep.'!','',$name);
812    }
813
814
815    function __newFootnoteId() {
816        static $id = 1;
817        return $id++;
818    }
819
820    function __xmlEntities($string) {
821        return htmlspecialchars($string);
822    }
823
824    /**
825    * @TODO Tuning needed - e.g. utf8 strtolower ?
826    */
827    function __headerToLink($title) {
828        return preg_replace('/\W/','_',trim($title));
829    }
830
831    /**
832     * Adds code for section editing button
833     */
834    function __secedit($f, $t){
835        print '<!-- SECTION ['.$f.'-'.$t.'] -->';
836    }
837
838    function __getLinkTitle($title, $default, & $isImage) {
839        $isImage = FALSE;
840
841        if ( is_null($title) ) {
842            return $this->__xmlEntities($default);
843
844        } else if ( is_string($title) ) {
845
846            return $this->__xmlEntities($title);
847
848        } else if ( is_array($title) ) {
849
850            $isImage = TRUE;
851            return $this->__imageTitle($title);
852
853        }
854    }
855
856    /**
857     * @TODO Resolve namespace on internal images
858     */
859    function __imageTitle($img) {
860
861        //FIXME resolve internal links
862
863        return $this->__media($img['src'],
864                              $img['title'],
865                              $img['align'],
866                              $img['width'],
867                              $img['height'],
868                              $img['cache']);
869
870/*
871        if ( $img['type'] == 'internalmedia' ) {
872
873            // Resolve here...
874            if ( strpos($img['src'],':') ) {
875                $src = explode(':',$img['src']);
876                $src = $src[1];
877            } else {
878                $src = $img['src'];
879            }
880
881            $imgStr = '<img class="media" src="http://wiki.splitbrain.org/media/wiki/'.$this->__xmlEntities($src).'"';
882
883        } else {
884
885            $imgStr = '<img class="media" src="'.$this->__xmlEntities($img['src']).'"';
886
887        }
888
889        if ( !is_null($img['title']) ) {
890            $imgStr .= ' alt="'.$this->__xmlEntities($img['title']).'"';
891        } else {
892            $imgStr .= ' alt=""';
893        }
894
895        if ( !is_null($img['align']) ) {
896            $imgStr .= ' align="'.$img['align'].'"';
897        }
898
899        if ( !is_null($img['width']) ) {
900            $imgStr .= ' width="'.$this->__xmlEntities($img['width']).'"';
901        }
902
903        if ( !is_null($img['height']) ) {
904            $imgStr .= ' height="'.$this->__xmlEntities($img['height']).'"';
905        }
906
907        $imgStr .= '/>';
908
909        return $imgStr;
910*/
911    }
912}
913
914/**
915* Test whether there's an image to display with this interwiki link
916*/
917function interwikiImgExists($name) {
918
919    static $exists = array();
920
921    if ( array_key_exists($name,$exists) ) {
922        return $exists[$name];
923    }
924
925    if( @file_exists( DOKU. 'interwiki/'.$name.'.png') ) {
926        $exists[$name] = 'png';
927    } else if ( @file_exists( DOKU . 'interwiki/'.$name.'.gif') ) {
928        $exists[$name] = 'gif';
929    } else {
930        $exists[$name] = FALSE;
931    }
932
933    return $exists[$name];
934}
935
936/**
937 * For determining whether to use CSS class "wikilink1" or "wikilink2"
938 * @todo use configinstead of DOKU_DATA
939 * @deprecated -> resolve_pagename should be used
940 */
941function wikiPageExists($name) {
942msg("deprecated wikiPageExists called",-1);
943    static $pages = array();
944
945    if ( array_key_exists($name,$pages) ) {
946        return $pages[$name];
947    }
948
949    $file = str_replace(':','/',$name).'.txt';
950
951    if ( @file_exists( DOKU_DATA . $file ) ) {
952        $pages[$name] = TRUE;
953    } else {
954        $pages[$name] = FALSE;
955    }
956
957    return $pages[$name];
958}
959
960
961//Setup VIM: ex: et ts=4 enc=utf-8 :
962