xref: /plugin/tagging/action/main.php (revision df43a7be9125b55733c41a4f1a13770bf4033169)
14a5f6748SAnna Dabrowska<?php
24a5f6748SAnna Dabrowska
3*df43a7beSAndreas Gohruse dokuwiki\Extension\ActionPlugin;
4*df43a7beSAndreas Gohruse dokuwiki\Extension\Event;
5*df43a7beSAndreas Gohruse dokuwiki\Extension\EventHandler;
6*df43a7beSAndreas Gohr
74a5f6748SAnna Dabrowska/**
84a5f6748SAnna Dabrowska * Class action_plugin_tagging_main
94a5f6748SAnna Dabrowska */
10*df43a7beSAndreas Gohrclass action_plugin_tagging_main extends ActionPlugin
11*df43a7beSAndreas Gohr{
124a5f6748SAnna Dabrowska    /**
134a5f6748SAnna Dabrowska     * Register handlers
144a5f6748SAnna Dabrowska     *
15*df43a7beSAndreas Gohr     * @param EventHandler $controller
164a5f6748SAnna Dabrowska     */
17*df43a7beSAndreas Gohr    public function register(EventHandler $controller)
18*df43a7beSAndreas Gohr    {
194a5f6748SAnna Dabrowska        $controller->register_hook(
20*df43a7beSAndreas Gohr            'AJAX_CALL_UNKNOWN',
21*df43a7beSAndreas Gohr            'BEFORE',
22*df43a7beSAndreas Gohr            $this,
234a5f6748SAnna Dabrowska            'handle_ajax_call_unknown'
244a5f6748SAnna Dabrowska        );
254a5f6748SAnna Dabrowska
264a5f6748SAnna Dabrowska        $controller->register_hook(
27*df43a7beSAndreas Gohr            'ACTION_ACT_PREPROCESS',
28*df43a7beSAndreas Gohr            'BEFORE',
29*df43a7beSAndreas Gohr            $this,
304a5f6748SAnna Dabrowska            'handle_jump'
314a5f6748SAnna Dabrowska        );
324a5f6748SAnna Dabrowska
334a5f6748SAnna Dabrowska        $controller->register_hook(
34*df43a7beSAndreas Gohr            'DOKUWIKI_STARTED',
35*df43a7beSAndreas Gohr            'AFTER',
36*df43a7beSAndreas Gohr            $this,
374a5f6748SAnna Dabrowska            'js_add_security_token'
384a5f6748SAnna Dabrowska        );
394a5f6748SAnna Dabrowska
404a5f6748SAnna Dabrowska        $controller->register_hook(
41*df43a7beSAndreas Gohr            'PLUGIN_MOVE_PAGE_RENAME',
42*df43a7beSAndreas Gohr            'AFTER',
43*df43a7beSAndreas Gohr            $this,
444a5f6748SAnna Dabrowska            'update_moved_page'
454a5f6748SAnna Dabrowska        );
464a5f6748SAnna Dabrowska    }
474a5f6748SAnna Dabrowska
484a5f6748SAnna Dabrowska    /**
494a5f6748SAnna Dabrowska     * Add sectok to JavaScript to secure ajax requests
504a5f6748SAnna Dabrowska     *
51*df43a7beSAndreas Gohr     * @param Event $event
524a5f6748SAnna Dabrowska     * @param            $param
534a5f6748SAnna Dabrowska     */
54*df43a7beSAndreas Gohr    public function js_add_security_token(Event $event, $param)
55*df43a7beSAndreas Gohr    {
564a5f6748SAnna Dabrowska        global $JSINFO;
574a5f6748SAnna Dabrowska        $JSINFO['sectok'] = getSecurityToken();
584a5f6748SAnna Dabrowska    }
594a5f6748SAnna Dabrowska
604a5f6748SAnna Dabrowska    /**
614a5f6748SAnna Dabrowska     * Handle our AJAX requests
624a5f6748SAnna Dabrowska     *
63*df43a7beSAndreas Gohr     * @param Event $event
644a5f6748SAnna Dabrowska     * @param            $param
654a5f6748SAnna Dabrowska     */
66*df43a7beSAndreas Gohr    public function handle_ajax_call_unknown(Event $event, $param)
67*df43a7beSAndreas Gohr    {
684a5f6748SAnna Dabrowska        $handled = true;
694a5f6748SAnna Dabrowska
704a5f6748SAnna Dabrowska        if ($event->data == 'plugin_tagging_save') {
714a5f6748SAnna Dabrowska            $this->save();
724a5f6748SAnna Dabrowska        } elseif ($event->data == 'plugin_tagging_autocomplete') {
734a5f6748SAnna Dabrowska            $this->autocomplete();
744a5f6748SAnna Dabrowska        } elseif ($event->data === 'plugin_tagging_admin_change') {
754a5f6748SAnna Dabrowska            $this->admin_change();
764a5f6748SAnna Dabrowska        } elseif ($event->data === 'plugin_tagging_html_pages') {
774a5f6748SAnna Dabrowska            $this->getPagesHtml();
784a5f6748SAnna Dabrowska        } elseif ($event->data === 'plugin_tagging_delete') {
794a5f6748SAnna Dabrowska            $this->deleteTag();
804a5f6748SAnna Dabrowska        } elseif ($event->data === 'plugin_tagging_rename') {
814a5f6748SAnna Dabrowska            $this->renameTag();
824a5f6748SAnna Dabrowska        } else {
834a5f6748SAnna Dabrowska            $handled = false;
844a5f6748SAnna Dabrowska        }
854a5f6748SAnna Dabrowska        if (!$handled) {
864a5f6748SAnna Dabrowska            return;
874a5f6748SAnna Dabrowska        }
884a5f6748SAnna Dabrowska
894a5f6748SAnna Dabrowska        $event->preventDefault();
904a5f6748SAnna Dabrowska        $event->stopPropagation();
914a5f6748SAnna Dabrowska    }
924a5f6748SAnna Dabrowska
934a5f6748SAnna Dabrowska    /**
944a5f6748SAnna Dabrowska     * Jump to a tag
954a5f6748SAnna Dabrowska     *
96*df43a7beSAndreas Gohr     * @param Event $event
974a5f6748SAnna Dabrowska     * @param            $param
984a5f6748SAnna Dabrowska     */
99*df43a7beSAndreas Gohr    public function handle_jump(Event &$event, $param)
100*df43a7beSAndreas Gohr    {
1014a5f6748SAnna Dabrowska        if (act_clean($event->data) != 'tagjmp') {
1024a5f6748SAnna Dabrowska            return;
1034a5f6748SAnna Dabrowska        }
1044a5f6748SAnna Dabrowska
1054a5f6748SAnna Dabrowska        $event->preventDefault();
1064a5f6748SAnna Dabrowska        $event->stopPropagation();
107*df43a7beSAndreas Gohr
1084a5f6748SAnna Dabrowska        $event->data = 'show';
1094a5f6748SAnna Dabrowska
1104a5f6748SAnna Dabrowska        global $INPUT;
1114a5f6748SAnna Dabrowska        $tags = $INPUT->arr('tag', (array)$INPUT->str('tag'));
1124a5f6748SAnna Dabrowska        $lang = $INPUT->str('lang');
1134a5f6748SAnna Dabrowska
1144a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
1154a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
1164a5f6748SAnna Dabrowska
1174a5f6748SAnna Dabrowska        foreach ($tags as $tag) {
118*df43a7beSAndreas Gohr            $filter = ['tag' => $tag];
1194a5f6748SAnna Dabrowska            if ($lang) {
1204a5f6748SAnna Dabrowska                $filter['lang'] = $lang;
1214a5f6748SAnna Dabrowska            }
1224a5f6748SAnna Dabrowska            $pages = $hlp->findItems($filter, 'pid', 1);
1234a5f6748SAnna Dabrowska            if (!count($pages)) {
1244a5f6748SAnna Dabrowska                continue;
1254a5f6748SAnna Dabrowska            }
1264a5f6748SAnna Dabrowska
1274a5f6748SAnna Dabrowska            $pages = array_keys($pages);
1284a5f6748SAnna Dabrowska            $id = array_pop($pages);
1294a5f6748SAnna Dabrowska            send_redirect(wl($id, '', true, '&'));
1304a5f6748SAnna Dabrowska        }
1314a5f6748SAnna Dabrowska
1324a5f6748SAnna Dabrowska        $tags = array_map('hsc', $tags);
133*df43a7beSAndreas Gohr        msg(sprintf($this->getLang('tagjmp_error'), implode(', ', $tags)), -1);
1344a5f6748SAnna Dabrowska    }
1354a5f6748SAnna Dabrowska
1364a5f6748SAnna Dabrowska    /**
1374a5f6748SAnna Dabrowska     * Save new/changed tags
1384a5f6748SAnna Dabrowska     */
139*df43a7beSAndreas Gohr    public function save()
140*df43a7beSAndreas Gohr    {
1414a5f6748SAnna Dabrowska        global $INPUT;
1424a5f6748SAnna Dabrowska        global $INFO;
1434a5f6748SAnna Dabrowska
1444a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
1454a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
1464a5f6748SAnna Dabrowska
1474a5f6748SAnna Dabrowska        $data = $INPUT->arr('tagging');
1484a5f6748SAnna Dabrowska        $id = $data['id'];
1494a5f6748SAnna Dabrowska        $INFO['writable'] = auth_quickaclcheck($id) >= AUTH_EDIT; // we also need this in findItems
1504a5f6748SAnna Dabrowska
1514a5f6748SAnna Dabrowska        if ($INFO['writable'] && $hlp->getUser()) {
1524a5f6748SAnna Dabrowska            $hlp->replaceTags(
153*df43a7beSAndreas Gohr                $id,
154*df43a7beSAndreas Gohr                $hlp->getUser(),
1554a5f6748SAnna Dabrowska                preg_split(
156*df43a7beSAndreas Gohr                    '/(\s*,\s*)|(\s*,?\s*\n\s*)/',
157*df43a7beSAndreas Gohr                    $data['tags'],
158*df43a7beSAndreas Gohr                    -1,
1594a5f6748SAnna Dabrowska                    PREG_SPLIT_NO_EMPTY
1604a5f6748SAnna Dabrowska                )
1614a5f6748SAnna Dabrowska            );
1624a5f6748SAnna Dabrowska            $hlp->updateElasticState($id);
1634a5f6748SAnna Dabrowska        }
1644a5f6748SAnna Dabrowska
165*df43a7beSAndreas Gohr        $tags = $hlp->findItems(['pid' => $id], 'tag');
166*df43a7beSAndreas Gohr        $hlp->html_cloud($tags, 'tag', [$hlp, 'linkToSearch'], false);
1674a5f6748SAnna Dabrowska    }
1684a5f6748SAnna Dabrowska
1694a5f6748SAnna Dabrowska    /**
1704a5f6748SAnna Dabrowska     * Return autocompletion data
1714a5f6748SAnna Dabrowska     */
172*df43a7beSAndreas Gohr    public function autocomplete()
173*df43a7beSAndreas Gohr    {
1744a5f6748SAnna Dabrowska        global $INPUT;
1754a5f6748SAnna Dabrowska
1764a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
1774a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
1784a5f6748SAnna Dabrowska
1794a5f6748SAnna Dabrowska        $search = $INPUT->str('term');
180*df43a7beSAndreas Gohr        $tags = $hlp->findItems(['tag' => '*' . $hlp->getDB()->escape_string($search) . '*'], 'tag');
1814a5f6748SAnna Dabrowska        arsort($tags);
1824a5f6748SAnna Dabrowska        $tags = array_keys($tags);
1834a5f6748SAnna Dabrowska
1844a5f6748SAnna Dabrowska        header('Content-Type: application/json');
1854a5f6748SAnna Dabrowska
1864a5f6748SAnna Dabrowska        echo json_encode(array_combine($tags, $tags));
1874a5f6748SAnna Dabrowska    }
1884a5f6748SAnna Dabrowska
1894a5f6748SAnna Dabrowska    /**
1904a5f6748SAnna Dabrowska     * Allow admins to change all tags (not only their own)
1914a5f6748SAnna Dabrowska     * We change the tag for every user
1924a5f6748SAnna Dabrowska     */
193*df43a7beSAndreas Gohr    public function admin_change()
194*df43a7beSAndreas Gohr    {
1954a5f6748SAnna Dabrowska        global $INPUT;
1964a5f6748SAnna Dabrowska
1974a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
1984a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
1994a5f6748SAnna Dabrowska
2004a5f6748SAnna Dabrowska        header('Content-Type: application/json');
2014a5f6748SAnna Dabrowska
2024a5f6748SAnna Dabrowska        if (!auth_isadmin()) {
203*df43a7beSAndreas Gohr            echo json_encode(['status' => 'error', 'msg' => $this->getLang('no_admin')]);
2044a5f6748SAnna Dabrowska            return;
2054a5f6748SAnna Dabrowska        }
2064a5f6748SAnna Dabrowska
2074a5f6748SAnna Dabrowska        if (!checkSecurityToken()) {
208*df43a7beSAndreas Gohr            echo json_encode(['status' => 'error', 'msg' => 'Security Token did not match. Possible CSRF attack.']);
2094a5f6748SAnna Dabrowska            return;
2104a5f6748SAnna Dabrowska        }
2114a5f6748SAnna Dabrowska
2124a5f6748SAnna Dabrowska        if (!$INPUT->has('id')) {
213*df43a7beSAndreas Gohr            echo json_encode(['status' => 'error', 'msg' => 'No page id given.']);
2144a5f6748SAnna Dabrowska            return;
2154a5f6748SAnna Dabrowska        }
2164a5f6748SAnna Dabrowska        $pid = $INPUT->str('id');
2174a5f6748SAnna Dabrowska
2184a5f6748SAnna Dabrowska        if (!$INPUT->has('oldValue') || !$INPUT->has('newValue')) {
219*df43a7beSAndreas Gohr            echo json_encode(['status' => 'error', 'msg' => 'No proper input. Give "oldValue" and "newValue"']);
2204a5f6748SAnna Dabrowska            return;
2214a5f6748SAnna Dabrowska        }
2224a5f6748SAnna Dabrowska
2234a5f6748SAnna Dabrowska
224*df43a7beSAndreas Gohr        [$err, $msg] = $hlp->modifyPageTag($pid, $INPUT->str('oldValue'), $INPUT->str('newValue'));
2254a5f6748SAnna Dabrowska        if ($err) {
226*df43a7beSAndreas Gohr            echo json_encode(['status' => 'error', 'msg' => $msg]);
2274a5f6748SAnna Dabrowska            return;
2284a5f6748SAnna Dabrowska        }
2294a5f6748SAnna Dabrowska
230*df43a7beSAndreas Gohr        $tags = $hlp->findItems(['pid' => $pid], 'tag');
231*df43a7beSAndreas Gohr        $userTags = $hlp->findItems(['pid' => $pid, 'tagger' => $hlp->getUser()], 'tag');
232*df43a7beSAndreas Gohr        echo json_encode([
2334a5f6748SAnna Dabrowska            'status' => 'ok',
2344a5f6748SAnna Dabrowska            'tags_edit_value' => implode(', ', array_keys($userTags)),
235*df43a7beSAndreas Gohr            'html_cloud' => $hlp->html_cloud($tags, 'tag', [$hlp, 'linkToSearch'], false, true)
236*df43a7beSAndreas Gohr        ]);
2374a5f6748SAnna Dabrowska    }
2384a5f6748SAnna Dabrowska
2394a5f6748SAnna Dabrowska    /**
2404a5f6748SAnna Dabrowska     * Management: delete all occurrences of a tag
2414a5f6748SAnna Dabrowska     */
2424a5f6748SAnna Dabrowska    public function deleteTag()
2434a5f6748SAnna Dabrowska    {
2444a5f6748SAnna Dabrowska        global $INPUT;
2454a5f6748SAnna Dabrowska        $data = $INPUT->arr('tagging');
2464a5f6748SAnna Dabrowska
2474a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
2484a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
2494a5f6748SAnna Dabrowska        $hlp->deleteTags($data['tid']);
2504a5f6748SAnna Dabrowska
2514a5f6748SAnna Dabrowska        // update elasticsearch state for all relevant pages
2524a5f6748SAnna Dabrowska        $pids = $hlp->findItems(['tag' => $data['tid'][0]], 'pid');
2534a5f6748SAnna Dabrowska        if (!empty($pids)) {
2544a5f6748SAnna Dabrowska            foreach (array_keys($pids) as $pid) {
2554a5f6748SAnna Dabrowska                $hlp->updateElasticState($pid);
2564a5f6748SAnna Dabrowska            }
2574a5f6748SAnna Dabrowska        }
2584a5f6748SAnna Dabrowska    }
2594a5f6748SAnna Dabrowska
2604a5f6748SAnna Dabrowska    /**
2614a5f6748SAnna Dabrowska     * Management: rename all occurrences of a tag
2624a5f6748SAnna Dabrowska     */
2634a5f6748SAnna Dabrowska    public function renameTag()
2644a5f6748SAnna Dabrowska    {
2654a5f6748SAnna Dabrowska        global $INPUT;
2664a5f6748SAnna Dabrowska        $data = $INPUT->arr('tagging');
2674a5f6748SAnna Dabrowska
2684a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
2694a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
2704a5f6748SAnna Dabrowska        $hlp->renameTag($data['oldValue'], $data['newValue']);
2714a5f6748SAnna Dabrowska
2724a5f6748SAnna Dabrowska        // update elasticsearch state for all relevant pages
2734a5f6748SAnna Dabrowska        $pids = $hlp->findItems(['tag' => $data['newValue']], 'pid');
2744a5f6748SAnna Dabrowska        if (!empty($pids)) {
2754a5f6748SAnna Dabrowska            foreach (array_keys($pids) as $pid) {
2764a5f6748SAnna Dabrowska                $hlp->updateElasticState($pid);
2774a5f6748SAnna Dabrowska            }
2784a5f6748SAnna Dabrowska        }
2794a5f6748SAnna Dabrowska    }
2804a5f6748SAnna Dabrowska
2814a5f6748SAnna Dabrowska    /**
282*df43a7beSAndreas Gohr     * Tag dialog HTML: print links to all pages with a given tag
2834a5f6748SAnna Dabrowska     */
2844a5f6748SAnna Dabrowska    public function getPagesHtml()
2854a5f6748SAnna Dabrowska    {
2864a5f6748SAnna Dabrowska        global $INPUT;
2874a5f6748SAnna Dabrowska        $data = $INPUT->arr('tagging');
2884a5f6748SAnna Dabrowska
2894a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
2904a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
2914a5f6748SAnna Dabrowska        echo $hlp->getPagesHtml($data['tid']);
2924a5f6748SAnna Dabrowska    }
2934a5f6748SAnna Dabrowska
2944a5f6748SAnna Dabrowska    /**
2954a5f6748SAnna Dabrowska     * Updates tagging database after a page has been moved/renamed by the move plugin
2964a5f6748SAnna Dabrowska     *
297*df43a7beSAndreas Gohr     * @param Event $event
2984a5f6748SAnna Dabrowska     * @param $param
2994a5f6748SAnna Dabrowska     */
300*df43a7beSAndreas Gohr    public function update_moved_page(Event $event, $param)
3014a5f6748SAnna Dabrowska    {
3024a5f6748SAnna Dabrowska        $src = $event->data['src_id'];
3034a5f6748SAnna Dabrowska        $dst = $event->data['dst_id'];
3044a5f6748SAnna Dabrowska
3054a5f6748SAnna Dabrowska        /** @var helper_plugin_tagging $hlp */
3064a5f6748SAnna Dabrowska        $hlp = plugin_load('helper', 'tagging');
3074a5f6748SAnna Dabrowska        $hlp->renamePage($src, $dst);
3084a5f6748SAnna Dabrowska    }
3094a5f6748SAnna Dabrowska}
310