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