xref: /plugin/dw2pdf/renderer.php (revision c4c95814504bb32ebf3f9b6a0e189c19779325fb)
1a876b55bSAndreas Gohr<?php
2852931daSAndreas Gohr
3852931daSAndreas Gohr// phpcs:disable: PSR1.Methods.CamelCapsMethodName.NotCamelCaps
4852931daSAndreas Gohr// phpcs:disable: PSR2.Methods.MethodDeclaration.Underscore
5852931daSAndreas Gohr
6a876b55bSAndreas Gohr/**
7a876b55bSAndreas Gohr * DokuWiki Plugin dw2pdf (Renderer Component)
8852931daSAndreas Gohr * Render xhtml suitable as input for mpdf library
9a876b55bSAndreas Gohr *
10a876b55bSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11a876b55bSAndreas Gohr * @author  Andreas Gohr <gohr@cosmocode.de>
12a876b55bSAndreas Gohr */
13852931daSAndreas Gohrclass renderer_plugin_dw2pdf extends Doku_Renderer_xhtml
14852931daSAndreas Gohr{
15bb7717bcSGerrit Uitslag    private $lastHeaderLevel = -1;
16bb7717bcSGerrit Uitslag    private $originalHeaderLevel = 0;
17bb7717bcSGerrit Uitslag    private $difference = 0;
189c76f78dSVincent GIRARD    private static $header_count = [];
199c76f78dSVincent GIRARD    private static $previous_level = 0;
20bb7717bcSGerrit Uitslag
2160e59de7SGerrit Uitslag    /**
2260e59de7SGerrit Uitslag     * Stores action instance
2360e59de7SGerrit Uitslag     *
2460e59de7SGerrit Uitslag     * @var action_plugin_dw2pdf
2560e59de7SGerrit Uitslag     */
26852931daSAndreas Gohr    private $actioninstance;
2760e59de7SGerrit Uitslag
2860e59de7SGerrit Uitslag    /**
2960e59de7SGerrit Uitslag     * load action plugin instance
3060e59de7SGerrit Uitslag     */
31852931daSAndreas Gohr    public function __construct()
32852931daSAndreas Gohr    {
3360e59de7SGerrit Uitslag        $this->actioninstance = plugin_load('action', 'dw2pdf');
3460e59de7SGerrit Uitslag    }
3560e59de7SGerrit Uitslag
36852931daSAndreas Gohr    public function document_start()
37852931daSAndreas Gohr    {
3860e59de7SGerrit Uitslag        global $ID;
3960e59de7SGerrit Uitslag
4060e59de7SGerrit Uitslag        parent::document_start();
4160e59de7SGerrit Uitslag
4260e59de7SGerrit Uitslag        //ancher for rewritten links to included pages
4360e59de7SGerrit Uitslag        $check = false;
4460e59de7SGerrit Uitslag        $pid = sectionID($ID, $check);
4560e59de7SGerrit Uitslag
4660e59de7SGerrit Uitslag        $this->doc .= "<a name=\"{$pid}__\">";
4760e59de7SGerrit Uitslag        $this->doc .= "</a>";
489c76f78dSVincent GIRARD
49852931daSAndreas Gohr        self::$header_count[1] = $this->actioninstance->getCurrentBookChapter();
5060e59de7SGerrit Uitslag    }
5183bac986SAndreas Gohr
52a876b55bSAndreas Gohr    /**
53a876b55bSAndreas Gohr     * Make available as XHTML replacement renderer
54236e9da2SGerrit Uitslag     *
55236e9da2SGerrit Uitslag     * @param $format
56236e9da2SGerrit Uitslag     * @return bool
57a876b55bSAndreas Gohr     */
58852931daSAndreas Gohr    public function canRender($format)
59852931daSAndreas Gohr    {
60*c4c95814SKlap-in        if ($format == 'xhtml') {
61*c4c95814SKlap-in            return true;
62*c4c95814SKlap-in        }
63a876b55bSAndreas Gohr        return false;
64a876b55bSAndreas Gohr    }
65a876b55bSAndreas Gohr
66a876b55bSAndreas Gohr    /**
67a876b55bSAndreas Gohr     * Simplified header printing with PDF bookmarks
68236e9da2SGerrit Uitslag     *
69236e9da2SGerrit Uitslag     * @param string $text
70bb7717bcSGerrit Uitslag     * @param int $level from 1 (highest) to 6 (lowest)
71236e9da2SGerrit Uitslag     * @param int $pos
72a876b55bSAndreas Gohr     */
73852931daSAndreas Gohr    public function header($text, $level, $pos, $returnonly = false)
74852931daSAndreas Gohr    {
75*c4c95814SKlap-in        if (!$text) {
76*c4c95814SKlap-in            return;
77*c4c95814SKlap-in        } //skip empty headlines
7860e59de7SGerrit Uitslag        global $ID;
79a876b55bSAndreas Gohr
80244aaa51SMichael Hamann        $hid = $this->_headerToLink($text, true);
8157a1b6f9SGerrit Uitslag
8257a1b6f9SGerrit Uitslag        //only add items within global configured levels (doesn't check the pdf toc settings)
8357a1b6f9SGerrit Uitslag        $this->toc_additem($hid, $text, $level);
8457a1b6f9SGerrit Uitslag
8560e59de7SGerrit Uitslag        $check = false;
8660e59de7SGerrit Uitslag        $pid = sectionID($ID, $check);
8760e59de7SGerrit Uitslag        $hid = $pid . '__' . $hid;
88244aaa51SMichael Hamann
899c76f78dSVincent GIRARD
909c76f78dSVincent GIRARD        // retrieve numbered headings option
919c76f78dSVincent GIRARD        $isnumberedheadings = $this->actioninstance->getExportConfig('headernumber');
929c76f78dSVincent GIRARD
939c76f78dSVincent GIRARD        $header_prefix = "";
949c76f78dSVincent GIRARD        if ($isnumberedheadings) {
959c76f78dSVincent GIRARD            if ($level > 0) {
96852931daSAndreas Gohr                if (self::$previous_level > $level) {
97852931daSAndreas Gohr                    for ($i = $level + 1; $i <= self::$previous_level; $i++) {
98852931daSAndreas Gohr                        self::$header_count[$i] = 0;
999c76f78dSVincent GIRARD                    }
1009c76f78dSVincent GIRARD                }
1019c76f78dSVincent GIRARD            }
102852931daSAndreas Gohr            self::$header_count[$level]++;
1039c76f78dSVincent GIRARD
1049c76f78dSVincent GIRARD            // $header_prefix = "";
1059c76f78dSVincent GIRARD            for ($i = 1; $i <= $level; $i++) {
106852931daSAndreas Gohr                $header_prefix .= self::$header_count[$i] . ".";
1079c76f78dSVincent GIRARD            }
1089c76f78dSVincent GIRARD        }
1099c76f78dSVincent GIRARD
110a876b55bSAndreas Gohr        // add PDF bookmark
1117fa15500SAndreas Gohr        $bookmark = '';
112bb7717bcSGerrit Uitslag        $maxbookmarklevel = $this->actioninstance->getExportConfig('maxbookmarks');
113bb7717bcSGerrit Uitslag        // 0: off, 1-6: show down to this level
114bb7717bcSGerrit Uitslag        if ($maxbookmarklevel && $maxbookmarklevel >= $level) {
115bb7717bcSGerrit Uitslag            $bookmarklevel = $this->calculateBookmarklevel($level);
116852931daSAndreas Gohr            $bookmark = sprintf(
117852931daSAndreas Gohr                '<bookmark content="%s %s" level="%d" />',
118852931daSAndreas Gohr                $header_prefix,
119852931daSAndreas Gohr                $this->_xmlEntities($text),
120852931daSAndreas Gohr                $bookmarklevel
121852931daSAndreas Gohr            );
122a876b55bSAndreas Gohr        }
123a876b55bSAndreas Gohr
124a876b55bSAndreas Gohr        // print header
1257fa15500SAndreas Gohr        $this->doc .= DOKU_LF . "<h$level>$bookmark";
1269c76f78dSVincent GIRARD        $this->doc .= $header_prefix . "<a name=\"$hid\">";
127a876b55bSAndreas Gohr        $this->doc .= $this->_xmlEntities($text);
128244aaa51SMichael Hamann        $this->doc .= "</a>";
129a876b55bSAndreas Gohr        $this->doc .= "</h$level>" . DOKU_LF;
130852931daSAndreas Gohr        self::$previous_level = $level;
131a876b55bSAndreas Gohr    }
132a876b55bSAndreas Gohr
133aab792a5SAndreas Gohr    /**
134bb7717bcSGerrit Uitslag     * Bookmark levels might increase maximal +1 per level.
135bb7717bcSGerrit Uitslag     * (note: levels start at 1, bookmarklevels at 0)
136bb7717bcSGerrit Uitslag     *
137bb7717bcSGerrit Uitslag     * @param int $level 1 (highest) to 6 (lowest)
138bb7717bcSGerrit Uitslag     * @return int
139bb7717bcSGerrit Uitslag     */
140852931daSAndreas Gohr    protected function calculateBookmarklevel($level)
141852931daSAndreas Gohr    {
142bb7717bcSGerrit Uitslag        if ($this->lastHeaderLevel == -1) {
143bb7717bcSGerrit Uitslag            $this->lastHeaderLevel = $level;
144bb7717bcSGerrit Uitslag        }
145bb7717bcSGerrit Uitslag        $step = $level - $this->lastHeaderLevel;
146bb7717bcSGerrit Uitslag        if ($step > 1) {
147852931daSAndreas Gohr            $this->difference += $step - 1;
148bb7717bcSGerrit Uitslag        }
149bb7717bcSGerrit Uitslag        if ($step < 0) {
150bb7717bcSGerrit Uitslag            $this->difference = min($this->difference, $level - $this->originalHeaderLevel);
151bb7717bcSGerrit Uitslag            $this->difference = max($this->difference, 0);
152bb7717bcSGerrit Uitslag        }
153bb7717bcSGerrit Uitslag
154bb7717bcSGerrit Uitslag        $bookmarklevel = $level - $this->difference;
155bb7717bcSGerrit Uitslag
156bb7717bcSGerrit Uitslag        if ($step > 1) {
157bb7717bcSGerrit Uitslag            $this->originalHeaderLevel = $bookmarklevel;
158bb7717bcSGerrit Uitslag        }
159bb7717bcSGerrit Uitslag
160bb7717bcSGerrit Uitslag        $this->lastHeaderLevel = $level;
161bb7717bcSGerrit Uitslag        return $bookmarklevel - 1; //zero indexed
162bb7717bcSGerrit Uitslag    }
163bb7717bcSGerrit Uitslag
164bb7717bcSGerrit Uitslag    /**
16560e59de7SGerrit Uitslag     * Render a page local link
16660e59de7SGerrit Uitslag     *
167236e9da2SGerrit Uitslag     * // modified copy of parent function
168236e9da2SGerrit Uitslag     *
16960e59de7SGerrit Uitslag     * @param string $hash hash link identifier
17060e59de7SGerrit Uitslag     * @param string $name name for the link
171236e9da2SGerrit Uitslag     * @param bool $returnonly
172236e9da2SGerrit Uitslag     * @return string|void
17360e59de7SGerrit Uitslag     *
17460e59de7SGerrit Uitslag     * @see Doku_Renderer_xhtml::locallink
17560e59de7SGerrit Uitslag     */
176852931daSAndreas Gohr    public function locallink($hash, $name = null, $returnonly = false)
177852931daSAndreas Gohr    {
17860e59de7SGerrit Uitslag        global $ID;
17960e59de7SGerrit Uitslag        $name = $this->_getLinkTitle($name, $hash, $isImage);
18060e59de7SGerrit Uitslag        $hash = $this->_headerToLink($hash);
18160e59de7SGerrit Uitslag        $title = $ID . ' ↵';
18260e59de7SGerrit Uitslag
18360e59de7SGerrit Uitslag        $check = false;
18460e59de7SGerrit Uitslag        $pid = sectionID($ID, $check);
18560e59de7SGerrit Uitslag
18660e59de7SGerrit Uitslag        $this->doc .= '<a href="#' . $pid . '__' . $hash . '" title="' . $title . '" class="wikilink1">';
18760e59de7SGerrit Uitslag        $this->doc .= $name;
18860e59de7SGerrit Uitslag        $this->doc .= '</a>';
18960e59de7SGerrit Uitslag    }
19060e59de7SGerrit Uitslag
19160e59de7SGerrit Uitslag    /**
192aab792a5SAndreas Gohr     * Wrap centered media in a div to center it
193236e9da2SGerrit Uitslag     *
194236e9da2SGerrit Uitslag     * @param string $src media ID
195236e9da2SGerrit Uitslag     * @param string $title descriptive text
196236e9da2SGerrit Uitslag     * @param string $align left|center|right
197236e9da2SGerrit Uitslag     * @param int $width width of media in pixel
198236e9da2SGerrit Uitslag     * @param int $height height of media in pixel
199236e9da2SGerrit Uitslag     * @param string $cache cache|recache|nocache
200236e9da2SGerrit Uitslag     * @param bool $render should the media be embedded inline or just linked
201236e9da2SGerrit Uitslag     * @return string
202aab792a5SAndreas Gohr     */
203852931daSAndreas Gohr    public function _media(
204852931daSAndreas Gohr        $src,
205852931daSAndreas Gohr        $title = null,
206852931daSAndreas Gohr        $align = null,
207852931daSAndreas Gohr        $width = null,
208852931daSAndreas Gohr        $height = null,
209852931daSAndreas Gohr        $cache = null,
210852931daSAndreas Gohr        $render = true
211852931daSAndreas Gohr    ) {
212aab792a5SAndreas Gohr
213aab792a5SAndreas Gohr        $out = '';
214aab792a5SAndreas Gohr        if ($align == 'center') {
215aab792a5SAndreas Gohr            $out .= '<div align="center" style="text-align: center">';
216aab792a5SAndreas Gohr        }
217aab792a5SAndreas Gohr
218aab792a5SAndreas Gohr        $out .= parent::_media($src, $title, $align, $width, $height, $cache, $render);
219aab792a5SAndreas Gohr
220aab792a5SAndreas Gohr        if ($align == 'center') {
221aab792a5SAndreas Gohr            $out .= '</div>';
222aab792a5SAndreas Gohr        }
223aab792a5SAndreas Gohr
224aab792a5SAndreas Gohr        return $out;
225aab792a5SAndreas Gohr    }
226aab792a5SAndreas Gohr
227551dd41eSAndreas Gohr    /**
228551dd41eSAndreas Gohr     * hover info makes no sense in PDFs, so drop acronyms
229236e9da2SGerrit Uitslag     *
230236e9da2SGerrit Uitslag     * @param string $acronym
231551dd41eSAndreas Gohr     */
232852931daSAndreas Gohr    public function acronym($acronym)
233852931daSAndreas Gohr    {
234551dd41eSAndreas Gohr        $this->doc .= $this->_xmlEntities($acronym);
235551dd41eSAndreas Gohr    }
236551dd41eSAndreas Gohr
2379eb4c81fSAndreas Gohr    /**
2389eb4c81fSAndreas Gohr     * reformat links if needed
239236e9da2SGerrit Uitslag     *
240236e9da2SGerrit Uitslag     * @param array $link
241236e9da2SGerrit Uitslag     * @return string
2429eb4c81fSAndreas Gohr     */
243852931daSAndreas Gohr    public function _formatLink($link)
244852931daSAndreas Gohr    {
24560e59de7SGerrit Uitslag
24660e59de7SGerrit Uitslag        // for internal links contains the title the pageid
24760e59de7SGerrit Uitslag        if (in_array($link['title'], $this->actioninstance->getExportedPages())) {
248852931daSAndreas Gohr            [/* url */, $hash] = sexplode('#', $link['url'], 2, '');
24960e59de7SGerrit Uitslag
25060e59de7SGerrit Uitslag            $check = false;
25160e59de7SGerrit Uitslag            $pid = sectionID($link['title'], $check);
25260e59de7SGerrit Uitslag            $link['url'] = "#" . $pid . '__' . $hash;
25360e59de7SGerrit Uitslag        }
25460e59de7SGerrit Uitslag
2559eb4c81fSAndreas Gohr        // prefix interwiki links with interwiki icon
2569eb4c81fSAndreas Gohr        if ($link['name'][0] != '<' && preg_match('/\binterwiki iw_(.\w+)\b/', $link['class'], $m)) {
2579eb4c81fSAndreas Gohr            if (file_exists(DOKU_INC . 'lib/images/interwiki/' . $m[1] . '.png')) {
2589eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki/' . $m[1] . '.png';
2599eb4c81fSAndreas Gohr            } elseif (file_exists(DOKU_INC . 'lib/images/interwiki/' . $m[1] . '.gif')) {
2609eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki/' . $m[1] . '.gif';
2619eb4c81fSAndreas Gohr            } else {
2629eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki.png';
2639eb4c81fSAndreas Gohr            }
2649eb4c81fSAndreas Gohr
265852931daSAndreas Gohr            $link['name'] = sprintf(
266852931daSAndreas Gohr                '<img src="%s" width="16" height="16" style="vertical-align: middle" class="%s" />%s',
267852931daSAndreas Gohr                $img,
268852931daSAndreas Gohr                $link['class'],
269852931daSAndreas Gohr                $link['name']
270852931daSAndreas Gohr            );
2719eb4c81fSAndreas Gohr        }
2729eb4c81fSAndreas Gohr        return parent::_formatLink($link);
2739eb4c81fSAndreas Gohr    }
274ccdd3126SAndreas Gohr
275ccdd3126SAndreas Gohr    /**
276ccdd3126SAndreas Gohr     * no obfuscation for email addresses
277236e9da2SGerrit Uitslag     *
278236e9da2SGerrit Uitslag     * @param string $address
279236e9da2SGerrit Uitslag     * @param null $name
280236e9da2SGerrit Uitslag     * @param bool $returnonly
281236e9da2SGerrit Uitslag     * @return string|void
282ccdd3126SAndreas Gohr     */
283852931daSAndreas Gohr    public function emaillink($address, $name = null, $returnonly = false)
284852931daSAndreas Gohr    {
285ccdd3126SAndreas Gohr        global $conf;
286ccdd3126SAndreas Gohr        $old = $conf['mailguard'];
287ccdd3126SAndreas Gohr        $conf['mailguard'] = 'none';
2889e1a2ac6SAnael Mobilia        parent::emaillink($address, $name, $returnonly);
289ccdd3126SAndreas Gohr        $conf['mailguard'] = $old;
290ccdd3126SAndreas Gohr    }
291a876b55bSAndreas Gohr}
292