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 /** 149 * TODO: replace with CSS styling 150 * https://datacadamia.com/web/css/content#heading_numbering 151 */ 152 $numbering = ""; 153 if ($level == 2) { 154 $numbering = $nodePosition; 155 } 156 if ($level == 3) { 157 $numbering = $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 158 } 159 if ($level == 4) { 160 $numbering = $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 161 } 162 if ($level == 5) { 163 $numbering = $this->nodeParentPosition[$level - 3] . "." . $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition; 164 } 165 if ($numbering <> "") { 166 $textWithLocalization = $numbering . " - " . $text; 167 } else { 168 $textWithLocalization = $text; 169 } 170 171 // Rendering is done by the parent 172 parent::header($textWithLocalization, $level, $pos); 173 174 175 // Add the page detail after the first header 176 if ($level == 1 and $nodePosition == 1) { 177 178 $this->doc .= BreadcrumbHierarchical::render(); 179 180 } 181 182 183 } 184 185 186 function document_end() 187 { 188 189 global $ID; 190 // The id of the page (not of the sidebar) 191 $id = $ID; 192 $isSidebar = FsWikiUtility::isSideBar(); 193 194 195 // Pump the last doc 196 $this->sections[$this->sectionNumber] = array('level' => $this->previousNodeLevel, 'position' => $this->previousNodePosition, 'content' => $this->doc, 'text' => $this->previousSectionTextHeader); 197 198 // Recreate the doc 199 $this->doc = ''; 200 $rollingLineCount = 0; 201 $currentLineCountSinceLastAd = 0; 202 $adsCounter = 0; 203 foreach ($this->sections as $sectionNumber => $section) { 204 205 $sectionContent = $section['content']; 206 207 208 if ($section['level'] == 1 and $section['position'] == 1) { 209 210 if (TocUtility::showToc($this)) { 211 $sectionContent .= TocUtility::renderToc($this); 212 } 213 214 } 215 216 # Split by element line 217 # element p, h, br, tr, li, pre (one line for pre) 218 $sectionLineCount = HtmlUtility::countLines($sectionContent); 219 $currentLineCountSinceLastAd += $sectionLineCount; 220 $rollingLineCount += $sectionLineCount; 221 222 // The content 223 if ($this->getConf('ShowCount') == 1 && $isSidebar == FALSE) { 224 $this->doc .= "<p>Section " . $sectionNumber . ": (" . $sectionLineCount . "|" . $currentLineCountSinceLastAd . "|" . $rollingLineCount . ")</p>"; 225 } 226 $this->doc .= $sectionContent; 227 228 // No ads on private page 229 230 231 $isLastSection = $sectionNumber === count($this->sections) - 1; 232 if (AdsUtility::showAds( 233 $sectionLineCount, 234 $currentLineCountSinceLastAd, 235 $sectionNumber, 236 $adsCounter, 237 $isLastSection 238 )) { 239 240 241 // Counter 242 $adsCounter += 1; 243 $currentLineCountSinceLastAd = 0; 244 245 $attributes = array("name" => AdsUtility::PREFIX_IN_ARTICLE_ADS . $adsCounter); 246 $this->doc .= AdsUtility::render($attributes); 247 248 249 } 250 251 252 } 253 254 parent::document_end(); 255 256 } 257 258 /** 259 * Start a table 260 * 261 * @param int $maxcols maximum number of columns 262 * @param int $numrows NOT IMPLEMENTED 263 * @param int $pos byte position in the original source 264 * @param string|string[] classes - have to be valid, do not pass unfiltered user input 265 */ 266 function table_open($maxcols = null, $numrows = null, $pos = null, $classes = NULL) 267 { 268 // initialize the row counter used for classes 269 $this->_counter['row_counter'] = 0; 270 TableUtility::tableOpen($this, $pos); 271 } 272 273 /** 274 * https://getbootstrap.com/docs/4.4/content/typography/#inline-text-elements 275 */ 276 public 277 function monospace_open() 278 { 279 $this->doc .= '<mark>'; 280 } 281 282 public 283 function monospace_close() 284 { 285 $this->doc .= '</mark>'; 286 } 287 288 289} 290