1<?php
2
3/**
4 * DokuWiki Plugin structsection (Syntax Component)
5 *
6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7 * @author  Michael Große <mic.grosse@googlemail.com>
8 */
9
10use dokuwiki\plugin\struct\meta\AccessTable;
11use dokuwiki\plugin\struct\meta\Assignments;
12use dokuwiki\plugin\struct\meta\StructException;
13
14class syntax_plugin_structsection extends \DokuWiki_Syntax_Plugin
15{
16    protected $hasBeenRendered = false;
17
18    private const XHTML_OPEN = '<div id="plugin__structsection_output">';
19    private const XHTML_CLOSE = '</div>';
20
21    /**
22     * @return string Syntax mode type
23     */
24    public function getType()
25    {
26        return 'substition';
27    }
28
29    /**
30     * @return string Paragraph type
31     */
32    public function getPType()
33    {
34        return 'block';
35    }
36
37    /**
38     * @return int Sort order - Low numbers go before high numbers
39     */
40    public function getSort()
41    {
42        return 155;
43    }
44
45    /**
46     * Connect lookup pattern to lexer.
47     *
48     * We do not connect any pattern here, because the call to this plugin is not
49     * triggered from syntax but our action component
50     *
51     * @asee action_plugin_structsection
52     * @param string $mode Parser mode
53     */
54    public function connectTo($mode)
55    {
56    }
57
58    /**
59     * Handle matches of the struct syntax
60     *
61     * @param string $match The match of the syntax
62     * @param int $state The state of the handler
63     * @param int $pos The position in the document
64     * @param \Doku_Handler $handler The handler
65     * @return array Data for the renderer
66     */
67    public function handle($match, $state, $pos, \Doku_Handler $handler)
68    {
69        // this is never called
70        return array();
71    }
72
73    /**
74     * Render schema data
75     *
76     * Currently completely renderer agnostic
77     *
78     * @param string $mode Renderer mode
79     * @param \Doku_Renderer $R The renderer
80     * @param array $handlerData The data from the handler() function
81     * @return bool If rendering was successful.
82     */
83    public function render($mode, \Doku_Renderer $R, $handlerData)
84    {
85        global $ID;
86        global $INFO;
87        global $REV;
88        if ($ID != $INFO['id']) {
89            return true;
90        }
91        if (!$INFO['exists']) {
92            return true;
93        }
94        if ($this->hasBeenRendered) {
95            return true;
96        }
97
98        // do not render the output twice on the same page, e.g. when another page has been included
99        $this->hasBeenRendered = true;
100        try {
101            $assignments = Assignments::getInstance();
102        } catch (StructException $e) {
103            return false;
104        }
105        $tables = $assignments->getPageAssignments($ID);
106        if (!$tables) {
107            return true;
108        }
109
110        $pos = $handlerData['pos'];
111        if ($mode == 'xhtml') {
112            $R->finishSectionEdit($pos - 1);
113            $R->doc .= self::XHTML_OPEN;
114        }
115
116
117        $hasdata = false;
118        foreach ($tables as $table) {
119            try {
120                $schemadata = AccessTable::getPageAccess($table, $ID, $REV);
121            } catch (StructException $ignored) {
122                continue; // no such schema at this revision
123            }
124            $schemadata->optionSkipEmpty(false);
125            $data = $schemadata->getData();
126            if (!count($data)) {
127                continue;
128            }
129            $hasdata = true;
130
131            foreach ($data as $field) {
132                if (!is_a($field->getColumn()->getType(), \dokuwiki\plugin\structsection\types\Section::class)) {
133                    continue;
134                }
135                $lvl = 2;
136                $R->header($field->getColumn()->getTranslatedLabel(), $lvl, $pos);
137                $pos += strlen($field->getColumn()->getTranslatedLabel());
138                $R->section_open($lvl);
139                if ($mode === 'xhtml') {
140                    $structDataAttribute = 'data-struct="' . hsc($field->getColumn()->getFullQualifiedLabel()) . '"';
141                    $R->doc = substr($R->doc, 0, -2) . ' ' . $structDataAttribute . '>' . "\n";
142                }
143                $field->render($R, $mode);
144                $R->section_close();
145            }
146        }
147
148        if ($mode == 'xhtml') {
149            $R->finishSectionEdit($pos);
150            $R->doc .= self::XHTML_CLOSE;
151        }
152
153        // if no data has been output, remove empty wrapper again
154        if ($mode == 'xhtml' && !$hasdata) {
155            $R->doc = substr($R->doc, 0, -1 * strlen(self::XHTML_OPEN . self::XHTML_CLOSE));
156        }
157
158        return true;
159    }
160}
161
162// vim:ts=4:sw=4:et:
163