xref: /template/strap/renderer/renderer.php (revision 21913ab3235d516e2fa19c7e3929b555b3a2bda1)
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