xref: /plugin/dw2pdf/renderer.php (revision bb7717bcc4e44b06fc01aeb8ea52a07716f70085)
1<?php
2/**
3 * DokuWiki Plugin dw2pdf (Renderer Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr <gohr@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) die();
11
12/**
13 * Render xhtml suitable as input for mpdf library
14 */
15class renderer_plugin_dw2pdf extends Doku_Renderer_xhtml {
16
17    private $lastHeaderLevel = -1;
18    private $originalHeaderLevel = 0;
19    private $difference = 0;
20
21    /**
22     * Stores action instance
23     *
24     * @var action_plugin_dw2pdf
25     */
26    private $actioninstance = null;
27
28    /**
29     * load action plugin instance
30     */
31    public function __construct() {
32        $this->actioninstance = plugin_load('action', 'dw2pdf');
33    }
34
35    public function document_start() {
36        global $ID;
37
38        parent::document_start();
39
40        //ancher for rewritten links to included pages
41        $check = false;
42        $pid = sectionID($ID, $check);
43
44        $this->doc .= "<a name=\"{$pid}__\">";
45        $this->doc .= "</a>";
46    }
47
48    /**
49     * Make available as XHTML replacement renderer
50     *
51     * @param $format
52     * @return bool
53     */
54    public function canRender($format){
55        if($format == 'xhtml') return true;
56        return false;
57    }
58
59    /**
60     * Simplified header printing with PDF bookmarks
61     *
62     * @param string $text
63     * @param int $level from 1 (highest) to 6 (lowest)
64     * @param int $pos
65     */
66    public function header($text, $level, $pos) {
67        if(!$text) return; //skip empty headlines
68        global $ID;
69
70        $hid = $this->_headerToLink($text, true);
71
72        //only add items within global configured levels (doesn't check the pdf toc settings)
73        $this->toc_additem($hid, $text, $level);
74
75        $check = false;
76        $pid = sectionID($ID, $check);
77        $hid = $pid . '__' . $hid;
78
79        // add PDF bookmark
80        $bookmark = '';
81        $maxbookmarklevel = $this->actioninstance->getExportConfig('maxbookmarks');
82        // 0: off, 1-6: show down to this level
83        if($maxbookmarklevel && $maxbookmarklevel >= $level) {
84            $bookmarklevel = $this->calculateBookmarklevel($level);
85            $bookmark = '<bookmark content="' . $this->_xmlEntities($text) . '" level="' . ($bookmarklevel) . '" />';
86        }
87
88        // print header
89        $this->doc .= DOKU_LF . "<h$level>$bookmark";
90        $this->doc .= "<a name=\"$hid\">";
91        $this->doc .= $this->_xmlEntities($text);
92        $this->doc .= "</a>";
93        $this->doc .= "</h$level>" . DOKU_LF;
94    }
95
96    /**
97     * Bookmark levels might increase maximal +1 per level.
98     * (note: levels start at 1, bookmarklevels at 0)
99     *
100     * @param int $level 1 (highest) to 6 (lowest)
101     * @return int
102     */
103    protected function calculateBookmarklevel($level) {
104        if($this->lastHeaderLevel == -1) {
105            $this->lastHeaderLevel = $level;
106        }
107        $step = $level - $this->lastHeaderLevel;
108        if($step > 1) {
109            $this->difference = $this->difference + ($step - 1);
110        }
111        if($step < 0 ) {
112            $this->difference = min($this->difference, $level - $this->originalHeaderLevel);
113            $this->difference = max($this->difference, 0);
114        }
115
116        $bookmarklevel = $level - $this->difference;
117
118        if($step > 1) {
119            $this->originalHeaderLevel = $bookmarklevel;
120        }
121
122        $this->lastHeaderLevel = $level;
123        return $bookmarklevel - 1; //zero indexed
124    }
125
126    /**
127     * Render a page local link
128     *
129     * // modified copy of parent function
130     *
131     * @param string $hash hash link identifier
132     * @param string $name name for the link
133     * @param bool $returnonly
134     * @return string|void
135     *
136     * @see Doku_Renderer_xhtml::locallink
137     */
138    function locallink($hash, $name = null, $returnonly = false) {
139        global $ID;
140        $name  = $this->_getLinkTitle($name, $hash, $isImage);
141        $hash  = $this->_headerToLink($hash);
142        $title = $ID.' ↵';
143
144        $check = false;
145        $pid = sectionID($ID, $check);
146
147        $this->doc .= '<a href="#'. $pid . '__' . $hash.'" title="'.$title.'" class="wikilink1">';
148        $this->doc .= $name;
149        $this->doc .= '</a>';
150    }
151
152    /**
153     * Wrap centered media in a div to center it
154     *
155     * @param string $src       media ID
156     * @param string $title     descriptive text
157     * @param string $align     left|center|right
158     * @param int    $width     width of media in pixel
159     * @param int    $height    height of media in pixel
160     * @param string $cache     cache|recache|nocache
161     * @param bool   $render    should the media be embedded inline or just linked
162     * @return string
163     */
164    function _media ($src, $title=NULL, $align=NULL, $width=NULL,
165                      $height=NULL, $cache=NULL, $render = true) {
166
167        $out = '';
168        if($align == 'center'){
169            $out .= '<div align="center" style="text-align: center">';
170        }
171
172        $out .= parent::_media ($src, $title, $align, $width, $height, $cache, $render);
173
174        if($align == 'center'){
175            $out .= '</div>';
176        }
177
178        return $out;
179    }
180
181    /**
182     * hover info makes no sense in PDFs, so drop acronyms
183     *
184     * @param string $acronym
185     */
186    function acronym($acronym) {
187        $this->doc .= $this->_xmlEntities($acronym);
188    }
189
190    /**
191     * reformat links if needed
192     *
193     * @param array $link
194     * @return string
195     */
196    function _formatLink($link){
197
198        // for internal links contains the title the pageid
199        if(in_array($link['title'], $this->actioninstance->getExportedPages())) {
200            list(/* $url */, $hash) = explode('#', $link['url'], 2);
201
202            $check = false;
203            $pid = sectionID($link['title'], $check);
204            $link['url'] = "#" . $pid . '__' . $hash;
205        }
206
207
208        // prefix interwiki links with interwiki icon
209        if($link['name'][0] != '<' && preg_match('/\binterwiki iw_(.\w+)\b/',$link['class'],$m)){
210            if(file_exists(DOKU_INC.'lib/images/interwiki/'.$m[1].'.png')){
211                $img = DOKU_BASE.'lib/images/interwiki/'.$m[1].'.png';
212            }elseif(file_exists(DOKU_INC.'lib/images/interwiki/'.$m[1].'.gif')){
213                $img = DOKU_BASE.'lib/images/interwiki/'.$m[1].'.gif';
214            }else{
215                $img = DOKU_BASE.'lib/images/interwiki.png';
216            }
217
218            $link['name'] = '<img src="'.$img.'" width="16" height="16" style="vertical-align: center" class="'.$link['class'].'" />'.$link['name'];
219        }
220        return parent::_formatLink($link);
221    }
222
223    /**
224     * no obfuscation for email addresses
225     *
226     * @param string $address
227     * @param null $name
228     * @param bool $returnonly
229     * @return string|void
230     */
231    function emaillink($address, $name = NULL, $returnonly = false) {
232        global $conf;
233        $old = $conf['mailguard'];
234        $conf['mailguard'] = 'none';
235        parent::emaillink($address, $name, $returnonly);
236        $conf['mailguard'] = $old;
237    }
238
239}
240
241