1<?php
2
3use dokuwiki\Extension\ActionPlugin;
4use dokuwiki\Extension\EventHandler;
5use dokuwiki\Extension\Event;
6use dokuwiki\Utf8\PhpString;
7
8/**
9 *
10 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
11 * @author     Andreas Gohr <andi@splitbrain.org>
12 */
13/**
14 * Class action_plugin_data
15 */
16class action_plugin_data extends ActionPlugin
17{
18    /**
19     * will hold the data helper plugin
20     * @var helper_plugin_data
21     */
22    public $dthlp;
23
24    /**
25     * Constructor. Load helper plugin
26     */
27    public function __construct()
28    {
29        $this->dthlp = plugin_load('helper', 'data');
30    }
31
32    /**
33     * Registers a callback function for a given event
34     */
35    public function register(EventHandler $controller)
36    {
37        $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'handle');
38        $controller->register_hook('HTML_SECEDIT_BUTTON', 'BEFORE', $this, 'editButton');
39        $controller->register_hook('HTML_EDIT_FORMSELECTION', 'BEFORE', $this, 'editForm'); // deprecated
40        $controller->register_hook('EDIT_FORM_ADDTEXTAREA', 'BEFORE', $this, 'editForm'); // replacement
41        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleEditPost');
42        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax');
43    }
44
45    /**
46     * Handles the page write event and removes the database info
47     * when the plugin code is no longer in the source
48     *
49     * @param Event $event
50     * @param null $param
51     */
52    public function handle(Event $event, $param)
53    {
54        $data = $event->data;
55        if (strpos($data[0][1], 'dataentry') !== false) return; // plugin seems still to be there
56
57        $sqlite = $this->dthlp->getDB();
58        if (!$sqlite) return;
59        $id = ltrim($data[1] . ':' . $data[2], ':');
60
61        // get page id
62        $pid = (int) $sqlite->queryValue('SELECT pid FROM pages WHERE page = ?', $id);
63        if (!$pid) return; // we have no data for this page
64
65        $sqlite->exec('DELETE FROM data WHERE pid = ?', $pid);
66        $sqlite->exec('DELETE FROM pages WHERE pid = ?', $pid);
67    }
68
69    /**
70     * @param Event $event
71     * @param null $param
72     */
73    public function editButton($event, $param)
74    {
75        if ($event->data['target'] !== 'plugin_data') {
76            return;
77        }
78
79        $event->data['name'] = $this->getLang('dataentry');
80    }
81
82    /**
83     * @param Event $event
84     * @param null $param
85     */
86    public function editForm(Event $event, $param)
87    {
88        global $TEXT;
89        if ($event->data['target'] !== 'plugin_data') {
90            // Not a data edit
91            return;
92        }
93
94        $event->stopPropagation();
95        $event->preventDefault();
96        unset($event->data['intro_locale']);
97        $event->data['media_manager'] = false;
98
99        echo $this->locale_xhtml('edit_intro' . ($this->getConf('edit_content_only') ? '_contentonly' : ''));
100
101        require_once __DIR__ . '/renderer_data_edit.php';
102        $Renderer = new Doku_Renderer_plugin_data_edit();
103        $Renderer->form = $event->data['form'];
104
105        // Loop through the instructions
106        $instructions = p_get_instructions($TEXT);
107        foreach ($instructions as $instruction) {
108            // Execute the callback against the Renderer
109            call_user_func_array([$Renderer, $instruction[0]], $instruction[1]);
110        }
111    }
112
113    /**
114     * @param Event $event
115     */
116    public function handleEditPost(Event $event)
117    {
118        if (!isset($_POST['data_edit'])) {
119            return;
120        }
121        global $TEXT;
122
123        require_once __DIR__ . '/syntax/entry.php';
124        $TEXT = syntax_plugin_data_entry::editToWiki($_POST['data_edit']);
125    }
126
127    /**
128     * @param Event $event
129     */
130    public function handleAjax(Event $event)
131    {
132        if ($event->data !== 'data_page') {
133            return;
134        }
135
136        $event->stopPropagation();
137        $event->preventDefault();
138
139        $type = substr($_REQUEST['aliastype'], 10);
140        $aliases = $this->dthlp->aliases();
141
142        if (!isset($aliases[$type])) {
143            echo 'Unknown type';
144            return;
145        }
146
147        if ($aliases[$type]['type'] !== 'page') {
148            echo 'AutoCompletion is only supported for page types';
149            return;
150        }
151
152        if (substr($aliases[$type]['postfix'], -1, 1) === ':') {
153            // Resolve namespace start page ID
154            global $conf;
155            $aliases[$type]['postfix'] .= $conf['start'];
156        }
157
158        $search = $_REQUEST['search'];
159
160        $c_search = $search;
161        $in_ns = false;
162        if (!$search) {
163            // No search given, so we just want all pages in the prefix
164            $c_search = $aliases[$type]['prefix'];
165            $in_ns = true;
166        }
167        $pages = ft_pageLookup($c_search, $in_ns, false);
168
169        $regexp = '/^';
170        if ($aliases[$type]['prefix'] !== '') {
171            $regexp .= preg_quote($aliases[$type]['prefix'], '/');
172        }
173        $regexp .= '([^:]+)';
174        if ($aliases[$type]['postfix'] !== '') {
175            $regexp .= preg_quote($aliases[$type]['postfix'], '/');
176        }
177        $regexp .= '$/';
178
179        $result = [];
180        foreach ($pages as $page => $title) {
181            $id = [];
182            if (!preg_match($regexp, $page, $id)) {
183                // Does not satisfy the postfix and prefix criteria
184                continue;
185            }
186
187            $id = $id[1];
188
189            if (
190                $search !== '' &&
191                stripos($id, cleanID($search)) === false &&
192                stripos($title, (string) $search) === false
193            ) {
194                // Search string is not in id part or title
195                continue;
196            }
197
198            if ($title === '') {
199                $title = PhpString::ucwords(str_replace('_', ' ', $id));
200            }
201            $result[hsc($id)] = hsc($title);
202        }
203
204        header('Content-Type: application/json');
205        echo json_encode($result);
206    }
207}
208