xref: /plugin/dw2pdf/renderer.php (revision 5aaf6fd4ab92733e0886392ca32eefc026e09a10)
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    {
60c4c95814SKlap-in        if ($format == 'xhtml') {
61c4c95814SKlap-in            return true;
62c4c95814SKlap-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*5aaf6fd4SGerrit Uitslag        //skip empty headlines
76c4c95814SKlap-in        if (!$text) {
77c4c95814SKlap-in            return;
78*5aaf6fd4SGerrit Uitslag        }
7960e59de7SGerrit Uitslag        global $ID;
80a876b55bSAndreas Gohr
81244aaa51SMichael Hamann        $hid = $this->_headerToLink($text, true);
8257a1b6f9SGerrit Uitslag
8357a1b6f9SGerrit Uitslag        //only add items within global configured levels (doesn't check the pdf toc settings)
8457a1b6f9SGerrit Uitslag        $this->toc_additem($hid, $text, $level);
8557a1b6f9SGerrit Uitslag
8660e59de7SGerrit Uitslag        $check = false;
8760e59de7SGerrit Uitslag        $pid = sectionID($ID, $check);
8860e59de7SGerrit Uitslag        $hid = $pid . '__' . $hid;
89244aaa51SMichael Hamann
909c76f78dSVincent GIRARD
919c76f78dSVincent GIRARD        // retrieve numbered headings option
929c76f78dSVincent GIRARD        $isnumberedheadings = $this->actioninstance->getExportConfig('headernumber');
939c76f78dSVincent GIRARD
949c76f78dSVincent GIRARD        $header_prefix = "";
959c76f78dSVincent GIRARD        if ($isnumberedheadings) {
969c76f78dSVincent GIRARD            if ($level > 0) {
97852931daSAndreas Gohr                if (self::$previous_level > $level) {
98852931daSAndreas Gohr                    for ($i = $level + 1; $i <= self::$previous_level; $i++) {
99852931daSAndreas Gohr                        self::$header_count[$i] = 0;
1009c76f78dSVincent GIRARD                    }
1019c76f78dSVincent GIRARD                }
1029c76f78dSVincent GIRARD            }
103852931daSAndreas Gohr            self::$header_count[$level]++;
1049c76f78dSVincent GIRARD
1059c76f78dSVincent GIRARD            // $header_prefix = "";
1069c76f78dSVincent GIRARD            for ($i = 1; $i <= $level; $i++) {
107852931daSAndreas Gohr                $header_prefix .= self::$header_count[$i] . ".";
1089c76f78dSVincent GIRARD            }
1099c76f78dSVincent GIRARD        }
1109c76f78dSVincent GIRARD
111a876b55bSAndreas Gohr        // add PDF bookmark
1127fa15500SAndreas Gohr        $bookmark = '';
113bb7717bcSGerrit Uitslag        $maxbookmarklevel = $this->actioninstance->getExportConfig('maxbookmarks');
114bb7717bcSGerrit Uitslag        // 0: off, 1-6: show down to this level
115bb7717bcSGerrit Uitslag        if ($maxbookmarklevel && $maxbookmarklevel >= $level) {
116bb7717bcSGerrit Uitslag            $bookmarklevel = $this->calculateBookmarklevel($level);
117852931daSAndreas Gohr            $bookmark = sprintf(
118852931daSAndreas Gohr                '<bookmark content="%s %s" level="%d" />',
119852931daSAndreas Gohr                $header_prefix,
120852931daSAndreas Gohr                $this->_xmlEntities($text),
121852931daSAndreas Gohr                $bookmarklevel
122852931daSAndreas Gohr            );
123a876b55bSAndreas Gohr        }
124a876b55bSAndreas Gohr
125a876b55bSAndreas Gohr        // print header
1267fa15500SAndreas Gohr        $this->doc .= DOKU_LF . "<h$level>$bookmark";
1279c76f78dSVincent GIRARD        $this->doc .= $header_prefix . "<a name=\"$hid\">";
128a876b55bSAndreas Gohr        $this->doc .= $this->_xmlEntities($text);
129244aaa51SMichael Hamann        $this->doc .= "</a>";
130a876b55bSAndreas Gohr        $this->doc .= "</h$level>" . DOKU_LF;
131852931daSAndreas Gohr        self::$previous_level = $level;
132a876b55bSAndreas Gohr    }
133a876b55bSAndreas Gohr
134aab792a5SAndreas Gohr    /**
135bb7717bcSGerrit Uitslag     * Bookmark levels might increase maximal +1 per level.
136bb7717bcSGerrit Uitslag     * (note: levels start at 1, bookmarklevels at 0)
137bb7717bcSGerrit Uitslag     *
138bb7717bcSGerrit Uitslag     * @param int $level 1 (highest) to 6 (lowest)
139bb7717bcSGerrit Uitslag     * @return int
140bb7717bcSGerrit Uitslag     */
141852931daSAndreas Gohr    protected function calculateBookmarklevel($level)
142852931daSAndreas Gohr    {
143bb7717bcSGerrit Uitslag        if ($this->lastHeaderLevel == -1) {
144bb7717bcSGerrit Uitslag            $this->lastHeaderLevel = $level;
145bb7717bcSGerrit Uitslag        }
146bb7717bcSGerrit Uitslag        $step = $level - $this->lastHeaderLevel;
147bb7717bcSGerrit Uitslag        if ($step > 1) {
148852931daSAndreas Gohr            $this->difference += $step - 1;
149bb7717bcSGerrit Uitslag        }
150bb7717bcSGerrit Uitslag        if ($step < 0) {
151bb7717bcSGerrit Uitslag            $this->difference = min($this->difference, $level - $this->originalHeaderLevel);
152bb7717bcSGerrit Uitslag            $this->difference = max($this->difference, 0);
153bb7717bcSGerrit Uitslag        }
154bb7717bcSGerrit Uitslag
155bb7717bcSGerrit Uitslag        $bookmarklevel = $level - $this->difference;
156bb7717bcSGerrit Uitslag
157bb7717bcSGerrit Uitslag        if ($step > 1) {
158bb7717bcSGerrit Uitslag            $this->originalHeaderLevel = $bookmarklevel;
159bb7717bcSGerrit Uitslag        }
160bb7717bcSGerrit Uitslag
161bb7717bcSGerrit Uitslag        $this->lastHeaderLevel = $level;
162bb7717bcSGerrit Uitslag        return $bookmarklevel - 1; //zero indexed
163bb7717bcSGerrit Uitslag    }
164bb7717bcSGerrit Uitslag
165bb7717bcSGerrit Uitslag    /**
16660e59de7SGerrit Uitslag     * Render a page local link
16760e59de7SGerrit Uitslag     *
168236e9da2SGerrit Uitslag     * // modified copy of parent function
169236e9da2SGerrit Uitslag     *
17060e59de7SGerrit Uitslag     * @param string $hash hash link identifier
17160e59de7SGerrit Uitslag     * @param string $name name for the link
172236e9da2SGerrit Uitslag     * @param bool $returnonly
173236e9da2SGerrit Uitslag     * @return string|void
17460e59de7SGerrit Uitslag     *
17560e59de7SGerrit Uitslag     * @see Doku_Renderer_xhtml::locallink
17660e59de7SGerrit Uitslag     */
177852931daSAndreas Gohr    public function locallink($hash, $name = null, $returnonly = false)
178852931daSAndreas Gohr    {
17960e59de7SGerrit Uitslag        global $ID;
18060e59de7SGerrit Uitslag        $name = $this->_getLinkTitle($name, $hash, $isImage);
18160e59de7SGerrit Uitslag        $hash = $this->_headerToLink($hash);
18260e59de7SGerrit Uitslag        $title = $ID . ' ↵';
18360e59de7SGerrit Uitslag
18460e59de7SGerrit Uitslag        $check = false;
18560e59de7SGerrit Uitslag        $pid = sectionID($ID, $check);
18660e59de7SGerrit Uitslag
18760e59de7SGerrit Uitslag        $this->doc .= '<a href="#' . $pid . '__' . $hash . '" title="' . $title . '" class="wikilink1">';
18860e59de7SGerrit Uitslag        $this->doc .= $name;
18960e59de7SGerrit Uitslag        $this->doc .= '</a>';
19060e59de7SGerrit Uitslag    }
19160e59de7SGerrit Uitslag
19260e59de7SGerrit Uitslag    /**
193aab792a5SAndreas Gohr     * Wrap centered media in a div to center it
194236e9da2SGerrit Uitslag     *
195236e9da2SGerrit Uitslag     * @param string $src media ID
196236e9da2SGerrit Uitslag     * @param string $title descriptive text
197236e9da2SGerrit Uitslag     * @param string $align left|center|right
198236e9da2SGerrit Uitslag     * @param int $width width of media in pixel
199236e9da2SGerrit Uitslag     * @param int $height height of media in pixel
200236e9da2SGerrit Uitslag     * @param string $cache cache|recache|nocache
201236e9da2SGerrit Uitslag     * @param bool $render should the media be embedded inline or just linked
202236e9da2SGerrit Uitslag     * @return string
203aab792a5SAndreas Gohr     */
204852931daSAndreas Gohr    public function _media(
205852931daSAndreas Gohr        $src,
206852931daSAndreas Gohr        $title = null,
207852931daSAndreas Gohr        $align = null,
208852931daSAndreas Gohr        $width = null,
209852931daSAndreas Gohr        $height = null,
210852931daSAndreas Gohr        $cache = null,
211852931daSAndreas Gohr        $render = true
212852931daSAndreas Gohr    ) {
213aab792a5SAndreas Gohr
214aab792a5SAndreas Gohr        $out = '';
215aab792a5SAndreas Gohr        if ($align == 'center') {
216aab792a5SAndreas Gohr            $out .= '<div align="center" style="text-align: center">';
217aab792a5SAndreas Gohr        }
218aab792a5SAndreas Gohr
219aab792a5SAndreas Gohr        $out .= parent::_media($src, $title, $align, $width, $height, $cache, $render);
220aab792a5SAndreas Gohr
221aab792a5SAndreas Gohr        if ($align == 'center') {
222aab792a5SAndreas Gohr            $out .= '</div>';
223aab792a5SAndreas Gohr        }
224aab792a5SAndreas Gohr
225aab792a5SAndreas Gohr        return $out;
226aab792a5SAndreas Gohr    }
227aab792a5SAndreas Gohr
228551dd41eSAndreas Gohr    /**
229551dd41eSAndreas Gohr     * hover info makes no sense in PDFs, so drop acronyms
230236e9da2SGerrit Uitslag     *
231236e9da2SGerrit Uitslag     * @param string $acronym
232551dd41eSAndreas Gohr     */
233852931daSAndreas Gohr    public function acronym($acronym)
234852931daSAndreas Gohr    {
235551dd41eSAndreas Gohr        $this->doc .= $this->_xmlEntities($acronym);
236551dd41eSAndreas Gohr    }
237551dd41eSAndreas Gohr
2389eb4c81fSAndreas Gohr    /**
2399eb4c81fSAndreas Gohr     * reformat links if needed
240236e9da2SGerrit Uitslag     *
241236e9da2SGerrit Uitslag     * @param array $link
242236e9da2SGerrit Uitslag     * @return string
2439eb4c81fSAndreas Gohr     */
244852931daSAndreas Gohr    public function _formatLink($link)
245852931daSAndreas Gohr    {
24660e59de7SGerrit Uitslag
24760e59de7SGerrit Uitslag        // for internal links contains the title the pageid
24860e59de7SGerrit Uitslag        if (in_array($link['title'], $this->actioninstance->getExportedPages())) {
249852931daSAndreas Gohr            [/* url */, $hash] = sexplode('#', $link['url'], 2, '');
25060e59de7SGerrit Uitslag
25160e59de7SGerrit Uitslag            $check = false;
25260e59de7SGerrit Uitslag            $pid = sectionID($link['title'], $check);
25360e59de7SGerrit Uitslag            $link['url'] = "#" . $pid . '__' . $hash;
25460e59de7SGerrit Uitslag        }
25560e59de7SGerrit Uitslag
2569eb4c81fSAndreas Gohr        // prefix interwiki links with interwiki icon
2579eb4c81fSAndreas Gohr        if ($link['name'][0] != '<' && preg_match('/\binterwiki iw_(.\w+)\b/', $link['class'], $m)) {
2589eb4c81fSAndreas Gohr            if (file_exists(DOKU_INC . 'lib/images/interwiki/' . $m[1] . '.png')) {
2599eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki/' . $m[1] . '.png';
2609eb4c81fSAndreas Gohr            } elseif (file_exists(DOKU_INC . 'lib/images/interwiki/' . $m[1] . '.gif')) {
2619eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki/' . $m[1] . '.gif';
2629eb4c81fSAndreas Gohr            } else {
2639eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki.png';
2649eb4c81fSAndreas Gohr            }
2659eb4c81fSAndreas Gohr
266852931daSAndreas Gohr            $link['name'] = sprintf(
267852931daSAndreas Gohr                '<img src="%s" width="16" height="16" style="vertical-align: middle" class="%s" />%s',
268852931daSAndreas Gohr                $img,
269852931daSAndreas Gohr                $link['class'],
270852931daSAndreas Gohr                $link['name']
271852931daSAndreas Gohr            );
2729eb4c81fSAndreas Gohr        }
2739eb4c81fSAndreas Gohr        return parent::_formatLink($link);
2749eb4c81fSAndreas Gohr    }
275ccdd3126SAndreas Gohr
276ccdd3126SAndreas Gohr    /**
277ccdd3126SAndreas Gohr     * no obfuscation for email addresses
278236e9da2SGerrit Uitslag     *
279236e9da2SGerrit Uitslag     * @param string $address
280236e9da2SGerrit Uitslag     * @param null $name
281236e9da2SGerrit Uitslag     * @param bool $returnonly
282236e9da2SGerrit Uitslag     * @return string|void
283ccdd3126SAndreas Gohr     */
284852931daSAndreas Gohr    public function emaillink($address, $name = null, $returnonly = false)
285852931daSAndreas Gohr    {
286ccdd3126SAndreas Gohr        global $conf;
287ccdd3126SAndreas Gohr        $old = $conf['mailguard'];
288ccdd3126SAndreas Gohr        $conf['mailguard'] = 'none';
2899e1a2ac6SAnael Mobilia        parent::emaillink($address, $name, $returnonly);
290ccdd3126SAndreas Gohr        $conf['mailguard'] = $old;
291ccdd3126SAndreas Gohr    }
292a876b55bSAndreas Gohr}
293