1<?php 2/** 3 * DokuWiki Plugin tagfilter (Action Component) 4 * 5 * inserts a button into the toolbar 6 * 7 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 8 * @author lisps 9 */ 10 11class action_plugin_tagfilter extends DokuWiki_Action_Plugin 12{ 13 /** 14 * Register the eventhandlers 15 */ 16 public function register(Doku_Event_Handler $controller) 17 { 18 $controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'insert_button', array()); 19 $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, '_addparams'); 20 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_ajax_call'); 21 } 22 23 public function _addparams($event, $param) 24 { 25 global $JSINFO; 26 global $INPUT; 27 // filter for ft* in GET 28 $f = function ($value) { 29 return strpos($value, "tf") === 0; 30 }; 31 $get_tagfilter = array_filter(array_keys($_GET), $f); 32 33 //filter for ft<key>_<label> and add it to JSINFO to select it via JavaScript 34 foreach ($get_tagfilter as $param) { 35 $ret = preg_match('/^tf(\d+)\_([\w\:äöü\-\/#]+)/', $param, $matches); 36 37 if ($ret && is_numeric($matches[1]) && $matches[2]) { 38 $JSINFO['tagfilter'][] = [ 39 'key' => $matches[1], 40 'label' => $matches[2], 41 'values' => $INPUT->str($param) ? [$INPUT->str($param)] : $INPUT->arr($param) 42 ]; 43 } 44 } 45 46 } 47 48 /** 49 * Inserts the toolbar button 50 */ 51 public function insert_button($event, $param) 52 { 53 $event->data[] = [ 54 'type' => 'format', 55 'title' => 'Tagfilter plugin', 56 'icon' => '../../plugins/tagfilter/tagfilter.png', 57 'sample' => '<namespace>? <Label>=<TagAusdruck>=<Tags Selected>|... &<pagelistoptions (&multi&nouser&chosen)>', 58 'open' => '{{tagfilter>', 59 'close' => '}}', 60 'insert' => '', 61 ]; 62 } 63 64 /** 65 * ajax Request Handler 66 */ 67 public function _ajax_call($event, $param) 68 { 69 if ($event->data !== 'plugin_tagfilter') { 70 return; 71 } 72 //no other ajax call handlers needed 73 $event->stopPropagation(); 74 $event->preventDefault(); 75 76 global $INPUT; 77 global $lang; 78 79 //Variables 80 $tagfilterFormId = $INPUT->int('id'); 81 $form = $this->getJSONdecodedUrlParameter('form'); 82 $ns = $this->getJSONdecodedUrlParameter('ns'); 83 $flags = (array)$this->getJSONdecodedUrlParameter('flags'); 84 //print_r($flags); 85 $tagfilterFlags = isset($flags[1]) ? (array)$flags[1] : []; //TODO parse? 86 $pagelistFlags = isset($flags[0]) ? (array)$flags[0] : []; 87 //print_r($tagfilterFlags); 88 $pagesearch = $this->getJSONdecodedUrlParameter('pagesearch'); 89 90 //load tagfilter plugin 91 /** @var helper_plugin_tagfilter $Htagfilter */ 92 $Htagfilter = $this->loadHelper('tagfilter', false); 93 94 //load tag plugin 95 /** @var helper_plugin_tag $Htag */ 96 if (is_null($Htag = $this->loadHelper('tag', false))) { 97 $this->sendResponse(sprintf($Htagfilter->getLang('missing_plugin'), 'tag')); 98 return; 99 } 100 //load tag plugin 101 /** @var helper_plugin_pagelist $Hpagelist */ 102 if (is_null($Hpagelist = $this->loadHelper('pagelist', false))) { 103 $this->sendResponse(sprintf($Htagfilter->getLang('missing_plugin'), 'pagelist')); 104 return; 105 } 106 107 $form = array_filter($form);//remove empty entries 108 109 $tag_list_r = []; 110 111 foreach ($form as $item) { //rearrange entries for tag plugin lookup 112 $tag_list_r[] = implode(' ', array_filter($item)); 113 } 114 115 $tag_list_r = array_filter($tag_list_r); 116 117 //lookup the pages from the taglist 118 //partially copied from tag->helper with less checks and no meta lookups 119 $page_names = []; 120 foreach ($tag_list_r as $key => $tag_list) { 121 $tags_parsed = $Htag->parseTagList($tag_list, true); 122 $pages_lookup = $Htag->getIndexedPagesMatchingTagQuery($tags_parsed); 123 foreach ($pages_lookup as $page_lookup) { 124 // filter by namespace, root namespace is identified with a dot 125 // root namespace is specified, discard all pages who lay outside the root namespace 126 if (($ns == '.' && getNS($page_lookup) === false) 127 || ($ns && strpos(':' . getNS($page_lookup) . ':', ':' . $ns . ':') === 0) 128 || $ns === '') { 129 if (auth_quickaclcheck($page_lookup) >= AUTH_READ) { 130 $page_names[$key][] = $page_lookup; 131 } 132 } 133 } 134 } 135 136 137 //get the first item 138 if (!is_array($pages_intersect = array_shift($page_names))) { 139 $pages_intersect = []; 140 } 141 142 //find the intersections 143 foreach ($page_names as $names) { 144 $pages_intersect = array_intersect($pages_intersect, $names); 145 } 146 147 //intersections with the pagesearch 148 if (is_array($pagesearch) && !empty($pagesearch)) { 149 $pages_intersect = array_intersect($pages_intersect, $pagesearch); 150 } 151 152 //no matching pages 153 if (count($pages_intersect) === 0) { 154 $this->sendResponse('<i>' . $lang['nothingfound'] . '</i>'); 155 return; 156 } 157 158 $pages_intersect = array_filter($pages_intersect, [$this, 'filterHide_Template']); 159 160 $pages = []; 161 foreach ($pages_intersect as $page) { 162 $title = p_get_metadata($page, 'title', METADATA_DONT_RENDER); 163 $pages[$title ?: $page] = [ 164 'title' => $title ?: $page, 165 'id' => $page 166 ]; 167 } 168 if (is_array($pagelistFlags) && in_array('rsort', $pagelistFlags)) { 169 krsort($pages, SORT_STRING | SORT_FLAG_CASE); 170 } else { 171 ksort($pages, SORT_STRING | SORT_FLAG_CASE); 172 } 173 174 if (!isset($tagfilterFlags['tagcolumn'])) { 175 $tagfilterFlags['tagcolumn'] = []; 176 } 177 foreach ($tagfilterFlags['tagcolumn'] as $tagcolumn) { 178 $Hpagelist->addColumn('tagfilter', hsc($tagcolumn)); 179 } 180 $Hpagelist->setFlags($pagelistFlags); 181 $Hpagelist->startList(); 182 183 foreach ($pages as $page) { 184 $Hpagelist->addPage($page); 185 } 186 $text = $Hpagelist->finishList(); 187 188 $this->sendResponse($text); 189 } 190 191 private function getJSONdecodedUrlParameter($name) 192 { 193 global $INPUT; 194 195 $param = null; 196 if ($INPUT->has($name)) { 197 $param = $INPUT->param($name); 198 $param = json_decode($param); 199 } 200 return $param; 201 } 202 203 /** 204 * @param string $text 205 */ 206 private function sendResponse($text) 207 { 208 global $INPUT; 209 $tagfilter_id = $INPUT->int('id'); 210 echo json_encode(['id' => $tagfilter_id, 'text' => $text]); 211 } 212 213 /** 214 * Filter function 215 * show only pages different to _template and the have to exist 216 * 217 * @param string $val 218 * @return bool 219 */ 220 private function filterHide_Template($val) 221 { 222 return strpos($val, "_template") === false && @file_exists(wikiFN($val)); 223 } 224 225} 226 227 228 229 230 231