xref: /plugin/struct/syntax/output.php (revision d6d97f6064c3b0f90310be8341edc9585520ee54)
1257dd7f8SAndreas Gohr<?php
2*d6d97f60SAnna Dabrowska
3257dd7f8SAndreas Gohr/**
4257dd7f8SAndreas Gohr * DokuWiki Plugin struct (Syntax Component)
5257dd7f8SAndreas Gohr *
6257dd7f8SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7257dd7f8SAndreas Gohr * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
8257dd7f8SAndreas Gohr */
9257dd7f8SAndreas Gohr
10257dd7f8SAndreas Gohr// must be run within Dokuwiki
11f411d872SAndreas Gohruse dokuwiki\plugin\struct\meta\AccessTable;
12ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Assignments;
137cbcfbdbSAndreas Gohruse dokuwiki\plugin\struct\meta\StructException;
14257dd7f8SAndreas Gohr
15257dd7f8SAndreas Gohrif (!defined('DOKU_INC')) die();
16257dd7f8SAndreas Gohr
17*d6d97f60SAnna Dabrowskaclass syntax_plugin_struct_output extends DokuWiki_Syntax_Plugin
18*d6d97f60SAnna Dabrowska{
1987050b53SMichael Grosse
2087050b53SMichael Grosse    protected $hasBeenRendered = false;
2187050b53SMichael Grosse
227938ca48SAndreas Gohr    const XHTML_OPEN = '<div id="plugin__struct_output">';
237938ca48SAndreas Gohr    const XHTML_CLOSE = '</div>';
247938ca48SAndreas Gohr
25257dd7f8SAndreas Gohr    /**
26bdefb930SAnna Dabrowska     * Class names of renderers which should NOT render struct data.
27bdefb930SAnna Dabrowska     * All descendants are also blacklisted.
28bdefb930SAnna Dabrowska     */
29bdefb930SAnna Dabrowska    const BLACKLIST_RENDERER = array('Doku_Renderer_metadata');
30bdefb930SAnna Dabrowska
31bdefb930SAnna Dabrowska    /**
32979b16f8SAndreas Gohr     * Regexp to check on which actions the struct data may be rendered
33979b16f8SAndreas Gohr     */
34979b16f8SAndreas Gohr    const WHITELIST_ACTIONS = '/^(show|export_.*)$/';
35979b16f8SAndreas Gohr
36979b16f8SAndreas Gohr    /**
37257dd7f8SAndreas Gohr     * @return string Syntax mode type
38257dd7f8SAndreas Gohr     */
39*d6d97f60SAnna Dabrowska    public function getType()
40*d6d97f60SAnna Dabrowska    {
41257dd7f8SAndreas Gohr        return 'substition';
42257dd7f8SAndreas Gohr    }
43da30fdd3SAndreas Gohr
44257dd7f8SAndreas Gohr    /**
45257dd7f8SAndreas Gohr     * @return string Paragraph type
46257dd7f8SAndreas Gohr     */
47*d6d97f60SAnna Dabrowska    public function getPType()
48*d6d97f60SAnna Dabrowska    {
49257dd7f8SAndreas Gohr        return 'block';
50257dd7f8SAndreas Gohr    }
51da30fdd3SAndreas Gohr
52257dd7f8SAndreas Gohr    /**
53257dd7f8SAndreas Gohr     * @return int Sort order - Low numbers go before high numbers
54257dd7f8SAndreas Gohr     */
55*d6d97f60SAnna Dabrowska    public function getSort()
56*d6d97f60SAnna Dabrowska    {
57257dd7f8SAndreas Gohr        return 155;
58257dd7f8SAndreas Gohr    }
59257dd7f8SAndreas Gohr
60257dd7f8SAndreas Gohr    /**
61257dd7f8SAndreas Gohr     * Connect lookup pattern to lexer.
62257dd7f8SAndreas Gohr     *
6382c064c1SAndreas Gohr     * We do not connect any pattern here, because the call to this plugin is not
6482c064c1SAndreas Gohr     * triggered from syntax but our action component
6582c064c1SAndreas Gohr     *
6682c064c1SAndreas Gohr     * @asee action_plugin_struct_output
67257dd7f8SAndreas Gohr     * @param string $mode Parser mode
68257dd7f8SAndreas Gohr     */
69*d6d97f60SAnna Dabrowska    public function connectTo($mode)
70*d6d97f60SAnna Dabrowska    {
71257dd7f8SAndreas Gohr    }
72257dd7f8SAndreas Gohr
73257dd7f8SAndreas Gohr    /**
74257dd7f8SAndreas Gohr     * Handle matches of the struct syntax
75257dd7f8SAndreas Gohr     *
76257dd7f8SAndreas Gohr     * @param string $match The match of the syntax
77257dd7f8SAndreas Gohr     * @param int $state The state of the handler
78257dd7f8SAndreas Gohr     * @param int $pos The position in the document
79257dd7f8SAndreas Gohr     * @param Doku_Handler $handler The handler
80257dd7f8SAndreas Gohr     * @return array Data for the renderer
81257dd7f8SAndreas Gohr     */
82*d6d97f60SAnna Dabrowska    public function handle($match, $state, $pos, Doku_Handler $handler)
83*d6d97f60SAnna Dabrowska    {
8482c064c1SAndreas Gohr        // this is never called
8582c064c1SAndreas Gohr        return array();
86257dd7f8SAndreas Gohr    }
87257dd7f8SAndreas Gohr
88257dd7f8SAndreas Gohr    /**
8982c064c1SAndreas Gohr     * Render schema data
90257dd7f8SAndreas Gohr     *
91564e138bSAnna Dabrowska     * Currently completely renderer agnostic
9282c064c1SAndreas Gohr     *
9382c064c1SAndreas Gohr     * @param string $mode Renderer mode
94257dd7f8SAndreas Gohr     * @param Doku_Renderer $R The renderer
95257dd7f8SAndreas Gohr     * @param array $data The data from the handler() function
96257dd7f8SAndreas Gohr     * @return bool If rendering was successful.
97257dd7f8SAndreas Gohr     */
98*d6d97f60SAnna Dabrowska    public function render($mode, Doku_Renderer $R, $data)
99*d6d97f60SAnna Dabrowska    {
1000e4a3e7cSMichael Große        global $ACT;
101257dd7f8SAndreas Gohr        global $ID;
10282c064c1SAndreas Gohr        global $INFO;
103257dd7f8SAndreas Gohr        global $REV;
104bdefb930SAnna Dabrowska
105bdefb930SAnna Dabrowska        foreach (self::BLACKLIST_RENDERER as $blacklisted) {
106bdefb930SAnna Dabrowska            if ($R instanceof $blacklisted) {
1070e4a3e7cSMichael Große                return true;
1080e4a3e7cSMichael Große            }
109bdefb930SAnna Dabrowska        }
11082c064c1SAndreas Gohr        if ($ID != $INFO['id']) return true;
1112f1a213bSAndreas Gohr        if (!$INFO['exists']) return true;
11287050b53SMichael Grosse        if ($this->hasBeenRendered) return true;
113979b16f8SAndreas Gohr        if (!preg_match(self::WHITELIST_ACTIONS, act_clean($ACT))) return true;
11487050b53SMichael Grosse
11587050b53SMichael Grosse        // do not render the output twice on the same page, e.g. when another page has been included
11687050b53SMichael Grosse        $this->hasBeenRendered = true;
1177cbcfbdbSAndreas Gohr        try {
118025cb9daSAndreas Gohr            $assignments = Assignments::getInstance();
1197cbcfbdbSAndreas Gohr        } catch (StructException $e) {
1207cbcfbdbSAndreas Gohr            return false;
1217cbcfbdbSAndreas Gohr        }
122257dd7f8SAndreas Gohr        $tables = $assignments->getPageAssignments($ID);
123257dd7f8SAndreas Gohr        if (!$tables) return true;
124257dd7f8SAndreas Gohr
12567b5dd6eSAnna Dabrowska        if ($mode == 'xhtml') $R->doc .= self::XHTML_OPEN;
1265a1eab78SAndreas Gohr
1277938ca48SAndreas Gohr        $hasdata = false;
128257dd7f8SAndreas Gohr        foreach ($tables as $table) {
129a28d6152SAndreas Gohr            try {
130d4897163SAnna Dabrowska                // use the current time if no revision is specified, otherwise we can't access page data
131d4897163SAnna Dabrowska                $ts = $REV ?: time();
13200bff81cSAnna Dabrowska                $schemadata = AccessTable::byTableName($table, $ID, $ts);
133a28d6152SAndreas Gohr            } catch (StructException $ignored) {
134a28d6152SAndreas Gohr                continue; // no such schema at this revision
135a28d6152SAndreas Gohr            }
1360dd23cefSAndreas Gohr            $schemadata->optionSkipEmpty(true);
1370dd23cefSAndreas Gohr            $data = $schemadata->getData();
138da30fdd3SAndreas Gohr            if (!count($data)) continue;
1397938ca48SAndreas Gohr            $hasdata = true;
140257dd7f8SAndreas Gohr
141da30fdd3SAndreas Gohr            $R->table_open();
142da30fdd3SAndreas Gohr
143da30fdd3SAndreas Gohr            $R->tablethead_open();
144da30fdd3SAndreas Gohr            $R->tablerow_open();
145da30fdd3SAndreas Gohr            $R->tableheader_open(2);
146127d6bacSMichael Große            $R->cdata($schemadata->getSchema()->getTranslatedLabel());
147da30fdd3SAndreas Gohr            $R->tableheader_close();
148da30fdd3SAndreas Gohr            $R->tablerow_close();
149ab7b42a5SAnika Henke            $R->tablethead_close();
150da30fdd3SAndreas Gohr
151da30fdd3SAndreas Gohr            $R->tabletbody_open();
152257dd7f8SAndreas Gohr            foreach ($data as $field) {
153257dd7f8SAndreas Gohr                $R->tablerow_open();
154257dd7f8SAndreas Gohr                $R->tableheader_open();
1559e9bee91SAndreas Gohr                $R->cdata($field->getColumn()->getTranslatedLabel());
156257dd7f8SAndreas Gohr                $R->tableheader_close();
157257dd7f8SAndreas Gohr                $R->tablecell_open();
15825852712SAndreas Gohr                if ($mode == 'xhtml') {
15925852712SAndreas Gohr                    $R->doc = substr($R->doc, 0, -1) . ' data-struct="' . hsc($field->getColumn()->getFullQualifiedLabel()) . '">';
16025852712SAndreas Gohr                }
161257dd7f8SAndreas Gohr                $field->render($R, $mode);
162257dd7f8SAndreas Gohr                $R->tablecell_close();
163257dd7f8SAndreas Gohr                $R->tablerow_close();
164257dd7f8SAndreas Gohr            }
165257dd7f8SAndreas Gohr            $R->tabletbody_close();
166257dd7f8SAndreas Gohr            $R->table_close();
167da30fdd3SAndreas Gohr        }
168257dd7f8SAndreas Gohr
16967b5dd6eSAnna Dabrowska        if ($mode == 'xhtml') $R->doc .= self::XHTML_CLOSE;
1707938ca48SAndreas Gohr
1717938ca48SAndreas Gohr        // if no data has been output, remove empty wrapper again
17267b5dd6eSAnna Dabrowska        if ($mode == 'xhtml' && !$hasdata) {
1737938ca48SAndreas Gohr            $R->doc = substr($R->doc, 0, -1 * strlen(self::XHTML_OPEN . self::XHTML_CLOSE));
1747938ca48SAndreas Gohr        }
1755a1eab78SAndreas Gohr
176257dd7f8SAndreas Gohr        return true;
177257dd7f8SAndreas Gohr    }
178257dd7f8SAndreas Gohr}
179257dd7f8SAndreas Gohr
180257dd7f8SAndreas Gohr// vim:ts=4:sw=4:et:
181