1<?php 2 3if(!defined('DOKU_INC')) die(); 4class helper_plugin_tagging extends DokuWiki_Plugin { 5 6 private function getDB() { 7 static $db; 8 if (!is_null($db)) { 9 return $db; 10 } 11 12 $db = plugin_load('helper', 'sqlite'); 13 if (is_null($db)) { 14 msg('The tagging plugin needs the sqlite plugin', -1); 15 return false; 16 } 17 if($db->init('tagging',dirname(__FILE__).'/db/')){ 18 return $db; 19 } 20 return false; 21 } 22 23 public function replaceTags($id, $user, $tags) { 24 $db = $this->getDB(); 25 $db->query('BEGIN TRANSACTION'); 26 $queries = array(array('DELETE FROM taggings WHERE pid = ? AND tagger = ?', $id, $user)); 27 foreach ($tags as $tag) { 28 $queries[] = array('INSERT INTO taggings (pid, tagger, tag) VALUES(?, ?, ?)', $id, $user, $tag); 29 } 30 31 foreach ($queries as $query) { 32 if (!call_user_func_array(array($db, 'query'), $query)) { 33 $db->query('ROLLBACK TRANSACTION'); 34 return false; 35 } 36 } 37 return $db->query('COMMIT TRANSACTION'); 38 } 39 40 public function getTags($search, $return) { 41 $where = '1=1'; 42 foreach($search as $k => $v) { 43 if ($k === 'tag') { 44 $k = 'UPPER(tag)'; 45 } 46 47 if ($this->useLike($v)) { 48 $where .= " AND $k LIKE"; 49 } else { 50 $where .= " AND $k ="; 51 } 52 53 if ($k === 'UPPER(tag)') { 54 $where .= ' UPPER(?)'; 55 } else { 56 $where .= ' ?'; 57 } 58 } 59 60 $db = $this->getDB(); 61 $res = $db->query('SELECT ' . $return . ', COUNT(*) ' . 62 'FROM taggings WHERE ' . $where . ' GROUP BY ' . $return . 63 ' ORDER BY tag', 64 array_values($search)); 65 66 $res = $db->res2arr($res); 67 $ret = array(); 68 foreach ($res as $v) { 69 $ret[$v[$return]] = $v['COUNT(*)']; 70 } 71 return $ret; 72 } 73 74 private function useLike($v) { 75 return strpos($v, '%') === 0 || strrpos($v, '%') === strlen($v) - 1; 76 } 77 78 public function getTagSearchURL($tag) { 79 return '?do=search&id=' . $tag . '#' . 80 str_replace(' ', '_', strtolower($this->getLang('search_section_title'))); 81 } 82 83 public function cloudData($tags, $levels = 10) { 84 $min = min($tags); 85 $max = max($tags); 86 87 // calculate tresholds 88 $tresholds = array(); 89 for($i=0; $i<=$levels; $i++){ 90 $tresholds[$i] = pow($max - $min + 1, $i/$levels) + $min - 1; 91 } 92 93 // assign weights 94 foreach($tags as $tag => $cnt){ 95 foreach($tresholds as $tresh => $val){ 96 if($cnt <= $val){ 97 $tags[$tag] = $tresh; 98 break; 99 } 100 $tags[$tag] = $levels; 101 } 102 } 103 return $tags; 104 } 105 106 public function html_cloud($tags, $type, $func, $wrap = true, $return = false) { 107 $ret = ''; 108 if ($wrap) $ret .= '<ul class="tagging_cloud clearfix">'; 109 if (count($tags) === 0) { 110 // Produce valid XHTML (ul needs a child) 111 $this->setupLocale(); 112 $ret .= '<li><div class="li">' . $this->lang['js']['no' . $type . 's'] . '</div></li>'; 113 } else { 114 $tags = $this->cloudData($tags); 115 foreach ($tags as $val => $size) { 116 $ret .= '<li class="t' . $size . '"><div class="li">'; 117 $ret .= call_user_func($func, $val); 118 $ret .= '</div></li>'; 119 } 120 } 121 if ($wrap) $ret .= '</ul>'; 122 if ($return) return $ret; 123 echo $ret; 124 } 125 126 private function linkToSearch($tag) { 127 return '<a href="' . hsc($this->getTagSearchURL($tag)) . '">' . 128 $tag . '</a>'; 129 } 130 131 public function tpl_tags() { 132 global $ID; 133 global $INFO; 134 global $lang; 135 $tags = $this->getTags(array('pid' => $ID), 'tag'); 136 $this->html_cloud($tags, 'tag', array($this, 'linkToSearch')); 137 138 if (isset($_SERVER['REMOTE_USER']) && $INFO['writable']) { 139 $lang['btn_tagging_edit'] = $lang['btn_secedit']; 140 echo html_btn('tagging_edit', $ID, '', array()); 141 $form = new Doku_Form(array('id' => 'tagging_edit', 'style' => 'display: none;')); 142 $form->addHidden('tagging[id]', $ID); 143 $form->addElement(form_makeTextField('tagging[tags]', implode(', ', array_keys($this->getTags(array('pid' => $ID, 'tagger' => $_SERVER['REMOTE_USER']), 'tag'))))); 144 $form->addElement(form_makeButton('submit', 'save', $lang['btn_save'], array('id' => 'tagging_edit_save'))); 145 $form->addElement(form_makeButton('submit', 'cancel', $lang['btn_cancel'], array('id' => 'tagging_edit_cancel'))); 146 $form->printForm(); 147 } 148 } 149} 150