xref: /plugin/combo/renderer/renderer.php (revision 007225e5fb2d3f64edaccd3bd447ca26effb9d68)
1*007225e5Sgerardnico<?php
2*007225e5Sgerardnico
3*007225e5Sgerardnicouse ComboStrap\AdsUtility;
4*007225e5Sgerardnicouse ComboStrap\BreadcrumbHierarchical;
5*007225e5Sgerardnicouse ComboStrap\HtmlUtility;
6*007225e5Sgerardnicouse ComboStrap\FsWikiUtility;
7*007225e5Sgerardnicouse ComboStrap\TableUtility;
8*007225e5Sgerardnicouse ComboStrap\TocUtility;
9*007225e5Sgerardnico
10*007225e5Sgerardnico
11*007225e5Sgerardnicorequire_once(__DIR__ . '/../class/FsWikiUtility.php');
12*007225e5Sgerardnicorequire_once(__DIR__ . '/../class/TableUtility.php');
13*007225e5Sgerardnicorequire_once(__DIR__ . '/../class/TocUtility.php');
14*007225e5Sgerardnicorequire_once(__DIR__ . '/../class/AdsUtility.php');
15*007225e5Sgerardnicorequire_once(__DIR__ . '/../class/HtmlUtility.php');
16*007225e5Sgerardnicorequire_once(__DIR__ . '/../class/BreadcrumbHierarchical.php');
17*007225e5Sgerardnico
18*007225e5Sgerardnico/**
19*007225e5Sgerardnico * Class renderer_plugin_combo_renderer
20*007225e5Sgerardnico * The last two parts ie `combo_renderer` is the id for dokuwiki
21*007225e5Sgerardnico * The last part should also be equal to the name
22*007225e5Sgerardnico */
23*007225e5Sgerardnicoclass  renderer_plugin_combo_renderer extends Doku_Renderer_xhtml
24*007225e5Sgerardnico{
25*007225e5Sgerardnico    const COMBO_RENDERER_NAME = 'combo_renderer';
26*007225e5Sgerardnico
27*007225e5Sgerardnico    /**
28*007225e5Sgerardnico     * @var array that hold the position of the parent
29*007225e5Sgerardnico     */
30*007225e5Sgerardnico    protected $nodeParentPosition = [];
31*007225e5Sgerardnico
32*007225e5Sgerardnico    /**
33*007225e5Sgerardnico     * @var array that hold the current position of an header for a level
34*007225e5Sgerardnico     * $headerNum[level]=position
35*007225e5Sgerardnico     */
36*007225e5Sgerardnico    protected $header = [];
37*007225e5Sgerardnico
38*007225e5Sgerardnico    /**
39*007225e5Sgerardnico     * @var array that will contains the whole doc but by section
40*007225e5Sgerardnico     */
41*007225e5Sgerardnico    protected $sections = [];
42*007225e5Sgerardnico
43*007225e5Sgerardnico    /**
44*007225e5Sgerardnico     * @var int the section number
45*007225e5Sgerardnico     */
46*007225e5Sgerardnico    protected $sectionNumber = 0;
47*007225e5Sgerardnico
48*007225e5Sgerardnico    /**
49*007225e5Sgerardnico     * @var string variable that permits to carry the header text of a previous section
50*007225e5Sgerardnico     */
51*007225e5Sgerardnico    protected $previousSectionTextHeader = '';
52*007225e5Sgerardnico
53*007225e5Sgerardnico
54*007225e5Sgerardnico    /**
55*007225e5Sgerardnico     * @var int variable that permits to carry the position of a previous section
56*007225e5Sgerardnico     */
57*007225e5Sgerardnico    protected $previousNodePosition = 0;
58*007225e5Sgerardnico
59*007225e5Sgerardnico    /**
60*007225e5Sgerardnico     * @var int variable that permits to carry the position of a previous section
61*007225e5Sgerardnico     */
62*007225e5Sgerardnico    protected $previousNodeLevel = 0;
63*007225e5Sgerardnico
64*007225e5Sgerardnico    /**
65*007225e5Sgerardnico     * @var int variable that permits to carry the number of words
66*007225e5Sgerardnico     */
67*007225e5Sgerardnico    protected $lineCounter = 0;
68*007225e5Sgerardnico
69*007225e5Sgerardnico
70*007225e5Sgerardnico    function getFormat()
71*007225e5Sgerardnico    {
72*007225e5Sgerardnico        return 'xhtml';
73*007225e5Sgerardnico    }
74*007225e5Sgerardnico
75*007225e5Sgerardnico    /*
76*007225e5Sgerardnico     * Function that enable to list the plugin in the options for config:renderer_xhtml
77*007225e5Sgerardnico     * http://www.dokuwiki.org/config:renderer_xhtml
78*007225e5Sgerardnico     * setting in its Configuration Manager.
79*007225e5Sgerardnico     */
80*007225e5Sgerardnico    public function canRender($format)
81*007225e5Sgerardnico    {
82*007225e5Sgerardnico        return ($format == 'xhtml');
83*007225e5Sgerardnico    }
84*007225e5Sgerardnico
85*007225e5Sgerardnico
86*007225e5Sgerardnico    /**
87*007225e5Sgerardnico     * Render a heading
88*007225e5Sgerardnico     *
89*007225e5Sgerardnico     * The rendering of the heading is done through the parent
90*007225e5Sgerardnico     * The function just:
91*007225e5Sgerardnico     *   - save the rendering between each header in the class variable $this->sections
92*007225e5Sgerardnico     * This variblae is used in the function document_end to recreate the whole doc.
93*007225e5Sgerardnico     *   - add the numbering to the header text
94*007225e5Sgerardnico     *
95*007225e5Sgerardnico     * @param string $text the text to display
96*007225e5Sgerardnico     * @param int $level header level
97*007225e5Sgerardnico     * @param int $pos byte position in the original source
98*007225e5Sgerardnico     */
99*007225e5Sgerardnico    function header($text, $level, $pos)
100*007225e5Sgerardnico    {
101*007225e5Sgerardnico
102*007225e5Sgerardnico
103*007225e5Sgerardnico        // We are going from 2 to 3
104*007225e5Sgerardnico        // The parent is 2
105*007225e5Sgerardnico        if ($level > $this->previousNodeLevel) {
106*007225e5Sgerardnico            $nodePosition = 1;
107*007225e5Sgerardnico            // Keep the position of the parent
108*007225e5Sgerardnico            $this->nodeParentPosition[$this->previousNodeLevel] = $this->previousNodePosition;
109*007225e5Sgerardnico        } elseif
110*007225e5Sgerardnico            // We are going from 3 to 2
111*007225e5Sgerardnico            // The parent is 1
112*007225e5Sgerardnico        ($level < $this->previousNodeLevel
113*007225e5Sgerardnico        ) {
114*007225e5Sgerardnico            $nodePosition = $this->nodeParentPosition[$level] + 1;
115*007225e5Sgerardnico        } else {
116*007225e5Sgerardnico            $nodePosition = $this->previousNodePosition + 1;
117*007225e5Sgerardnico        }
118*007225e5Sgerardnico
119*007225e5Sgerardnico        // Grab the doc from the previous section
120*007225e5Sgerardnico        $this->sections[$this->sectionNumber] = array(
121*007225e5Sgerardnico            'level' => $this->previousNodeLevel,
122*007225e5Sgerardnico            'position' => $this->previousNodePosition,
123*007225e5Sgerardnico            'content' => $this->doc,
124*007225e5Sgerardnico            'text' => $this->previousSectionTextHeader);
125*007225e5Sgerardnico
126*007225e5Sgerardnico        // And reset it
127*007225e5Sgerardnico        $this->doc = '';
128*007225e5Sgerardnico        // Set the looping variable
129*007225e5Sgerardnico        $this->sectionNumber = $this->sectionNumber + 1;
130*007225e5Sgerardnico        $this->previousNodeLevel = $level;
131*007225e5Sgerardnico        $this->previousNodePosition = $nodePosition;
132*007225e5Sgerardnico        $this->previousSectionTextHeader = $text;
133*007225e5Sgerardnico
134*007225e5Sgerardnico        $numbering = "";
135*007225e5Sgerardnico        if ($level == 2) {
136*007225e5Sgerardnico            $numbering = $nodePosition;
137*007225e5Sgerardnico        }
138*007225e5Sgerardnico        if ($level == 3) {
139*007225e5Sgerardnico            $numbering = $this->nodeParentPosition[$level - 1] . "." . $nodePosition;
140*007225e5Sgerardnico        }
141*007225e5Sgerardnico        if ($level == 4) {
142*007225e5Sgerardnico            $numbering = $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition;
143*007225e5Sgerardnico        }
144*007225e5Sgerardnico        if ($level == 5) {
145*007225e5Sgerardnico            $numbering = $this->nodeParentPosition[$level - 3] . "." . $this->nodeParentPosition[$level - 2] . "." . $this->nodeParentPosition[$level - 1] . "." . $nodePosition;
146*007225e5Sgerardnico        }
147*007225e5Sgerardnico        if ($numbering <> "") {
148*007225e5Sgerardnico            $textWithLocalization = $numbering . " - " . $text;
149*007225e5Sgerardnico        } else {
150*007225e5Sgerardnico            $textWithLocalization = $text;
151*007225e5Sgerardnico        }
152*007225e5Sgerardnico
153*007225e5Sgerardnico        // Rendering is done by the parent
154*007225e5Sgerardnico        parent::header($textWithLocalization, $level, $pos);
155*007225e5Sgerardnico
156*007225e5Sgerardnico
157*007225e5Sgerardnico        // Add the page detail after the first header
158*007225e5Sgerardnico        if ($level == 1 and $nodePosition == 1) {
159*007225e5Sgerardnico
160*007225e5Sgerardnico            $this->doc .= BreadcrumbHierarchical::render();
161*007225e5Sgerardnico
162*007225e5Sgerardnico        }
163*007225e5Sgerardnico
164*007225e5Sgerardnico
165*007225e5Sgerardnico    }
166*007225e5Sgerardnico
167*007225e5Sgerardnico
168*007225e5Sgerardnico    function document_end()
169*007225e5Sgerardnico    {
170*007225e5Sgerardnico
171*007225e5Sgerardnico        global $ID;
172*007225e5Sgerardnico        // The id of the page (not of the sidebar)
173*007225e5Sgerardnico        $id = $ID;
174*007225e5Sgerardnico        $isSidebar = FsWikiUtility::isSideBar();
175*007225e5Sgerardnico
176*007225e5Sgerardnico
177*007225e5Sgerardnico        // Pump the last doc
178*007225e5Sgerardnico        $this->sections[$this->sectionNumber] = array('level' => $this->previousNodeLevel, 'position' => $this->previousNodePosition, 'content' => $this->doc, 'text' => $this->previousSectionTextHeader);
179*007225e5Sgerardnico
180*007225e5Sgerardnico        // Recreate the doc
181*007225e5Sgerardnico        $this->doc = '';
182*007225e5Sgerardnico        $rollingLineCount = 0;
183*007225e5Sgerardnico        $currentLineCountSinceLastAd = 0;
184*007225e5Sgerardnico        $adsCounter = 0;
185*007225e5Sgerardnico        foreach ($this->sections as $sectionNumber => $section) {
186*007225e5Sgerardnico
187*007225e5Sgerardnico            $sectionContent = $section['content'];
188*007225e5Sgerardnico
189*007225e5Sgerardnico
190*007225e5Sgerardnico            if ($section['level'] == 1 and $section['position'] == 1) {
191*007225e5Sgerardnico
192*007225e5Sgerardnico                if (TocUtility::showToc($this)) {
193*007225e5Sgerardnico                    $sectionContent .= TocUtility::renderToc($this);
194*007225e5Sgerardnico                }
195*007225e5Sgerardnico
196*007225e5Sgerardnico            }
197*007225e5Sgerardnico
198*007225e5Sgerardnico            # Split by element line
199*007225e5Sgerardnico            # element p, h, br, tr, li, pre (one line for pre)
200*007225e5Sgerardnico            $sectionLineCount = HtmlUtility::countLines($sectionContent);
201*007225e5Sgerardnico            $currentLineCountSinceLastAd += $sectionLineCount;
202*007225e5Sgerardnico            $rollingLineCount += $sectionLineCount;
203*007225e5Sgerardnico
204*007225e5Sgerardnico            // The content
205*007225e5Sgerardnico            if ($this->getConf('ShowCount') == 1 && $isSidebar == FALSE) {
206*007225e5Sgerardnico                $this->doc .= "<p>Section " . $sectionNumber . ": (" . $sectionLineCount . "|" . $currentLineCountSinceLastAd . "|" . $rollingLineCount . ")</p>";
207*007225e5Sgerardnico            }
208*007225e5Sgerardnico            $this->doc .= $sectionContent;
209*007225e5Sgerardnico
210*007225e5Sgerardnico            // No ads on private page
211*007225e5Sgerardnico
212*007225e5Sgerardnico
213*007225e5Sgerardnico            $isLastSection = $sectionNumber === count($this->sections) - 1;
214*007225e5Sgerardnico            if (AdsUtility::showAds(
215*007225e5Sgerardnico                $sectionLineCount,
216*007225e5Sgerardnico                $currentLineCountSinceLastAd,
217*007225e5Sgerardnico                $sectionNumber,
218*007225e5Sgerardnico                $adsCounter,
219*007225e5Sgerardnico                $isLastSection
220*007225e5Sgerardnico            )) {
221*007225e5Sgerardnico
222*007225e5Sgerardnico
223*007225e5Sgerardnico                // Counter
224*007225e5Sgerardnico                $adsCounter += 1;
225*007225e5Sgerardnico                $currentLineCountSinceLastAd = 0;
226*007225e5Sgerardnico
227*007225e5Sgerardnico                $attributes = array("name" => AdsUtility::PREFIX_IN_ARTICLE_ADS . $adsCounter);
228*007225e5Sgerardnico                $this->doc .= AdsUtility::render($attributes);
229*007225e5Sgerardnico
230*007225e5Sgerardnico
231*007225e5Sgerardnico            }
232*007225e5Sgerardnico
233*007225e5Sgerardnico
234*007225e5Sgerardnico        }
235*007225e5Sgerardnico
236*007225e5Sgerardnico        parent::document_end();
237*007225e5Sgerardnico
238*007225e5Sgerardnico    }
239*007225e5Sgerardnico
240*007225e5Sgerardnico    /**
241*007225e5Sgerardnico     * Start a table
242*007225e5Sgerardnico     *
243*007225e5Sgerardnico     * @param int $maxcols maximum number of columns
244*007225e5Sgerardnico     * @param int $numrows NOT IMPLEMENTED
245*007225e5Sgerardnico     * @param int $pos byte position in the original source
246*007225e5Sgerardnico     * @param string|string[]  classes - have to be valid, do not pass unfiltered user input
247*007225e5Sgerardnico     */
248*007225e5Sgerardnico    function table_open($maxcols = null, $numrows = null, $pos = null, $classes = NULL)
249*007225e5Sgerardnico    {
250*007225e5Sgerardnico        // initialize the row counter used for classes
251*007225e5Sgerardnico        $this->_counter['row_counter'] = 0;
252*007225e5Sgerardnico        TableUtility::tableOpen($this, $pos);
253*007225e5Sgerardnico    }
254*007225e5Sgerardnico
255*007225e5Sgerardnico    /**
256*007225e5Sgerardnico     * https://getbootstrap.com/docs/4.4/content/typography/#inline-text-elements
257*007225e5Sgerardnico     */
258*007225e5Sgerardnico    public
259*007225e5Sgerardnico    function monospace_open()
260*007225e5Sgerardnico    {
261*007225e5Sgerardnico        $this->doc .= '<mark>';
262*007225e5Sgerardnico    }
263*007225e5Sgerardnico
264*007225e5Sgerardnico    public
265*007225e5Sgerardnico    function monospace_close()
266*007225e5Sgerardnico    {
267*007225e5Sgerardnico        $this->doc .= '</mark>';
268*007225e5Sgerardnico    }
269*007225e5Sgerardnico
270*007225e5Sgerardnico
271*007225e5Sgerardnico}
272