xref: /plugin/struct/action/aggregationeditor.php (revision bbd79bcc843f6bb7f0c0a6106f4c181ff9e7e427)
1<?php
2
3/**
4 * DokuWiki Plugin struct (Action Component)
5 *
6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7 * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
8 */
9
10use dokuwiki\plugin\struct\meta\AccessTable;
11use dokuwiki\plugin\struct\meta\AccessTableGlobal;
12use dokuwiki\plugin\struct\meta\Column;
13use dokuwiki\plugin\struct\meta\AggregationEditorTable;
14use dokuwiki\plugin\struct\meta\Schema;
15use dokuwiki\plugin\struct\meta\SearchConfig;
16use dokuwiki\plugin\struct\meta\StructException;
17use dokuwiki\plugin\struct\meta\Value;
18
19/**
20 * Class action_plugin_struct_lookup
21 *
22 * Handle global and serial data table editing
23 */
24class action_plugin_struct_aggregationeditor extends DokuWiki_Action_Plugin
25{
26
27    /** @var  Column */
28    protected $column = null;
29
30    /** @var string */
31    protected $pid = '';
32
33    /** @var int */
34    protected $rid = 0;
35
36    /**
37     * Registers a callback function for a given event
38     *
39     * @param Doku_Event_Handler $controller DokuWiki's event controller object
40     * @return void
41     */
42    public function register(Doku_Event_Handler $controller)
43    {
44        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax');
45    }
46
47    /**
48     * @param Doku_Event $event
49     * @param $param
50     */
51    public function handleAjax(Doku_Event $event, $param)
52    {
53        $len = strlen('plugin_struct_aggregationeditor_');
54        if (substr($event->data, 0, $len) != 'plugin_struct_aggregationeditor_') {
55            return;
56        }
57        $event->preventDefault();
58        $event->stopPropagation();
59
60        try {
61            if (substr($event->data, $len) == 'new') {
62                $this->newRowEditor();
63            }
64
65            if (substr($event->data, $len) == 'save') {
66                $this->saveRow();
67            }
68
69            if (substr($event->data, $len) == 'delete') {
70                $this->deleteRow();
71            }
72        } catch (StructException $e) {
73            http_status(500);
74            header('Content-Type: text/plain');
75            echo $e->getMessage();
76        }
77    }
78
79    /**
80     * Deletes a row
81     */
82    protected function deleteRow()
83    {
84        global $INPUT;
85        $tablename = $INPUT->str('schema');
86        if (!$tablename) {
87            throw new StructException('No schema given');
88        }
89
90        $this->rid = $INPUT->int('rid');
91        $this->validate();
92
93        action_plugin_struct_inline::checkCSRF();
94
95        $access = $this->getAccess($tablename);
96        if (!$access->getSchema()->isEditable()) {
97            throw new StructException('lookup delete error: no permission for schema');
98        }
99        $access->clearData();
100    }
101
102    /**
103     * Save one new row
104     */
105    protected function saveRow()
106    {
107        global $INPUT;
108        $tablename = $INPUT->str('schema');
109        $data = $INPUT->arr('entry');
110        $this->pid = $INPUT->str('pid');
111        action_plugin_struct_inline::checkCSRF();
112
113        // create a new row based on the original aggregation config
114        $access = $this->getAccess($tablename);
115
116        /** @var helper_plugin_struct $helper */
117        $helper = plugin_load('helper', 'struct');
118        $helper->saveLookupData($access, $data);
119
120        $config = json_decode($INPUT->str('searchconf'), true);
121        // update row id
122        $this->rid = $access->getRid();
123        $config = $this->addTypeFilter($config);
124
125        $editorTable = new AggregationEditorTable(
126            $this->pid,
127            'xhtml',
128            new Doku_Renderer_xhtml(),
129            new SearchConfig($config)
130        );
131
132        echo $editorTable->getFirstRow();
133    }
134
135    /**
136     * Create the Editor for a new row
137     */
138    protected function newRowEditor()
139    {
140        global $INPUT;
141        global $lang;
142        $tablename = $INPUT->str('schema');
143
144        $schema = new Schema($tablename);
145        if (!$schema->isEditable()) {
146            return;
147        } // no permissions, no editor
148
149        echo '<div class="struct_entry_form">';
150        echo '<fieldset>';
151        echo '<legend>' . $this->getLang('lookup new entry') . '</legend>';
152        /** @var action_plugin_struct_edit $edit */
153        $edit = plugin_load('action', 'struct_edit');
154        foreach ($schema->getColumns(false) as $column) {
155            $label = $column->getLabel();
156            $field = new Value($column, '');
157            echo $edit->makeField($field, "entry[$label]");
158        }
159        formSecurityToken(); // csrf protection
160        echo '<input type="hidden" name="call" value="plugin_struct_aggregationeditor_save" />';
161        echo '<input type="hidden" name="schema" value="' . hsc($tablename) . '" />';
162
163        echo '<button type="submit">' . $lang['btn_save'] . '</button>';
164
165        echo '<div class="err"></div>';
166        echo '</fieldset>';
167        echo '</div>';
168    }
169
170    /**
171     * Returns data accessor
172     *
173     * @param string $tablename
174     * @return AccessTableGlobal
175     */
176    protected function getAccess($tablename)
177    {
178        if ($this->pid) {
179            return AccessTable::getSerialAccess($tablename, $this->pid, $this->rid);
180        }
181        return AccessTable::getGlobalAccess($tablename, $this->rid);
182    }
183
184    /**
185     * Adds filter to search config to differentiate data types
186     *
187     * @param array $config
188     * @return array
189     */
190    protected function addTypeFilter($config)
191    {
192        $config['filter'][] = ['%rowid%', '=', $this->rid, 'AND'];
193        if ($this->pid) {
194            $config['filter'][] = ['%pageid%', '=', $this->pid, 'AND'];
195        }
196        return $config;
197    }
198
199    /**
200     * Throws an exception if data is invalid
201     */
202    protected function validate()
203    {
204        if (!$this->rid) {
205            throw new StructException('No row id given');
206        }
207    }
208}
209