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