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