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