xref: /plugin/struct/syntax/table.php (revision 67f70d54d911c6c842e298d4a97622e9d01815b3)
1549a0837SAndreas Gohr<?php
261356325SAnna Dabrowska
3549a0837SAndreas Gohr/**
4549a0837SAndreas Gohr * DokuWiki Plugin struct (Syntax Component)
5549a0837SAndreas Gohr *
6549a0837SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7549a0837SAndreas Gohr * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
8549a0837SAndreas Gohr */
9549a0837SAndreas Gohr
107234bfb1Ssplitbrainuse dokuwiki\Extension\SyntaxPlugin;
11d90aa848SAndreas Gohruse dokuwiki\plugin\struct\meta\Aggregation;
12ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\AggregationTable;
13ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\ConfigParser;
14ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\SearchConfig;
15ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\StructException;
1615929be2SAndreas Gohr
177234bfb1Ssplitbrainclass syntax_plugin_struct_table extends SyntaxPlugin
1861356325SAnna Dabrowska{
193f2a8309SAndreas Gohr    /** @var string which class to use for output */
203f2a8309SAndreas Gohr    protected $tableclass = AggregationTable::class;
213f2a8309SAndreas Gohr
22d90aa848SAndreas Gohr    /** @var string Config options that are not allowed for this syntax mode */
23ce44c639SAndreas Gohr    protected $illegalOptions = ['nesting', 'index'];
24d90aa848SAndreas Gohr
25549a0837SAndreas Gohr    /**
26549a0837SAndreas Gohr     * @return string Syntax mode type
27549a0837SAndreas Gohr     */
2861356325SAnna Dabrowska    public function getType()
2961356325SAnna Dabrowska    {
3015929be2SAndreas Gohr        return 'substition';
31549a0837SAndreas Gohr    }
323f2a8309SAndreas Gohr
33549a0837SAndreas Gohr    /**
34549a0837SAndreas Gohr     * @return string Paragraph type
35549a0837SAndreas Gohr     */
3661356325SAnna Dabrowska    public function getPType()
3761356325SAnna Dabrowska    {
3815929be2SAndreas Gohr        return 'block';
39549a0837SAndreas Gohr    }
403f2a8309SAndreas Gohr
41549a0837SAndreas Gohr    /**
42549a0837SAndreas Gohr     * @return int Sort order - Low numbers go before high numbers
43549a0837SAndreas Gohr     */
4461356325SAnna Dabrowska    public function getSort()
4561356325SAnna Dabrowska    {
465511bd5bSAndreas Gohr        return 155;
47549a0837SAndreas Gohr    }
48549a0837SAndreas Gohr
49549a0837SAndreas Gohr    /**
50549a0837SAndreas Gohr     * Connect lookup pattern to lexer.
51549a0837SAndreas Gohr     *
52549a0837SAndreas Gohr     * @param string $mode Parser mode
53549a0837SAndreas Gohr     */
5461356325SAnna Dabrowska    public function connectTo($mode)
5561356325SAnna Dabrowska    {
565511bd5bSAndreas Gohr        $this->Lexer->addSpecialPattern('----+ *struct table *-+\n.*?\n----+', $mode, 'plugin_struct_table');
57549a0837SAndreas Gohr    }
58549a0837SAndreas Gohr
59549a0837SAndreas Gohr    /**
60549a0837SAndreas Gohr     * Handle matches of the struct syntax
61549a0837SAndreas Gohr     *
62549a0837SAndreas Gohr     * @param string $match The match of the syntax
63549a0837SAndreas Gohr     * @param int $state The state of the handler
64549a0837SAndreas Gohr     * @param int $pos The position in the document
65549a0837SAndreas Gohr     * @param Doku_Handler $handler The handler
66549a0837SAndreas Gohr     * @return array Data for the renderer
67549a0837SAndreas Gohr     */
6861356325SAnna Dabrowska    public function handle($match, $state, $pos, Doku_Handler $handler)
6961356325SAnna Dabrowska    {
70bd363da9SAndreas Gohr        global $conf;
71549a0837SAndreas Gohr
725511bd5bSAndreas Gohr        $lines = explode("\n", $match);
735511bd5bSAndreas Gohr        array_shift($lines);
745511bd5bSAndreas Gohr        array_pop($lines);
755511bd5bSAndreas Gohr
765511bd5bSAndreas Gohr        try {
775511bd5bSAndreas Gohr            $parser = new ConfigParser($lines);
780659dc64SMichael Grosse            $config = $parser->getConfig();
79d90aa848SAndreas Gohr            $this->checkForInvalidOptions($config);
800659dc64SMichael Grosse            return $config;
815511bd5bSAndreas Gohr        } catch (StructException $e) {
825511bd5bSAndreas Gohr            msg($e->getMessage(), -1, $e->getLine(), $e->getFile());
83bd363da9SAndreas Gohr            if ($conf['allowdebug']) msg('<pre>' . hsc($e->getTraceAsString()) . '</pre>', -1);
845511bd5bSAndreas Gohr            return null;
855511bd5bSAndreas Gohr        }
86549a0837SAndreas Gohr    }
87549a0837SAndreas Gohr
88549a0837SAndreas Gohr    /**
89549a0837SAndreas Gohr     * Render xhtml output or metadata
90549a0837SAndreas Gohr     *
9134ea6e10SAnna Dabrowska     * @param string $format Renderer mode (supported modes: xhtml)
92549a0837SAndreas Gohr     * @param Doku_Renderer $renderer The renderer
9330bf61e6SAndreas Gohr     * @param array $config The parsed config data from the handler() function
94549a0837SAndreas Gohr     * @return bool If rendering was successful.
95549a0837SAndreas Gohr     */
9630bf61e6SAndreas Gohr    public function render($format, Doku_Renderer $renderer, $config)
9761356325SAnna Dabrowska    {
9806fee43aSMichael Grosse        global $INFO;
99bd363da9SAndreas Gohr        global $conf;
10029877279SMichael Große
10130bf61e6SAndreas Gohr        if (!$config) return false;
10230bf61e6SAndreas Gohr        $config = $this->addTypeFilter($config); // add type specific filters
10330bf61e6SAndreas Gohr
10425ed0c0dSAndreas Gohr        // always use the main page's ID @todo might make sense as utility method somewhere
10525ed0c0dSAndreas Gohr        if ($INFO !== null) {
10625ed0c0dSAndreas Gohr            $mainId = $INFO['id'];
10725ed0c0dSAndreas Gohr        } else {
10825ed0c0dSAndreas Gohr            $mainId = getID();
10925ed0c0dSAndreas Gohr        }
11025ed0c0dSAndreas Gohr
11115929be2SAndreas Gohr        try {
112299ca8ccSAndreas Gohr            $search = $this->getSearchConfig($config);
11334ea6e10SAnna Dabrowska            if ($format === 'struct_csv') {
1146ce83f43SAndreas Gohr                // no pagination in export
1156ce83f43SAndreas Gohr                $search->setLimit(0);
1166ce83f43SAndreas Gohr                $search->setOffset(0);
1176ce83f43SAndreas Gohr            }
1186ce83f43SAndreas Gohr
11925ed0c0dSAndreas Gohr            $table = new $this->tableclass($mainId, $format, $renderer, $search);
1207234bfb1Ssplitbrain            if (!$table instanceof Aggregation) {
121039b05b8SAndreas Gohr                // this may happen with plugins that extend struct
122039b05b8SAndreas Gohr                throw new StructException('Aggregation class does not inherit Aggregation: ' . $this->tableclass);
123039b05b8SAndreas Gohr            }
124039b05b8SAndreas Gohr
12595a8e37dSAnna Dabrowska            $table->startScope();
12695a8e37dSAnna Dabrowska            $table->render(true);
12795a8e37dSAnna Dabrowska            $table->finishScope();
128*67f70d54SAnna Dabrowska
129*67f70d54SAnna Dabrowska            if ($format === 'metadata') {
130*67f70d54SAnna Dabrowska                /** @var Doku_Renderer_metadata $renderer */
131*67f70d54SAnna Dabrowska                $renderer->meta['plugin']['struct']['hasaggregation'] = $search->getCacheFlag();
13216b7d914SAndreas Gohr            }
1335511bd5bSAndreas Gohr        } catch (StructException $e) {
13415929be2SAndreas Gohr            msg($e->getMessage(), -1, $e->getLine(), $e->getFile());
135bd363da9SAndreas Gohr            if ($conf['allowdebug']) msg('<pre>' . hsc($e->getTraceAsString()) . '</pre>', -1);
13615929be2SAndreas Gohr        }
13715929be2SAndreas Gohr
138549a0837SAndreas Gohr        return true;
139549a0837SAndreas Gohr    }
1400ceefd5cSAnna Dabrowska
1410ceefd5cSAnna Dabrowska    /**
142299ca8ccSAndreas Gohr     * Initialize a SearchConfig with the given parsed config
143299ca8ccSAndreas Gohr     *
144299ca8ccSAndreas Gohr     * @param array $config
145299ca8ccSAndreas Gohr     * @return SearchConfig
146299ca8ccSAndreas Gohr     */
147299ca8ccSAndreas Gohr    protected function getSearchConfig($config)
148299ca8ccSAndreas Gohr    {
149299ca8ccSAndreas Gohr        return new SearchConfig($config);
150299ca8ccSAndreas Gohr    }
151299ca8ccSAndreas Gohr
152299ca8ccSAndreas Gohr
153299ca8ccSAndreas Gohr    /**
154c797933dSAnna Dabrowska     * Filter based on primary key columns, applicable in child classes
1550ceefd5cSAnna Dabrowska     *
1560ceefd5cSAnna Dabrowska     * @param array $config
1570ceefd5cSAnna Dabrowska     * @return array
1580ceefd5cSAnna Dabrowska     */
1590ceefd5cSAnna Dabrowska    protected function addTypeFilter($config)
1600ceefd5cSAnna Dabrowska    {
1610ceefd5cSAnna Dabrowska        return $config;
1620ceefd5cSAnna Dabrowska    }
163d90aa848SAndreas Gohr
164d90aa848SAndreas Gohr    /**
165d90aa848SAndreas Gohr     * Checks for options that do not work in this aggregation
166d90aa848SAndreas Gohr     *
167d90aa848SAndreas Gohr     * @param array $config
168d90aa848SAndreas Gohr     */
169d90aa848SAndreas Gohr    protected function checkForInvalidOptions($config)
170d90aa848SAndreas Gohr    {
171d90aa848SAndreas Gohr        foreach ($this->illegalOptions as $illegalOption) {
172d90aa848SAndreas Gohr            if (!empty($config[$illegalOption])) {
173d90aa848SAndreas Gohr                throw new StructException('illegal option', $illegalOption);
174d90aa848SAndreas Gohr            }
175d90aa848SAndreas Gohr        }
176d90aa848SAndreas Gohr    }
177549a0837SAndreas Gohr}
178