xref: /plugin/dw2pdf/renderer.php (revision 852931daed0aa7c73fc4da5d421d2c117decf509)
1a876b55bSAndreas Gohr<?php
2*852931daSAndreas Gohr
3*852931daSAndreas Gohr// phpcs:disable: PSR1.Methods.CamelCapsMethodName.NotCamelCaps
4*852931daSAndreas Gohr// phpcs:disable: PSR2.Methods.MethodDeclaration.Underscore
5*852931daSAndreas Gohr
6a876b55bSAndreas Gohr/**
7a876b55bSAndreas Gohr * DokuWiki Plugin dw2pdf (Renderer Component)
8*852931daSAndreas 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 */
13*852931daSAndreas Gohrclass renderer_plugin_dw2pdf extends Doku_Renderer_xhtml
14*852931daSAndreas 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     */
26*852931daSAndreas Gohr    private $actioninstance;
2760e59de7SGerrit Uitslag
2860e59de7SGerrit Uitslag    /**
2960e59de7SGerrit Uitslag     * load action plugin instance
3060e59de7SGerrit Uitslag     */
31*852931daSAndreas Gohr    public function __construct()
32*852931daSAndreas Gohr    {
3360e59de7SGerrit Uitslag        $this->actioninstance = plugin_load('action', 'dw2pdf');
3460e59de7SGerrit Uitslag    }
3560e59de7SGerrit Uitslag
36*852931daSAndreas Gohr    public function document_start()
37*852931daSAndreas 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
49*852931daSAndreas 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     */
58*852931daSAndreas Gohr    public function canRender($format)
59*852931daSAndreas Gohr    {
60a876b55bSAndreas Gohr        if ($format == 'xhtml') return true;
61a876b55bSAndreas Gohr        return false;
62a876b55bSAndreas Gohr    }
63a876b55bSAndreas Gohr
64a876b55bSAndreas Gohr    /**
65a876b55bSAndreas Gohr     * Simplified header printing with PDF bookmarks
66236e9da2SGerrit Uitslag     *
67236e9da2SGerrit Uitslag     * @param string $text
68bb7717bcSGerrit Uitslag     * @param int $level from 1 (highest) to 6 (lowest)
69236e9da2SGerrit Uitslag     * @param int $pos
70a876b55bSAndreas Gohr     */
71*852931daSAndreas Gohr    public function header($text, $level, $pos, $returnonly = false)
72*852931daSAndreas Gohr    {
73a876b55bSAndreas Gohr        if (!$text) return; //skip empty headlines
7460e59de7SGerrit Uitslag        global $ID;
75a876b55bSAndreas Gohr
76244aaa51SMichael Hamann        $hid = $this->_headerToLink($text, true);
7757a1b6f9SGerrit Uitslag
7857a1b6f9SGerrit Uitslag        //only add items within global configured levels (doesn't check the pdf toc settings)
7957a1b6f9SGerrit Uitslag        $this->toc_additem($hid, $text, $level);
8057a1b6f9SGerrit Uitslag
8160e59de7SGerrit Uitslag        $check = false;
8260e59de7SGerrit Uitslag        $pid = sectionID($ID, $check);
8360e59de7SGerrit Uitslag        $hid = $pid . '__' . $hid;
84244aaa51SMichael Hamann
859c76f78dSVincent GIRARD
869c76f78dSVincent GIRARD        // retrieve numbered headings option
879c76f78dSVincent GIRARD        $isnumberedheadings = $this->actioninstance->getExportConfig('headernumber');
889c76f78dSVincent GIRARD
899c76f78dSVincent GIRARD        $header_prefix = "";
909c76f78dSVincent GIRARD        if ($isnumberedheadings) {
919c76f78dSVincent GIRARD            if ($level > 0) {
92*852931daSAndreas Gohr                if (self::$previous_level > $level) {
93*852931daSAndreas Gohr                    for ($i = $level + 1; $i <= self::$previous_level; $i++) {
94*852931daSAndreas Gohr                        self::$header_count[$i] = 0;
959c76f78dSVincent GIRARD                    }
969c76f78dSVincent GIRARD                }
979c76f78dSVincent GIRARD            }
98*852931daSAndreas Gohr            self::$header_count[$level]++;
999c76f78dSVincent GIRARD
1009c76f78dSVincent GIRARD            // $header_prefix = "";
1019c76f78dSVincent GIRARD            for ($i = 1; $i <= $level; $i++) {
102*852931daSAndreas Gohr                $header_prefix .= self::$header_count[$i] . ".";
1039c76f78dSVincent GIRARD            }
1049c76f78dSVincent GIRARD        }
1059c76f78dSVincent GIRARD
106a876b55bSAndreas Gohr        // add PDF bookmark
1077fa15500SAndreas Gohr        $bookmark = '';
108bb7717bcSGerrit Uitslag        $maxbookmarklevel = $this->actioninstance->getExportConfig('maxbookmarks');
109bb7717bcSGerrit Uitslag        // 0: off, 1-6: show down to this level
110bb7717bcSGerrit Uitslag        if ($maxbookmarklevel && $maxbookmarklevel >= $level) {
111bb7717bcSGerrit Uitslag            $bookmarklevel = $this->calculateBookmarklevel($level);
112*852931daSAndreas Gohr            $bookmark = sprintf(
113*852931daSAndreas Gohr                '<bookmark content="%s %s" level="%d" />',
114*852931daSAndreas Gohr                $header_prefix,
115*852931daSAndreas Gohr                $this->_xmlEntities($text),
116*852931daSAndreas Gohr                $bookmarklevel
117*852931daSAndreas Gohr            );
118a876b55bSAndreas Gohr        }
119a876b55bSAndreas Gohr
120a876b55bSAndreas Gohr        // print header
1217fa15500SAndreas Gohr        $this->doc .= DOKU_LF . "<h$level>$bookmark";
1229c76f78dSVincent GIRARD        $this->doc .= $header_prefix . "<a name=\"$hid\">";
123a876b55bSAndreas Gohr        $this->doc .= $this->_xmlEntities($text);
124244aaa51SMichael Hamann        $this->doc .= "</a>";
125a876b55bSAndreas Gohr        $this->doc .= "</h$level>" . DOKU_LF;
126*852931daSAndreas Gohr        self::$previous_level = $level;
127a876b55bSAndreas Gohr    }
128a876b55bSAndreas Gohr
129aab792a5SAndreas Gohr    /**
130bb7717bcSGerrit Uitslag     * Bookmark levels might increase maximal +1 per level.
131bb7717bcSGerrit Uitslag     * (note: levels start at 1, bookmarklevels at 0)
132bb7717bcSGerrit Uitslag     *
133bb7717bcSGerrit Uitslag     * @param int $level 1 (highest) to 6 (lowest)
134bb7717bcSGerrit Uitslag     * @return int
135bb7717bcSGerrit Uitslag     */
136*852931daSAndreas Gohr    protected function calculateBookmarklevel($level)
137*852931daSAndreas Gohr    {
138bb7717bcSGerrit Uitslag        if ($this->lastHeaderLevel == -1) {
139bb7717bcSGerrit Uitslag            $this->lastHeaderLevel = $level;
140bb7717bcSGerrit Uitslag        }
141bb7717bcSGerrit Uitslag        $step = $level - $this->lastHeaderLevel;
142bb7717bcSGerrit Uitslag        if ($step > 1) {
143*852931daSAndreas Gohr            $this->difference += $step - 1;
144bb7717bcSGerrit Uitslag        }
145bb7717bcSGerrit Uitslag        if ($step < 0) {
146bb7717bcSGerrit Uitslag            $this->difference = min($this->difference, $level - $this->originalHeaderLevel);
147bb7717bcSGerrit Uitslag            $this->difference = max($this->difference, 0);
148bb7717bcSGerrit Uitslag        }
149bb7717bcSGerrit Uitslag
150bb7717bcSGerrit Uitslag        $bookmarklevel = $level - $this->difference;
151bb7717bcSGerrit Uitslag
152bb7717bcSGerrit Uitslag        if ($step > 1) {
153bb7717bcSGerrit Uitslag            $this->originalHeaderLevel = $bookmarklevel;
154bb7717bcSGerrit Uitslag        }
155bb7717bcSGerrit Uitslag
156bb7717bcSGerrit Uitslag        $this->lastHeaderLevel = $level;
157bb7717bcSGerrit Uitslag        return $bookmarklevel - 1; //zero indexed
158bb7717bcSGerrit Uitslag    }
159bb7717bcSGerrit Uitslag
160bb7717bcSGerrit Uitslag    /**
16160e59de7SGerrit Uitslag     * Render a page local link
16260e59de7SGerrit Uitslag     *
163236e9da2SGerrit Uitslag     * // modified copy of parent function
164236e9da2SGerrit Uitslag     *
16560e59de7SGerrit Uitslag     * @param string $hash hash link identifier
16660e59de7SGerrit Uitslag     * @param string $name name for the link
167236e9da2SGerrit Uitslag     * @param bool $returnonly
168236e9da2SGerrit Uitslag     * @return string|void
16960e59de7SGerrit Uitslag     *
17060e59de7SGerrit Uitslag     * @see Doku_Renderer_xhtml::locallink
17160e59de7SGerrit Uitslag     */
172*852931daSAndreas Gohr    public function locallink($hash, $name = null, $returnonly = false)
173*852931daSAndreas Gohr    {
17460e59de7SGerrit Uitslag        global $ID;
17560e59de7SGerrit Uitslag        $name = $this->_getLinkTitle($name, $hash, $isImage);
17660e59de7SGerrit Uitslag        $hash = $this->_headerToLink($hash);
17760e59de7SGerrit Uitslag        $title = $ID . ' ↵';
17860e59de7SGerrit Uitslag
17960e59de7SGerrit Uitslag        $check = false;
18060e59de7SGerrit Uitslag        $pid = sectionID($ID, $check);
18160e59de7SGerrit Uitslag
18260e59de7SGerrit Uitslag        $this->doc .= '<a href="#' . $pid . '__' . $hash . '" title="' . $title . '" class="wikilink1">';
18360e59de7SGerrit Uitslag        $this->doc .= $name;
18460e59de7SGerrit Uitslag        $this->doc .= '</a>';
18560e59de7SGerrit Uitslag    }
18660e59de7SGerrit Uitslag
18760e59de7SGerrit Uitslag    /**
188aab792a5SAndreas Gohr     * Wrap centered media in a div to center it
189236e9da2SGerrit Uitslag     *
190236e9da2SGerrit Uitslag     * @param string $src media ID
191236e9da2SGerrit Uitslag     * @param string $title descriptive text
192236e9da2SGerrit Uitslag     * @param string $align left|center|right
193236e9da2SGerrit Uitslag     * @param int $width width of media in pixel
194236e9da2SGerrit Uitslag     * @param int $height height of media in pixel
195236e9da2SGerrit Uitslag     * @param string $cache cache|recache|nocache
196236e9da2SGerrit Uitslag     * @param bool $render should the media be embedded inline or just linked
197236e9da2SGerrit Uitslag     * @return string
198aab792a5SAndreas Gohr     */
199*852931daSAndreas Gohr    public function _media(
200*852931daSAndreas Gohr        $src,
201*852931daSAndreas Gohr        $title = null,
202*852931daSAndreas Gohr        $align = null,
203*852931daSAndreas Gohr        $width = null,
204*852931daSAndreas Gohr        $height = null,
205*852931daSAndreas Gohr        $cache = null,
206*852931daSAndreas Gohr        $render = true
207*852931daSAndreas Gohr    ) {
208aab792a5SAndreas Gohr
209aab792a5SAndreas Gohr        $out = '';
210aab792a5SAndreas Gohr        if ($align == 'center') {
211aab792a5SAndreas Gohr            $out .= '<div align="center" style="text-align: center">';
212aab792a5SAndreas Gohr        }
213aab792a5SAndreas Gohr
214aab792a5SAndreas Gohr        $out .= parent::_media($src, $title, $align, $width, $height, $cache, $render);
215aab792a5SAndreas Gohr
216aab792a5SAndreas Gohr        if ($align == 'center') {
217aab792a5SAndreas Gohr            $out .= '</div>';
218aab792a5SAndreas Gohr        }
219aab792a5SAndreas Gohr
220aab792a5SAndreas Gohr        return $out;
221aab792a5SAndreas Gohr    }
222aab792a5SAndreas Gohr
223551dd41eSAndreas Gohr    /**
224551dd41eSAndreas Gohr     * hover info makes no sense in PDFs, so drop acronyms
225236e9da2SGerrit Uitslag     *
226236e9da2SGerrit Uitslag     * @param string $acronym
227551dd41eSAndreas Gohr     */
228*852931daSAndreas Gohr    public function acronym($acronym)
229*852931daSAndreas Gohr    {
230551dd41eSAndreas Gohr        $this->doc .= $this->_xmlEntities($acronym);
231551dd41eSAndreas Gohr    }
232551dd41eSAndreas Gohr
2339eb4c81fSAndreas Gohr    /**
2349eb4c81fSAndreas Gohr     * reformat links if needed
235236e9da2SGerrit Uitslag     *
236236e9da2SGerrit Uitslag     * @param array $link
237236e9da2SGerrit Uitslag     * @return string
2389eb4c81fSAndreas Gohr     */
239*852931daSAndreas Gohr    public function _formatLink($link)
240*852931daSAndreas Gohr    {
24160e59de7SGerrit Uitslag
24260e59de7SGerrit Uitslag        // for internal links contains the title the pageid
24360e59de7SGerrit Uitslag        if (in_array($link['title'], $this->actioninstance->getExportedPages())) {
244*852931daSAndreas Gohr            [/* url */, $hash] = sexplode('#', $link['url'], 2, '');
24560e59de7SGerrit Uitslag
24660e59de7SGerrit Uitslag            $check = false;
24760e59de7SGerrit Uitslag            $pid = sectionID($link['title'], $check);
24860e59de7SGerrit Uitslag            $link['url'] = "#" . $pid . '__' . $hash;
24960e59de7SGerrit Uitslag        }
25060e59de7SGerrit Uitslag
2519eb4c81fSAndreas Gohr        // prefix interwiki links with interwiki icon
2529eb4c81fSAndreas Gohr        if ($link['name'][0] != '<' && preg_match('/\binterwiki iw_(.\w+)\b/', $link['class'], $m)) {
2539eb4c81fSAndreas Gohr            if (file_exists(DOKU_INC . 'lib/images/interwiki/' . $m[1] . '.png')) {
2549eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki/' . $m[1] . '.png';
2559eb4c81fSAndreas Gohr            } elseif (file_exists(DOKU_INC . 'lib/images/interwiki/' . $m[1] . '.gif')) {
2569eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki/' . $m[1] . '.gif';
2579eb4c81fSAndreas Gohr            } else {
2589eb4c81fSAndreas Gohr                $img = DOKU_BASE . 'lib/images/interwiki.png';
2599eb4c81fSAndreas Gohr            }
2609eb4c81fSAndreas Gohr
261*852931daSAndreas Gohr            $link['name'] = sprintf(
262*852931daSAndreas Gohr                '<img src="%s" width="16" height="16" style="vertical-align: middle" class="%s" />%s',
263*852931daSAndreas Gohr                $img,
264*852931daSAndreas Gohr                $link['class'],
265*852931daSAndreas Gohr                $link['name']
266*852931daSAndreas Gohr            );
2679eb4c81fSAndreas Gohr        }
2689eb4c81fSAndreas Gohr        return parent::_formatLink($link);
2699eb4c81fSAndreas Gohr    }
270ccdd3126SAndreas Gohr
271ccdd3126SAndreas Gohr    /**
272ccdd3126SAndreas Gohr     * no obfuscation for email addresses
273236e9da2SGerrit Uitslag     *
274236e9da2SGerrit Uitslag     * @param string $address
275236e9da2SGerrit Uitslag     * @param null $name
276236e9da2SGerrit Uitslag     * @param bool $returnonly
277236e9da2SGerrit Uitslag     * @return string|void
278ccdd3126SAndreas Gohr     */
279*852931daSAndreas Gohr    public function emaillink($address, $name = null, $returnonly = false)
280*852931daSAndreas Gohr    {
281ccdd3126SAndreas Gohr        global $conf;
282ccdd3126SAndreas Gohr        $old = $conf['mailguard'];
283ccdd3126SAndreas Gohr        $conf['mailguard'] = 'none';
2849e1a2ac6SAnael Mobilia        parent::emaillink($address, $name, $returnonly);
285ccdd3126SAndreas Gohr        $conf['mailguard'] = $old;
286ccdd3126SAndreas Gohr    }
287a876b55bSAndreas Gohr}
288