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 * Capture the h1 104 */ 105 if ($level == 1) { 106 /** 107 * $ACT == 'show' 108 * Otherwise we get the title of the admin page ... 109 */ 110 global $ACT; 111 if ($ACT == 'show') { 112 global $ID; 113 p_set_metadata($ID, array("h1" => $text)); 114 } 115 } 116 117 // We are going from 2 to 3 118 // The parent is 2 119 if ($level > $this->previousNodeLevel) { 120 $nodePosition = 1; 121 // Keep the position of the parent 122 $this->nodeParentPosition[$this->previousNodeLevel] = $this->previousNodePosition; 123 } elseif 124 // We are going from 3 to 2 125 // The parent is 1 126 ($level < $this->previousNodeLevel 127 ) { 128 $nodePosition = $this->nodeParentPosition[$level] + 1; 129 } else { 130 $nodePosition = $this->previousNodePosition + 1; 131 } 132 133 // Grab the doc from the previous section 134 $this->sections[$this->sectionNumber] = array( 135 'level' => $this->previousNodeLevel, 136 'position' => $this->previousNodePosition, 137 'content' => $this->doc, 138 'text' => $this->previousSectionTextHeader); 139 140 // And reset it 141 $this->doc = ''; 142 // Set the looping variable 143 $this->sectionNumber = $this->sectionNumber + 1; 144 $this->previousNodeLevel = $level; 145 $this->previousNodePosition = $nodePosition; 146 $this->previousSectionTextHeader = $text; 147 148 $numbering = ""; 149 if ($level == 2) { 150 $numbering = $nodePosition; 151 } 152 if ($level == 3) { 153 $numbering = $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 154 } 155 if ($level == 4) { 156 $numbering = $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 157 } 158 if ($level == 5) { 159 $numbering = $this->nodeParentPosition[$level - 3] . "." . $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 160 } 161 if ($numbering <> "") { 162 $textWithLocalization = $numbering . " - " . $text; 163 } else { 164 $textWithLocalization = $text; 165 } 166 167 // Rendering is done by the parent 168 parent::header($textWithLocalization, $level, $pos); 169 170 171 // Add the page detail after the first header 172 if ($level == 1 and $nodePosition == 1) { 173 174 $this->doc .= BreadcrumbHierarchical::render(); 175 176 } 177 178 179 } 180 181 182 function document_end() 183 { 184 185 global $ID; 186 // The id of the page (not of the sidebar) 187 $id = $ID; 188 $isSidebar = FsWikiUtility::isSideBar(); 189 190 191 // Pump the last doc 192 $this->sections[$this->sectionNumber] = array('level' => $this->previousNodeLevel, 'position' => $this->previousNodePosition, 'content' => $this->doc, 'text' => $this->previousSectionTextHeader); 193 194 // Recreate the doc 195 $this->doc = ''; 196 $rollingLineCount = 0; 197 $currentLineCountSinceLastAd = 0; 198 $adsCounter = 0; 199 foreach ($this->sections as $sectionNumber => $section) { 200 201 $sectionContent = $section['content']; 202 203 204 if ($section['level'] == 1 and $section['position'] == 1) { 205 206 if (TocUtility::showToc($this)) { 207 $sectionContent .= TocUtility::renderToc($this); 208 } 209 210 } 211 212 # Split by element line 213 # element p, h, br, tr, li, pre (one line for pre) 214 $sectionLineCount = HtmlUtility::countLines($sectionContent); 215 $currentLineCountSinceLastAd += $sectionLineCount; 216 $rollingLineCount += $sectionLineCount; 217 218 // The content 219 if ($this->getConf('ShowCount') == 1 && $isSidebar == FALSE) { 220 $this->doc .= "<p>Section " . $sectionNumber . ": (" . $sectionLineCount . "|" . $currentLineCountSinceLastAd . "|" . $rollingLineCount . ")</p>"; 221 } 222 $this->doc .= $sectionContent; 223 224 // No ads on private page 225 226 227 $isLastSection = $sectionNumber === count($this->sections) - 1; 228 if (AdsUtility::showAds( 229 $sectionLineCount, 230 $currentLineCountSinceLastAd, 231 $sectionNumber, 232 $adsCounter, 233 $isLastSection 234 )) { 235 236 237 // Counter 238 $adsCounter += 1; 239 $currentLineCountSinceLastAd = 0; 240 241 $attributes = array("name" => AdsUtility::PREFIX_IN_ARTICLE_ADS . $adsCounter); 242 $this->doc .= AdsUtility::render($attributes); 243 244 245 } 246 247 248 } 249 250 parent::document_end(); 251 252 } 253 254 /** 255 * Start a table 256 * 257 * @param int $maxcols maximum number of columns 258 * @param int $numrows NOT IMPLEMENTED 259 * @param int $pos byte position in the original source 260 * @param string|string[] classes - have to be valid, do not pass unfiltered user input 261 */ 262 function table_open($maxcols = null, $numrows = null, $pos = null, $classes = NULL) 263 { 264 // initialize the row counter used for classes 265 $this->_counter['row_counter'] = 0; 266 TableUtility::tableOpen($this, $pos); 267 } 268 269 /** 270 * https://getbootstrap.com/docs/4.4/content/typography/#inline-text-elements 271 */ 272 public 273 function monospace_open() 274 { 275 $this->doc .= '<mark>'; 276 } 277 278 public 279 function monospace_close() 280 { 281 $this->doc .= '</mark>'; 282 } 283 284 285} 286