xref: /plugin/struct/action/entry.php (revision 8ec87814898d9c0f4ea1082a8bacaa17ac6b1bf7)
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\Assignments;
12use dokuwiki\plugin\struct\meta\AccessDataValidator;
13use dokuwiki\plugin\struct\meta\Value;
14
15/**
16 * Class action_plugin_struct_entry
17 *
18 * Handles the entry process of struct data with type "page"
19 */
20class action_plugin_struct_entry extends DokuWiki_Action_Plugin
21{
22
23    /**
24     * @var string The form name we use to transfer schema data
25     */
26    protected static $VAR = 'struct_schema_data';
27
28    /** @var helper_plugin_sqlite */
29    protected $sqlite;
30
31    /** @var  bool has the data been validated correctly? */
32    protected $validated;
33
34    /** @var  AccessDataValidator[] these schemas are validated and have changed data and need to be saved */
35    protected $tosave;
36
37    /**
38     * Registers a callback function for a given event
39     *
40     * @param Doku_Event_Handler $controller DokuWiki's event controller object
41     * @return void
42     */
43    public function register(Doku_Event_Handler $controller)
44    {
45        // validate data on preview and save;
46        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleValidation');
47        // ensure a page revision is created when struct data changes:
48        $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'handlePagesaveBefore');
49        // save struct data after page has been saved:
50        $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handlePagesaveAfter');
51    }
52
53    /**
54     * Clean up and validate the input data
55     *
56     * @param Doku_Event $event event object by reference
57     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
58     *                           handler was registered]
59     * @return bool
60     */
61    public function handleValidation(Doku_Event $event, $param)
62    {
63        global $ID, $INPUT;
64        $act = act_clean($event->data);
65        if (!in_array($act, array('save', 'preview'))) return false;
66        $this->tosave = array();
67
68        // run the validation for each assignded schema
69        $valid = AccessDataValidator::validateDataForPage($INPUT->arr(self::$VAR), $ID, $errors);
70        if ($valid === false) {
71            $this->validated = false;
72            foreach ($errors as $error) {
73                msg(hsc($error), -1);
74            }
75        } else {
76            $this->validated = true;
77            $this->tosave = $valid;
78        }
79
80        // FIXME we used to set the cleaned data as new input data. this caused #140
81        // could we just not do that, and keep the cleaning to saving only? and fix that bug this way?
82
83        // did validation go through? otherwise abort saving
84        if (!$this->validated && $act == 'save') {
85            $event->data = 'edit';
86        }
87
88        return true;
89    }
90
91    /**
92     * Check if the page has to be changed
93     *
94     * @param Doku_Event $event event object by reference
95     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
96     *                           handler was registered]
97     * @return bool
98     */
99    public function handlePagesaveBefore(Doku_Event $event, $param)
100    {
101        if ($event->data['contentChanged']) return false; // will be saved for page changes
102        global $ACT;
103        if ($ACT == 'revert') return false; // this is handled in revert.php
104
105        if ((is_array($this->tosave) && count($this->tosave)) || isset($GLOBALS['struct_plugin_force_page_save'])) {
106            if (trim($event->data['newContent']) === '') {
107                // this happens when a new page is tried to be created with only struct data
108                msg($this->getLang('emptypage'), -1);
109            } else {
110                $event->data['contentChanged'] = true; // save for data changes
111
112                // add a summary
113                if (empty($event->data['summary'])) {
114                    $event->data['summary'] = $this->getLang('summary');
115                }
116            }
117        }
118
119        return true;
120    }
121
122    /**
123     * Save the data
124     *
125     * When this is called, INPUT data has been validated already.
126     *
127     * @param Doku_Event $event event object by reference
128     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
129     *                           handler was registered]
130     * @return bool
131     */
132    public function handlePagesaveAfter(Doku_Event $event, $param)
133    {
134        global $ACT;
135        if ($ACT == 'revert') return false; // handled in revert
136
137        $assignments = Assignments::getInstance();
138        if ($event->data['changeType'] == DOKU_CHANGE_TYPE_DELETE && empty($GLOBALS['PLUGIN_MOVE_WORKING'])) {
139            // clear all data on delete unless it's a move operation
140            $tables = $assignments->getPageAssignments($event->data['id']);
141            foreach ($tables as $table) {
142                $schemaData = AccessTable::getPageAccess($table, $event->data['id']);
143                if ($schemaData->getSchema()->isEditable()) {
144                    $schemaData->clearData();
145                }
146            }
147        } else {
148            // save the provided data
149            if ($this->tosave) foreach ($this->tosave as $validation) {
150                if ($validation->getAccessTable()->getSchema()->isEditable()) {
151                    $validation->saveData($event->data['newRevision']);
152
153                    // make sure this schema is assigned
154                    $assignments->assignPageSchema(
155                        $event->data['id'],
156                        $validation->getAccessTable()->getSchema()->getTable()
157                    );
158                }
159            }
160        }
161        return true;
162    }
163}
164
165// vim:ts=4:sw=4:et:
166