1<?php 2 3use ComboStrap\AdsUtility; 4use ComboStrap\BreadcrumbHierarchical; 5use ComboStrap\HtmlUtility; 6use ComboStrap\FsWikiUtility; 7use ComboStrap\TableUtility; 8use ComboStrap\TocUtility; 9 10 11require_once(__DIR__ . '/../class/FsWikiUtility.php'); 12require_once(__DIR__ . '/../class/TableUtility.php'); 13require_once(__DIR__ . '/../class/TocUtility.php'); 14require_once(__DIR__ . '/../class/AdsUtility.php'); 15require_once(__DIR__ . '/../class/HtmlUtility.php'); 16require_once(__DIR__ . '/../class/BreadcrumbHierarchical.php'); 17 18/** 19 * Class renderer_plugin_combo_renderer 20 * The last two parts ie `combo_renderer` is the id for dokuwiki 21 * The last part should also be equal to the name 22 */ 23class renderer_plugin_combo_renderer extends Doku_Renderer_xhtml 24{ 25 const COMBO_RENDERER_NAME = 'combo_renderer'; 26 27 /** 28 * @var array that hold the position of the parent 29 */ 30 protected $nodeParentPosition = []; 31 32 /** 33 * @var array that hold the current position of an header for a level 34 * $headerNum[level]=position 35 */ 36 protected $header = []; 37 38 /** 39 * @var array that will contains the whole doc but by section 40 */ 41 protected $sections = []; 42 43 /** 44 * @var int the section number 45 */ 46 protected $sectionNumber = 0; 47 48 /** 49 * @var string variable that permits to carry the header text of a previous section 50 */ 51 protected $previousSectionTextHeader = ''; 52 53 54 /** 55 * @var int variable that permits to carry the position of a previous section 56 */ 57 protected $previousNodePosition = 0; 58 59 /** 60 * @var int variable that permits to carry the position of a previous section 61 */ 62 protected $previousNodeLevel = 0; 63 64 /** 65 * @var int variable that permits to carry the number of words 66 */ 67 protected $lineCounter = 0; 68 69 70 function getFormat() 71 { 72 return 'xhtml'; 73 } 74 75 /* 76 * Function that enable to list the plugin in the options for config:renderer_xhtml 77 * http://www.dokuwiki.org/config:renderer_xhtml 78 * setting in its Configuration Manager. 79 */ 80 public function canRender($format) 81 { 82 return ($format == 'xhtml'); 83 } 84 85 86 /** 87 * Render a heading 88 * 89 * The rendering of the heading is done through the parent 90 * The function just: 91 * - save the rendering between each header in the class variable $this->sections 92 * This variblae is used in the function document_end to recreate the whole doc. 93 * - add the numbering to the header text 94 * 95 * @param string $text the text to display 96 * @param int $level header level 97 * @param int $pos byte position in the original source 98 */ 99 function header($text, $level, $pos) 100 { 101 102 103 // We are going from 2 to 3 104 // The parent is 2 105 if ($level > $this->previousNodeLevel) { 106 $nodePosition = 1; 107 // Keep the position of the parent 108 $this->nodeParentPosition[$this->previousNodeLevel] = $this->previousNodePosition; 109 } elseif 110 // We are going from 3 to 2 111 // The parent is 1 112 ($level < $this->previousNodeLevel 113 ) { 114 $nodePosition = $this->nodeParentPosition[$level] + 1; 115 } else { 116 $nodePosition = $this->previousNodePosition + 1; 117 } 118 119 // Grab the doc from the previous section 120 $this->sections[$this->sectionNumber] = array( 121 'level' => $this->previousNodeLevel, 122 'position' => $this->previousNodePosition, 123 'content' => $this->doc, 124 'text' => $this->previousSectionTextHeader); 125 126 // And reset it 127 $this->doc = ''; 128 // Set the looping variable 129 $this->sectionNumber = $this->sectionNumber + 1; 130 $this->previousNodeLevel = $level; 131 $this->previousNodePosition = $nodePosition; 132 $this->previousSectionTextHeader = $text; 133 134 $numbering = ""; 135 if ($level == 2) { 136 $numbering = $nodePosition; 137 } 138 if ($level == 3) { 139 $numbering = $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 140 } 141 if ($level == 4) { 142 $numbering = $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 143 } 144 if ($level == 5) { 145 $numbering = $this->nodeParentPosition[$level - 3] . "." . $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 146 } 147 if ($numbering <> "") { 148 $textWithLocalization = $numbering . " - " . $text; 149 } else { 150 $textWithLocalization = $text; 151 } 152 153 // Rendering is done by the parent 154 parent::header($textWithLocalization, $level, $pos); 155 156 157 // Add the page detail after the first header 158 if ($level == 1 and $nodePosition == 1) { 159 160 $this->doc .= BreadcrumbHierarchical::render(); 161 162 } 163 164 165 } 166 167 168 function document_end() 169 { 170 171 global $ID; 172 // The id of the page (not of the sidebar) 173 $id = $ID; 174 $isSidebar = FsWikiUtility::isSideBar(); 175 176 177 // Pump the last doc 178 $this->sections[$this->sectionNumber] = array('level' => $this->previousNodeLevel, 'position' => $this->previousNodePosition, 'content' => $this->doc, 'text' => $this->previousSectionTextHeader); 179 180 // Recreate the doc 181 $this->doc = ''; 182 $rollingLineCount = 0; 183 $currentLineCountSinceLastAd = 0; 184 $adsCounter = 0; 185 foreach ($this->sections as $sectionNumber => $section) { 186 187 $sectionContent = $section['content']; 188 189 190 if ($section['level'] == 1 and $section['position'] == 1) { 191 192 if (TocUtility::showToc($this)) { 193 $sectionContent .= TocUtility::renderToc($this); 194 } 195 196 } 197 198 # Split by element line 199 # element p, h, br, tr, li, pre (one line for pre) 200 $sectionLineCount = HtmlUtility::countLines($sectionContent); 201 $currentLineCountSinceLastAd += $sectionLineCount; 202 $rollingLineCount += $sectionLineCount; 203 204 // The content 205 if ($this->getConf('ShowCount') == 1 && $isSidebar == FALSE) { 206 $this->doc .= "<p>Section " . $sectionNumber . ": (" . $sectionLineCount . "|" . $currentLineCountSinceLastAd . "|" . $rollingLineCount . ")</p>"; 207 } 208 $this->doc .= $sectionContent; 209 210 // No ads on private page 211 212 213 $isLastSection = $sectionNumber === count($this->sections) - 1; 214 if (AdsUtility::showAds( 215 $sectionLineCount, 216 $currentLineCountSinceLastAd, 217 $sectionNumber, 218 $adsCounter, 219 $isLastSection 220 )) { 221 222 223 // Counter 224 $adsCounter += 1; 225 $currentLineCountSinceLastAd = 0; 226 227 $attributes = array("name" => AdsUtility::PREFIX_IN_ARTICLE_ADS . $adsCounter); 228 $this->doc .= AdsUtility::render($attributes); 229 230 231 } 232 233 234 } 235 236 parent::document_end(); 237 238 } 239 240 /** 241 * Start a table 242 * 243 * @param int $maxcols maximum number of columns 244 * @param int $numrows NOT IMPLEMENTED 245 * @param int $pos byte position in the original source 246 * @param string|string[] classes - have to be valid, do not pass unfiltered user input 247 */ 248 function table_open($maxcols = null, $numrows = null, $pos = null, $classes = NULL) 249 { 250 // initialize the row counter used for classes 251 $this->_counter['row_counter'] = 0; 252 TableUtility::tableOpen($this, $pos); 253 } 254 255 /** 256 * https://getbootstrap.com/docs/4.4/content/typography/#inline-text-elements 257 */ 258 public 259 function monospace_open() 260 { 261 $this->doc .= '<mark>'; 262 } 263 264 public 265 function monospace_close() 266 { 267 $this->doc .= '</mark>'; 268 } 269 270 271} 272