1<?php 2/** 3 * DokuWiki Plugin TagAdd (Action Component) 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author lisps 7 */ 8 9 10/** 11 * All DokuWiki plugins to extend the parser/rendering mechanism 12 * need to inherit from this class 13 */ 14class action_plugin_tagadd extends DokuWiki_Action_Plugin 15{ 16 17 public function register(Doku_Event_Handler $controller) { 18 $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, '_addjs'); 19 if($this->getConf('showPagetoolBtn')) { 20 $controller->register_hook('TEMPLATE_PAGETOOLS_DISPLAY', 'BEFORE', $this, '_addbutton'); 21 $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addsvgbutton'); 22 } 23 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_ajax_call'); 24 } 25 26 public function _addjs(Doku_Event $event, $param) { 27 global $ID; 28 global $JSINFO; 29 global $ACT; 30 31 $perm = auth_quickaclcheck($ID); 32 if ($perm > AUTH_READ) 33 $JSINFO['acl_write'] = '1'; 34 $JSINFO['currentNamespace'] = (($ns = getNS($ID))?$ns:''); 35 36 if(!isset($JSINFO['act'])) { 37 $JSINFO['act'] = $ACT; 38 } 39 40 $JSINFO['tagadd_altKey'] = $this->getConf('altKey'); 41 $JSINFO['tagadd_ctrlKey'] = $this->getConf('ctrlKey'); 42 $JSINFO['tagadd_keyCode'] = array_map('trim',explode(',',$this->getConf('keyCode'))); 43 44 } 45 46 public function _addbutton(Doku_Event $event) { 47 global $ID; 48 49 $perm = auth_quickaclcheck($ID); 50 if ($perm > AUTH_READ) { 51 $event->data['items'][] = '<li class="plugin_tagadd__addtags">' . tpl_link(wl($ID), '<span>'.$this->getLang('btn_addTagButton').'</span>', 52 'class="action tagadd" title="'.$this->getLang('btn_addTagButton').'"', 1) . '</li>'; 53 } 54 } 55 56 57 public function addsvgbutton(Doku_Event $event) { 58 if($event->data['view'] != 'page') return; 59 $event->data['items'][] = new \dokuwiki\plugin\tagadd\MenuItem(); 60 } 61 62 63 public function _ajax_call(Doku_Event $event, $param) { 64 if ($event->data !== 'plugin_tagadd') { 65 return; 66 } 67 //no other ajax call handlers needed 68 $event->stopPropagation(); 69 $event->preventDefault(); 70 71 /* @var $INPUT \Input */ 72 global $INPUT; 73 global $ID; 74 75 #Variables 76 $action = $INPUT->str('action'); 77 78 79 /* @var $Hajax \helper_plugin_ajaxedit */ 80 $Hajax = $this->loadHelper('ajaxedit'); 81 82 $Htf = $this->loadhelper('tagfilter'); 83 84 //Action Save Tags 85 if($action === 'saveTags') { 86 $chked_tags=array(); 87 foreach($INPUT->arr('form', array()) as $entry){ 88 if($entry['name']=='tag') 89 $chked_tags[]=$entry['value']; 90 } 91 sort($chked_tags); 92 93 $this->editWiki($chked_tags); 94 95 $Htag= $this->loadHelper('tag'); 96 97 $links=$Htag->tagLinks($chked_tags); 98 p_set_metadata($ID,array('subject'=>$chked_tags)); 99 if(!$Htf->isNewTagVersion()) { 100 $Htag->_updateTagIndex($ID,$chked_tags); 101 } 102 103 $Hajax->success(array('links'=>$links)); 104 105 } 106 107 //Action LoadForm 108 if($action === 'loadForm') { 109 global $INPUT; 110 $ns = $INPUT->str('ns'); 111 112 $form = $this->createForm($ID, $ns); 113 $Hajax->success(['form' => $form]); 114 } 115 } 116 117 /* 118 * Returns html breadcrumbs string for namspace selection 119 * @param string $ID Id of the site 120 * @return string html string 121 */ 122 protected function createNsSelector($ID, $ns_selected){ 123 //root namespace selector 124 if($ns_selected === '' ) { 125 $output="<a href='' onclick='tagadd__loadForm(\"\");return false;'><b>[:]</b></a>->"; 126 } else { 127 $output="<a href='' onclick='tagadd__loadForm(\"\");return false;'>[:]</a>->"; 128 } 129 $ns=explode(':',$ID); 130 $anz_ns=count($ns); 131 $root = ''; 132 133 foreach($ns as $key => $part){ 134 //this is the site name 135 if($key+1==$anz_ns) { 136 $output.=$part; 137 } else { 138 $root .=$part.':'; 139 140 if($root == $ns_selected ) { 141 $output.="<a href='' onclick='tagadd__loadForm(\"".$root."\");return false;'><b>[".$part."]</b></a>->"; 142 } else { 143 $output.="<a href='' onclick='tagadd__loadForm(\"".$root."\");return false;'>[".$part."]</a>->"; 144 } 145 } 146 } 147 return $output; 148 } 149 150 151 /** 152 * Returns html string with the accordion to select the tags 153 * loads the tags from the given site and the tags of the given namespace 154 * 155 * @param string $ID site id 156 * @param string $ns namespace from which the tags should be loaded 157 */ 158 protected function createForm($ID,$ns) 159 { 160 161 $Htagfilter= $this->loadHelper('tagfilter'); 162 $siteTags = $Htagfilter->getTagsBySiteID($ID); 163 $nsTags = $Htagfilter->getTagsByNamespace(trim($ns,':')); 164 165 sort($siteTags); 166 sort($nsTags); 167 //print_r($nsTags); 168 //workaround for empty entries in the arrays 169 $siteTags=array_filter($siteTags); 170 $nsTags=array_filter($nsTags); 171 /* 172 echo '<pre>'; 173 //print_r($nsTags); 174 print_r($siteTags); 175 echo '</pre>'; 176 */ 177 $html = $this->createNsSelector($ID, $ns); 178 179 if(count($nsTags)<1) return $html."<br><br>no Tags found"; 180 $form = new Doku_Form('tagadd__form'); 181 $form->_content[]='<div id="tagadd__accordion" height="800px">'; 182 183 $this->createAccordion($form,$nsTags,$siteTags); 184 185 $html .= $form->getForm(); 186 return $html; 187 } 188 189 /** 190 * Categorysize Tags by the first part before a ':' 191 * @param array $tags Array of tags 192 * <pre> 193 * array('category1:tag1','category1:tag2','category2:tag1','category2:tag2') 194 * </pre> 195 * @returns array multidimensional array 196 * <pre> 197 * [category1] => 'category1:tag1' 198 * => 'category1:tag2' 199 * [category2] => 'category2:tag1' 200 * => 'category2:tag2' 201 * </pre> 202 */ 203 protected function categorysizeTags($tags) 204 { 205 $catTags = array(); 206 foreach($tags as $nsTag){ 207 $category=substr($nsTag,0,strpos($nsTag,':')); 208 $catTags[$category][]=$nsTag; 209 } 210 ksort($catTags); 211 return $catTags; 212 } 213 214 /** 215 * creates the accordion with the checkbox fields 216 * @param Doku_Form $form doku form instance 217 * @param array $nsTags Selectable tags 218 * @param array $siteTags Checked tags 219 * @return string html code 220 */ 221 protected function createAccordion($form,$nsTags,$siteTags) 222 { 223 $nsTags_cat = $this->categorysizeTags($nsTags); 224 $siteTags_cat = $this->categorysizeTags($siteTags); 225 226 foreach($nsTags_cat as $category=>$tags) { 227 $catTagsCount = array_key_exists($category, $siteTags_cat) ? count($siteTags_cat[$category]) : '0'; 228 $form->_content[]='<h3><a href="#">'.$category.' ('.$catTagsCount.'/'.count($tags).')</a></h3><div>'; 229 foreach($tags as $tag){ 230 $chk_attrs=array(); 231 232 if(in_array($tag,$siteTags)){ 233 $chk_attrs['checked']='checked'; 234 } 235 $form->addElement(form_makeCheckboxField('tag', $tag, $tag, 'ad_'.$tag, 'tagadd', $chk_attrs)); 236 237 } 238 $form->_content[]='</div>'; 239 } 240 $form->_content[]='</div>'; 241 } 242 243 /** 244 * save the tags to the raw wiki page 245 * @tags array tags 246 */ 247 protected function editWiki($tags) { 248 $Hajax = $this->loadHelper('ajaxedit'); 249 $idcount = 0; 250 251 $data=$Hajax->getWikiPage(); 252 //find "our" fsinput fields 253 $found=explode("{{tag>",$data); 254 255 if ($idcount < count($found) && count($found)>1) { 256 257 $found[$idcount+1] = ltrim($found[$idcount+1]); 258 $stop=strpos($found[$idcount+1],"}}"); 259 if ($stop === FALSE) { 260 $Hajax->error('cant find object'); 261 } 262 else { 263 $oldstr = substr($found[$idcount+1],0,$stop); 264 $newstr=implode(" ",$tags); 265 if($stop == 0) 266 $found[$idcount+1]= " ".$newstr." ".$found[$idcount+1]; 267 else 268 $found[$idcount+1]=str_replace($oldstr," ".$newstr." ",$found[$idcount+1]); 269 } 270 //create new pagesource 271 $data=implode("{{tag>",$found); 272 273 //get removed and added tags 274 $oldtags_r=explode(" ",$oldstr); 275 $oldtags_r = array_filter($oldtags_r); 276 $diff =array_diff($oldtags_r,$tags); 277 $rem = array_intersect($oldtags_r,$diff); 278 $diff =array_diff($tags,$oldtags_r); 279 $add = array_intersect($tags,$diff); 280 } else if(!empty($tags)){ 281 $text = '{{tag>' . implode(" ",$tags) .'}}'; 282 $data.=DOKU_LF.$text; 283 284 $rem = array(); 285 $add = $tags; 286 } 287 else{ 288 $Hajax->error('no tags selected'); 289 } 290 291 292 $log = ""; 293 if(!empty($add)) { 294 $log.=' Added: '.implode(",",$add); 295 } 296 if(!empty($rem)) { 297 $log.=' Removed: '.implode(",",$rem); 298 } 299 300 $summary= "Tag".$idcount." ".$log; 301 $Hajax->saveWikiPage($data,$summary,true, [],false); 302 303 } 304 305 306} 307 308