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