1<?php 2 3use ComboStrap\AdsUtility; 4use ComboStrap\BreadcrumbHierarchical; 5use ComboStrap\FsWikiUtility; 6use ComboStrap\XhtmlUtility; 7use ComboStrap\PluginUtility; 8use ComboStrap\TableUtility; 9use ComboStrap\TocUtility; 10 11 12require_once(__DIR__ . '/../ComboStrap/FsWikiUtility.php'); 13require_once(__DIR__ . '/../ComboStrap/TableUtility.php'); 14require_once(__DIR__ . '/../ComboStrap/TocUtility.php'); 15require_once(__DIR__ . '/../ComboStrap/AdsUtility.php'); 16require_once(__DIR__ . '/../ComboStrap/XhtmlUtility.php'); 17require_once(__DIR__ . '/../ComboStrap/BreadcrumbHierarchical.php'); 18 19/** 20 * Class renderer_plugin_combo_renderer 21 * The last two parts ie `combo_renderer` is the id for dokuwiki 22 * The last part should also be equal to the name 23 */ 24class renderer_plugin_combo_renderer extends Doku_Renderer_xhtml 25{ 26 const COMBO_RENDERER_NAME = 'combo_renderer'; 27 28 /** 29 * @var array that hold the position of the parent 30 */ 31 protected $nodeParentPosition = []; 32 33 /** 34 * @var array that hold the current position of an header for a level 35 * $headerNum[level]=position 36 */ 37 protected $header = []; 38 39 /** 40 * @var array that will contains the whole doc but by section 41 */ 42 protected $sections = []; 43 44 /** 45 * @var int the section number 46 */ 47 protected $sectionNumber = 0; 48 49 /** 50 * @var string variable that permits to carry the header text of a previous section 51 */ 52 protected $previousSectionTextHeader = ''; 53 54 55 /** 56 * @var int variable that permits to carry the position of a previous section 57 */ 58 protected $previousNodePosition = 0; 59 60 /** 61 * @var int variable that permits to carry the position of a previous section 62 */ 63 protected $previousNodeLevel = 0; 64 65 /** 66 * @var int variable that permits to carry the number of words 67 */ 68 protected $lineCounter = 0; 69 70 71 function getFormat() 72 { 73 return 'xhtml'; 74 } 75 76 /* 77 * Function that enable to list the plugin in the options for config:renderer_xhtml 78 * http://www.dokuwiki.org/config:renderer_xhtml 79 * setting in its Configuration Manager. 80 */ 81 public function canRender($format) 82 { 83 return ($format == 'xhtml'); 84 } 85 86 87 /** 88 * Render a heading 89 * 90 * The rendering of the heading is done through the parent 91 * The function just: 92 * - save the rendering between each header in the class variable $this->sections 93 * This variblae is used in the function document_end to recreate the whole doc. 94 * - add the numbering to the header text 95 * 96 * @param string $text the text to display 97 * @param int $level header level 98 * @param int $pos byte position in the original source 99 */ 100 function header($text, $level, $pos) 101 { 102 103 /** 104 * Save the H1 even if the heading dokuwiki is not enable 105 */ 106 if(!PluginUtility::getConfValue(syntax_plugin_combo_headingwiki::CONF_WIKI_HEADING_ENABLE)){ 107 /** 108 * $ACT == 'show' 109 * Otherwise we may capture the title of the admin page ... 110 */ 111 global $ACT; 112 if ($ACT == 'show') { 113 syntax_plugin_combo_heading::processHeadingMetadataH1($level, $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 150 /** 151 * Rendering is done by the parent 152 * And should be the last one 153 * Because we delete the heading 154 * with {@link syntax_plugin_combo_heading::reduceToFirstOpeningTagAndReturnAttributes()} 155 * in order to be able to add the toc and section 156 * 157 */ 158 parent::header($text, $level, $pos); 159 160 161 162 } 163 164 165 function document_end() 166 { 167 168 global $ID; 169 // The id of the page (not of the sidebar) 170 $id = $ID; 171 $isSidebar = FsWikiUtility::isSideBar(); 172 173 174 // Pump the last doc 175 $this->sections[$this->sectionNumber] = array('level' => $this->previousNodeLevel, 'position' => $this->previousNodePosition, 'content' => $this->doc, 'text' => $this->previousSectionTextHeader); 176 177 // Recreate the doc 178 $this->doc = ''; 179 $rollingLineCount = 0; 180 $currentLineCountSinceLastAd = 0; 181 $adsCounter = 0; 182 foreach ($this->sections as $sectionNumber => $section) { 183 184 $sectionContent = $section['content']; 185 186 187 if ($section['level'] == 1 and $section['position'] == 1) { 188 189 // Add the hierarchical breadcrumb detail after the first header 190 $sectionContent .= BreadcrumbHierarchical::render(); 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 = XhtmlUtility::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