1<?php
2/**
3 * Renderer for XHTML output
4 *
5 * @author Carsten Graw <dokuwiki@graw.eu>
6 */
7// must be run within Dokuwiki
8if(!defined('DOKU_INC')) die();
9
10// we inherit from the XHTML renderer instead directly of the base renderer
11require_once DOKU_INC.'inc/parser/xhtml.php';
12
13/**
14 * The Renderer
15 */
16class renderer_plugin_offline extends Doku_Renderer_xhtml {
17   var $base='';
18    var $tpl='';
19
20    /**
21     * return some info
22     */
23    function getInfo(){
24        return confToHash(dirname(__FILE__).'/info.txt');
25    }
26
27    /**
28     * the format we produce
29     */
30    function getFormat(){
31        // this should be "offline"' usally, but we inherit from the xhtml renderer
32        // and produce XHTML as well, so we can gain magically compatibility
33        // by saying we're the 'xhtml' renderer here.
34        return 'xhtml';
35    }
36
37
38    /**
39     * Initialize the rendering
40     */
41     function document_start() {
42        // call the parent
43        parent::document_start();
44
45        // send the content type header
46        header('Content-Type: text/html; charset=utf-8');
47
48        $this->base = DOKU_BASE.'lib/plugins/offline/ui/';
49        $this->tpl  = $this->getConf('template');
50        $this->offline_init($text);
51    }
52
53    /**
54     * Print the header of the page
55     *
56     * Gets called when the very first H1 header is discovered. It includes
57     * all the S5 CSS and JavaScript magic
58     */
59
60    function offline_init($title){
61        global $conf;
62        global $lang;
63        global $INFO;
64        global $ID;
65// Create prefix to turn almost absolute path into relative path
66$urlPrefixStr = $this->create_url_prefix($ID);
67
68        //throw away any previous content
69        $this->doc = '
70<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
71 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
72<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="'.$conf['lang'].'"
73 lang="'.$conf['lang'].'" dir="'.$lang['direction'].'">
74
75<head>
76<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
77<title>'.hsc($title).'</title>
78<!-- metadata -->
79<meta name="generator" content="Offline" />
80<meta name="version" content="Offline 0.1" />
81<!-- style sheet links -->
82<link rel="stylesheet" media="all" type="text/css" href="' . $urlPrefixStr . '../css/all.css" />
83<link rel="stylesheet" media="screen" type="text/css" href="' . $urlPrefixStr . '../css/screen.css" />
84<link rel="stylesheet" media="print" type="text/css" href="' . $urlPrefixStr . '../css/print.css" />
85
86</head>
87<body>
88<div class="dokuwiki export">
89
90';
91    }
92
93    /**
94     * Closes the document
95    function document_end(){
96        // we don't care for footnotes and toc
97        // but cleanup is nice
98        $this->doc = preg_replace('#<p>\s*</p>#','',$this->doc);
99
100        if($this->slideopen){
101            $this->doc .= '</div>'.DOKU_LF; //close previous slide
102        }
103        $this->doc .= '</div>
104                       </body>
105                       </html>';
106    }
107     */
108
109    function document_end() {
110        if ( count ($this->footnotes) > 0 ) {
111            $this->doc .= '<div class="footnotes">'.DOKU_LF;
112
113            $id = 0;
114            foreach ( $this->footnotes as $footnote ) {
115                $id++;   // the number of the current footnote
116
117                // check its not a placeholder that indicates actual footnote text is elsewhere
118                if (substr($footnote, 0, 5) != "@@FNT") {
119
120                    // open the footnote and set the anchor and backlink
121                    $this->doc .= '<div class="fn">';
122                    $this->doc .= '<sup><a href="#fnt__'.$id.'" id="fn__'.$id.'" name="fn__'.$id.'" class="fn_bot">';
123                    $this->doc .= $id.')</a></sup> '.DOKU_LF;
124
125                    // get any other footnotes that use the same markup
126                    $alt = array_keys($this->footnotes, "@@FNT$id");
127
128                    if (count($alt)) {
129                      foreach ($alt as $ref) {
130                        // set anchor and backlink for the other footnotes
131                        $this->doc .= ', <sup><a href="#fnt__'.($ref+1).'" id="fn__'.($ref+1).'" name="fn__'.($ref+1).'" class="fn_bot">';
132                        $this->doc .= ($ref+1).')</a></sup> '.DOKU_LF;
133                      }
134                    }
135
136                    // add footnote markup and close this footnote
137                    $this->doc .= $footnote;
138                    $this->doc .= '</div>' . DOKU_LF;
139                }
140            }
141            $this->doc .= '</div>'.DOKU_LF;
142        }
143
144        // Prepare the TOC
145        if($this->info['toc'] && is_array($this->toc) && count($this->toc) > 2){
146            global $TOC;
147            $TOC = $this->toc;
148        }
149
150        // make sure there are no empty paragraphs
151        $this->doc = preg_replace('#<p>\s*</p>#','',$this->doc);
152        $this->doc .= '</div><!-- closes <div class="dokuwiki export">-->';
153    }
154
155
156
157   /**
158     * Renders internal and external media
159     *
160     * @author Andreas Gohr <andi@splitbrain.org>
161     */
162    function _media ($src, $title=NULL, $align=NULL, $width=NULL,
163                      $height=NULL, $cache=NULL, $render = true) {
164global $ID;
165// Create prefix to turn almost absolute path into relative path
166$urlPrefixStr = $this->create_url_prefix($ID);
167
168        $ret = '';
169
170        list($ext,$mime) = mimetype($src);
171        if(substr($mime,0,5) == 'image'){
172            // first get the $title
173            if (!is_null($title)) {
174                $title  = $this->_xmlEntities($title);
175            }elseif($ext == 'jpg' || $ext == 'jpeg'){
176                //try to use the caption from IPTC/EXIF
177                require_once(DOKU_INC.'inc/JpegMeta.php');
178                $jpeg =& new JpegMeta(mediaFN($src));
179                if($jpeg !== false) $cap = $jpeg->getTitle();
180                if($cap){
181                    $title = $this->_xmlEntities($cap);
182                }
183            }
184            if (!$render) {
185                // if the picture is not supposed to be rendered
186                // return the title of the picture
187                if (!$title) {
188                    // just show the sourcename
189                    $title = $this->_xmlEntities(basename(noNS($src)));
190                }
191                return $title;
192            }
193            //add image tag
194$ret .= '<img src="'.$urlPrefixStr.'../media/'.str_replace(':', '/', $src).'"';
195            $ret .= ' class="media'.$align.'"';
196
197            // make left/right alignment for no-CSS view work (feeds)
198            if($align == 'right') $ret .= ' align="right"';
199            if($align == 'left')  $ret .= ' align="left"';
200
201            if ($title) {
202                $ret .= ' title="' . $title . '"';
203                $ret .= ' alt="'   . $title .'"';
204            }else{
205                $ret .= ' alt=""';
206            }
207
208            if ( !is_null($width) )
209                $ret .= ' width="'.$this->_xmlEntities($width).'"';
210
211            if ( !is_null($height) )
212                $ret .= ' height="'.$this->_xmlEntities($height).'"';
213
214            $ret .= ' />';
215
216        }elseif($mime == 'application/x-shockwave-flash'){
217            $ret .= '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'.
218                    ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"';
219            if ( !is_null($width) ) $ret .= ' width="'.$this->_xmlEntities($width).'"';
220            if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"';
221            $ret .= '>'.DOKU_LF;
222            $ret .= '<param name="movie" value="'.ml($src).'" />'.DOKU_LF;
223            $ret .= '<param name="quality" value="high" />'.DOKU_LF;
224            $ret .= '<embed src="'.ml($src).'"'.
225                    ' quality="high"';
226            if ( !is_null($width) ) $ret .= ' width="'.$this->_xmlEntities($width).'"';
227            if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"';
228            $ret .= ' type="application/x-shockwave-flash"'.
229                    ' pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>'.DOKU_LF;
230            $ret .= '</object>'.DOKU_LF;
231
232        }elseif($title){
233            // well at least we have a title to display
234            $ret .= $this->_xmlEntities($title);
235        }else{
236            // just show the sourcename
237            $ret .= $this->_xmlEntities(basename(noNS($src)));
238        }
239
240        return $ret;
241    }
242
243
244    /**
245     * Render an internal Wiki Link
246     *
247     * $search and $returnonly are not for the renderer but are used
248     * elsewhere - no need to implement them in other renderers
249     *
250     * @author Andreas Gohr <andi@splitbrain.org>
251     */
252    function internallink($id, $name = NULL, $search=NULL,$returnonly=false) {
253        global $conf;
254        global $ID;
255        // default name is based on $id as given
256        $default = $this->_simpleTitle($id);// now first resolve and clean up the $id
257        resolve_pageid(getNS($ID),$id,$exists);
258        $name = $this->_getLinkTitle($name, $default, $isImage, $id);
259        if ( !$isImage ) {
260            if ( $exists ) {
261                $class='wikilink1';
262            } else {
263                $class='wikilink2';
264                $link['rel']='nofollow';
265            }
266        } else {
267            $class='media';
268        }
269
270$urlPrefixStr = $this->create_url_prefix($ID);
271        //keep hash anchor
272        list($id,$hash) = explode('#',$id,2);
273        if(!empty($hash)) $hash = $this->_headerToLink($hash);
274
275        //prepare for formating
276        $link['target'] = $conf['target']['wiki'];
277        $link['style']  = '';
278        $link['pre']    = '';
279        $link['suf']    = '';
280        // highlight link to current page
281        if ($id == $ID) {
282            $link['pre']    = '<span class="curid">';
283            $link['suf']    = '</span>';
284        }
285        $link['more']   = '';
286        $link['class']  = $class;
287$link['url']    = $urlPrefixStr . str_replace(':', '/', $id) . '.html';// Links relativ
288        $link['name']   = $name;
289        $link['title']  = $id;
290        //add search string
291        if($search){
292            ($conf['userewrite']) ? $link['url'].='?' : $link['url'].='&amp;';
293            if(is_array($search)){
294                $search = array_map('rawurlencode',$search);
295                $link['url'] .= 's[]='.join('&amp;s[]=',$search);
296            }else{
297                $link['url'] .= 's='.rawurlencode($search);
298            }
299        }
300
301        //keep hash
302        if($hash) $link['url'].='#'.$hash;
303
304        //output formatted
305        if($returnonly){
306            return $this->_formatLink($link);
307        }else{
308            $this->doc .= $this->_formatLink($link);
309        }
310    }
311
312
313
314     /**
315     * Create URL-prefix to turn almost absolute path into relative path
316     * Carsten Graw
317     */
318    function create_url_prefix($ID) {
319        // $ID enth"alt die ID der Seite, die die Links enth"alt.
320        // $id ist ein Link-Ziel in der Seite ID.
321        //echo '<hr><div>ID: ', $ID, '<br />';
322        //echo 'id: ', $id, '</div><hr />';
323        //
324        $directoryLevel = substr_count($ID, ':');
325        $urlPrefixStr = '';
326        for ($i = 0; $i < $directoryLevel; $i++) {
327            $urlPrefixStr .= '../';
328        }
329
330        return $urlPrefixStr;
331    }
332
333    /**
334     * Top-Level Sections are slides
335    function section_open($level) {
336        if($level < 3){
337            $this->doc .= '<div class="slidecontent">'.DOKU_LF;
338        }else{
339            $this->doc .= '<div>'.DOKU_LF;
340        }
341        // we don't use it
342    }
343     */
344
345    /**
346     * Throw away footnote
347    function footnote_close() {
348        // recover footnote into the stack and restore old content
349        $footnote = $this->doc;
350        $this->doc = $this->store;
351        $this->store = '';
352    }
353     */
354
355    /**
356     * No acronyms in a presentation
357    function acronym($acronym){
358        $this->doc .= $this->_xmlEntities($acronym);
359    }
360     */
361
362    /**
363     * A line stops the slide and start the handout section
364    function hr() {
365        $this->doc .= '</div>'.DOKU_LF;
366        $this->doc .= '<div class="handout">'.DOKU_LF;
367    }
368     */
369
370
371/**
372 * Places the TOC where the function is called
373 *
374 * If you use this you most probably want to call tpl_content with
375 * a false argument
376 *
377 * @author Andreas Gohr <andi@splitbrain.org>
378 */
379function tpl_toc2($return=false){
380    global $TOC;
381    global $ACT;
382    global $ID;
383    global $REV;
384    global $INFO;
385    $toc = array();
386
387    if(is_array($TOC)){
388        // if a TOC was prepared in global scope, always use it
389        $toc = $TOC;
390    }elseif(($ACT == 'show' || substr($ACT,0,6) == 'export') && !$REV && $INFO['exists']){
391        // get TOC from metadata, render if neccessary
392        $meta = p_get_metadata($ID, false, true);
393        if(isset($meta['internal']['toc'])){
394            $tocok = $meta['internal']['toc'];
395        }else{
396            $tocok = true;
397        }
398        $toc   = $meta['description']['tableofcontents'];
399        if(!$tocok || !is_array($toc) || count($toc) < 3){
400            $toc = array();
401        }
402    }elseif($ACT == 'admin'){
403        // try to load admin plugin TOC FIXME: duplicates code from tpl_admin
404        $plugin = null;
405        if (!empty($_REQUEST['page'])) {
406            $pluginlist = plugin_list('admin');
407            if (in_array($_REQUEST['page'], $pluginlist)) {
408                // attempt to load the plugin
409                $plugin =& plugin_load('admin',$_REQUEST['page']);
410            }
411        }
412        if ( ($plugin !== null) &&
413             (!$plugin->forAdminOnly() || $INFO['isadmin']) ){
414            $toc = $plugin->getTOC();
415            $TOC = $toc; // avoid later rebuild
416        }
417    }
418
419    $html = html_TOC($toc);
420    if($return) return $html;
421    echo $html;
422}
423
424
425
426}
427
428
429//Setup VIM: ex: et ts=4 enc=utf-8 :
430