1<?php
2/**
3 * DokuWiki Plugin tablelayout (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Michael Große <dokuwiki@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) {
11    die();
12}
13
14/**
15 * Class action_plugin_tablelayout
16 *
17 * Handles the adjusted tablelayout strings from edittable
18 */
19class action_plugin_tablelayout_action extends DokuWiki_Action_Plugin
20{
21
22    /**
23     * Registers a callback function for a given event
24     *
25     * @param Doku_Event_Handler $controller DokuWiki's event controller object
26     * @return void
27     */
28    public function register(Doku_Event_Handler $controller)
29    {
30        $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'ensurePagesave');
31        $controller->register_hook('PLUGIN_EDITTABLE_PREPROCESS_EDITOR', 'AFTER', $this, 'handleTablePost');
32        $controller->register_hook('HTML_EDITFORM_OUTPUT', 'BEFORE', $this, 'addLayoutField');
33        $controller->register_hook('FORM_EDIT_OUTPUT', 'BEFORE', $this, 'addLayoutField');
34    }
35
36    /**
37     * Adds tablelayout options to hidden fields, and so makes them accessible
38     * to tablelayout form.
39     *
40     * @param Doku_Event $event
41     * @return void
42     */
43    public function addLayoutField(Doku_Event $event)
44    {
45        global $INPUT;
46
47        /** @var Doku_Form||\dokuwiki\Form\Form $form */
48        $form =& $event->data;
49
50        if (is_a($form, \dokuwiki\Form\Form::class) && $INPUT->str('target') === 'table') {
51            $form->setHiddenField('tablelayout',  $INPUT->str('tablelayout'));
52        }
53
54        if (is_a($form, Doku_Form::class) && $event->data->_hidden['target'] !== 'table') {
55            $form->addHidden('tablelayout', $INPUT->str('tablelayout'));
56        }
57    }
58
59    public function handleTablePost(Doku_Event $event, $param)
60    {
61        global $TEXT, $INPUT;
62
63        switch (act_clean($event->data)) {
64            case 'preview':
65                /** @var helper_plugin_tablelayout $helper */
66                $helper = $this->loadHelper('tablelayout');
67                $newSyntax = $helper->buildSyntaxFromJSON($INPUT->str('tablelayout'));
68                if (strlen($newSyntax) > 0) {
69                    $TEXT = $newSyntax . "\n" . $TEXT;
70                }
71                break;
72            case 'save':
73                if ($INPUT->post->has('edittable__new')) {
74                    /** @var helper_plugin_tablelayout $helper */
75                    $helper = $this->loadHelper('tablelayout');
76                    $newSyntax = $helper->buildSyntaxFromJSON($INPUT->str('tablelayout'));
77                    if (strlen($newSyntax) > 0) {
78                        $TEXT = $newSyntax . "\n" . $TEXT;
79                    }
80                };
81                break;
82            case 'edit':
83                if ($INPUT->post->has('edittable__new')) {
84                    $featuresDefaultState = $this->getConf('features_active_by_default') === 1;
85                    // FIXME this duplicates the default layout-data in the javascript
86                    $INPUT->post->set('tablelayout', json_encode(array(
87                            'rowsHeaderSource' => 'Auto',
88                            'tableSearch' => $featuresDefaultState,
89                            'tableSort' => $featuresDefaultState,
90                            'tablePrint' => $featuresDefaultState,
91                        ))
92                    );
93                };
94            default:
95        }
96    }
97
98    /**
99     * Check if page has to be saved because tablelayout has changed
100     *
101     * @param Doku_Event $event
102     * @param $param
103     * @return void
104     */
105    public function ensurePagesave(Doku_Event $event, $param)
106    {
107        if ($event->data['revertFrom'] || empty($event->data['newContent'])) {
108            return;
109        }
110        global $RANGE, $INPUT;
111        if (!$INPUT->has('tablelayout')) {
112            return;
113        }
114        list($start) = explode('-', $RANGE);
115        $start = (int)$start-1; // $RANGE is 1-based
116
117        if (!$this->isTableSave($event->data['newContent'], $start)) {
118            return;
119        }
120        $pretext = explode("\n", rtrim(substr($event->data['newContent'], 0, $start)));
121        $tableAndSuffix = substr($event->data['newContent'],$start);
122
123        $oldSyntax = end($pretext);
124        $newLayoutJSON = $INPUT->str('tablelayout');
125
126        /** @var helper_plugin_tablelayout $helper */
127        $helper = $this->loadHelper('tablelayout');
128        $newSyntax = $helper->buildSyntaxFromJSON($newLayoutJSON);
129
130        if ($oldSyntax !== $newSyntax) {
131            if (strpos($oldSyntax, '{{tablelayout') === 0) {
132                array_pop($pretext);
133            }
134            $pretext[] = $newSyntax;
135            $event->data['newContent'] = implode("\n", $pretext) . "\n" . $tableAndSuffix;
136            $event->data['contentChanged'] = true;
137            return;
138        }
139    }
140
141    /**
142     * Determine if this is saving a table
143     *
144     * @todo: this might be somewhat redundant, since only table-saves should have the tablelayout-key
145     *
146     * @param string $text
147     * @param int $start
148     * @return bool
149     */
150    private function isTableSave($text, $start)
151    {
152        $firstChar = $text[$start];
153        return $firstChar === '^' || $firstChar === '|';
154    }
155}
156
157// vim:ts=4:sw=4:et:
158