xref: /plugin/struct/action/inline.php (revision 4731b875bb4fd88700d786e5fdd24b8d7bd56276)
1<?php
2/**
3 * DokuWiki Plugin struct (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10use dokuwiki\plugin\struct\meta\Column;
11use dokuwiki\plugin\struct\meta\SchemaData;
12use dokuwiki\plugin\struct\meta\StructException;
13use dokuwiki\plugin\struct\meta\Title;
14use dokuwiki\plugin\struct\meta\Validator;
15
16if(!defined('DOKU_INC')) die();
17
18/**
19 * Class action_plugin_struct_inline
20 *
21 * Handle inline editing
22 */
23class action_plugin_struct_inline extends DokuWiki_Action_Plugin {
24
25    /** @var  SchemaData */
26    protected $schemadata = null;
27
28    /** @var  Column */
29    protected $column = null;
30
31    /** @var String */
32    protected $pid = '';
33
34    /**
35     * Registers a callback function for a given event
36     *
37     * @param Doku_Event_Handler $controller DokuWiki's event controller object
38     * @return void
39     */
40    public function register(Doku_Event_Handler $controller) {
41        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax');
42    }
43
44    /**
45     * @param Doku_Event $event
46     * @param $param
47     */
48    public function handle_ajax(Doku_Event $event, $param) {
49        $len = strlen('plugin_struct_inline_');
50        if(substr($event->data, 0,  $len) != 'plugin_struct_inline_') return;
51        $event->preventDefault();
52        $event->stopPropagation();
53
54        if(substr($event->data,$len) == 'editor') {
55            $this->inline_editor();
56        }
57
58        if(substr($event->data,$len) == 'save') {
59            try {
60                $this->inline_save();
61            } catch(StructException $e) {
62                http_status(500);
63                header('Content-Type: text/plain; charset=utf-8');
64                echo $e->getMessage();
65            }
66        }
67    }
68
69
70    protected function inline_editor() {
71        if(!$this->initFromInput()) return;
72
73
74        // FIXME check read permission
75
76        // FIXME lock page
77
78        $value = $this->schemadata->getDataColumn($this->column);
79        echo '<div>';
80        echo $value->getValueEditor('entry');
81        echo '</div>';
82
83        $hint = $this->column->getType()->getTranslatedHint();
84        if($hint) {
85            echo '<div class="hint">';
86            echo hsc($hint);
87            echo '</div>';
88        }
89    }
90
91    protected function inline_save() {
92        global $INPUT;
93
94        if(!$this->initFromInput()) {
95            throw new StructException('inline save error');
96        }
97
98        // FIXME
99
100        // FIXME handle CSRF protection
101        // FIXME check write permission
102        // FIXME make sure page still locked
103
104        // validate
105        $value = $INPUT->param('entry');
106        $validator = new Validator();
107        if(!$validator->validateValue($this->column, $value)) {
108            throw new StructException(join("\n", $validator->getErrors()));
109        }
110
111        // current data
112        $tosave = $this->schemadata->getDataArray();
113        $tosave[$this->column->getLabel()] = $value;
114        $tosave = array($this->schemadata->getTable() => $tosave);
115
116        // save
117        /** @var helper_plugin_struct $helper */
118        $helper = plugin_load('helper', 'struct');
119        $helper->saveData($this->pid, $tosave, 'inline edit');
120
121
122        // reinit then render
123        $this->initFromInput();
124        $value = $this->schemadata->getDataColumn($this->column);
125        $R = new Doku_Renderer_xhtml();
126        $value->render($R, 'xhtml'); // FIXME use configured default renderer
127
128        echo $R->doc;
129    }
130
131    /**
132     * Initialize internal state based on input variables
133     *
134     * @return bool if initialization was successfull
135     */
136    protected function initFromInput() {
137        global $INPUT;
138
139        $this->schemadata = null;
140        $this->column = null;
141
142        $pid = $INPUT->str('pid');
143        list($table, $field) = explode('.', $INPUT->str('field'));
144        if(blank($pid)) return false;
145        if(blank($table)) return false;
146        if(blank($field)) return false;
147
148        $this->pid = $pid;
149
150        $this->schemadata = new SchemaData($table, $pid, 0);
151        if(!$this->schemadata->getId()) {
152            $this->schemadata = null;
153            return false;
154        }
155
156
157        $this->column = $this->schemadata->findColumn($field);
158        if(!$this->column || !$this->column->isVisibleInEditor()) {
159            $this->schemadata = null;
160            $this->column = null;
161            return false;
162        }
163
164        return true;
165    }
166
167}
168