1f61105deSAdrian Lang<?php 2f61105deSAdrian Lang 3f61105deSAdrian Langif(!defined('DOKU_INC')) die(); 4e4543b6dSAdrian Langclass helper_plugin_tagging extends DokuWiki_Plugin { 5f61105deSAdrian Lang 6289f50bdSAndreas Gohr /** 7289f50bdSAndreas Gohr * @return helper_plugin_sqlite 8289f50bdSAndreas Gohr */ 9289f50bdSAndreas Gohr public function getDB() { 10f61105deSAdrian Lang static $db; 11f61105deSAdrian Lang if (!is_null($db)) { 12f61105deSAdrian Lang return $db; 13f61105deSAdrian Lang } 14f61105deSAdrian Lang 15f61105deSAdrian Lang $db = plugin_load('helper', 'sqlite'); 16f61105deSAdrian Lang if (is_null($db)) { 17f61105deSAdrian Lang msg('The tagging plugin needs the sqlite plugin', -1); 18f61105deSAdrian Lang return false; 19f61105deSAdrian Lang } 207e6afce6SAndreas Gohr $db->init('tagging',dirname(__FILE__).'/db/'); 21f61105deSAdrian Lang return $db; 22f61105deSAdrian Lang } 23f61105deSAdrian Lang 24f61105deSAdrian Lang public function replaceTags($id, $user, $tags) { 25f61105deSAdrian Lang $db = $this->getDB(); 26f61105deSAdrian Lang $db->query('BEGIN TRANSACTION'); 27f61105deSAdrian Lang $queries = array(array('DELETE FROM taggings WHERE pid = ? AND tagger = ?', $id, $user)); 28f61105deSAdrian Lang foreach ($tags as $tag) { 29f61105deSAdrian Lang $queries[] = array('INSERT INTO taggings (pid, tagger, tag) VALUES(?, ?, ?)', $id, $user, $tag); 30f61105deSAdrian Lang } 31f61105deSAdrian Lang 32f61105deSAdrian Lang foreach ($queries as $query) { 33f61105deSAdrian Lang if (!call_user_func_array(array($db, 'query'), $query)) { 34f61105deSAdrian Lang $db->query('ROLLBACK TRANSACTION'); 35f61105deSAdrian Lang return false; 36f61105deSAdrian Lang } 37f61105deSAdrian Lang } 38f61105deSAdrian Lang return $db->query('COMMIT TRANSACTION'); 39f61105deSAdrian Lang } 40f61105deSAdrian Lang 41f61105deSAdrian Lang public function getTags($search, $return) { 42f61105deSAdrian Lang $where = '1=1'; 43f61105deSAdrian Lang foreach($search as $k => $v) { 44b2073787SDominik Eckelmann if ($k === 'tag') { 45b2073787SDominik Eckelmann $k = 'UPPER(tag)'; 46b2073787SDominik Eckelmann } 47b2073787SDominik Eckelmann 48b2073787SDominik Eckelmann if ($this->useLike($v)) { 49b2073787SDominik Eckelmann $where .= " AND $k LIKE"; 50f61105deSAdrian Lang } else { 51b2073787SDominik Eckelmann $where .= " AND $k ="; 52b2073787SDominik Eckelmann } 53b2073787SDominik Eckelmann 54b2073787SDominik Eckelmann if ($k === 'UPPER(tag)') { 55b2073787SDominik Eckelmann $where .= ' UPPER(?)'; 56b2073787SDominik Eckelmann } else { 57b2073787SDominik Eckelmann $where .= ' ?'; 58f61105deSAdrian Lang } 59f61105deSAdrian Lang } 60b2073787SDominik Eckelmann 61f61105deSAdrian Lang $db = $this->getDB(); 62f61105deSAdrian Lang $res = $db->query('SELECT ' . $return . ', COUNT(*) ' . 630dbdc3fcSAdrian Lang 'FROM taggings WHERE ' . $where . ' GROUP BY ' . $return . 640dbdc3fcSAdrian Lang ' ORDER BY tag', 65f61105deSAdrian Lang array_values($search)); 66f61105deSAdrian Lang 67f61105deSAdrian Lang $res = $db->res2arr($res); 68f61105deSAdrian Lang $ret = array(); 69f61105deSAdrian Lang foreach ($res as $v) { 70f61105deSAdrian Lang $ret[$v[$return]] = $v['COUNT(*)']; 71f61105deSAdrian Lang } 72f61105deSAdrian Lang return $ret; 73f61105deSAdrian Lang } 74f61105deSAdrian Lang 75b2073787SDominik Eckelmann private function useLike($v) { 76b2073787SDominik Eckelmann return strpos($v, '%') === 0 || strrpos($v, '%') === strlen($v) - 1; 77b2073787SDominik Eckelmann } 78b2073787SDominik Eckelmann 79f61105deSAdrian Lang public function getTagSearchURL($tag) { 80f61105deSAdrian Lang return '?do=search&id=' . $tag . '#' . 81f61105deSAdrian Lang str_replace(' ', '_', strtolower($this->getLang('search_section_title'))); 82f61105deSAdrian Lang } 83f61105deSAdrian Lang 84f61105deSAdrian Lang public function cloudData($tags, $levels = 10) { 85f61105deSAdrian Lang $min = min($tags); 86f61105deSAdrian Lang $max = max($tags); 87f61105deSAdrian Lang 88f61105deSAdrian Lang // calculate tresholds 89f61105deSAdrian Lang $tresholds = array(); 90f61105deSAdrian Lang for($i=0; $i<=$levels; $i++){ 91f61105deSAdrian Lang $tresholds[$i] = pow($max - $min + 1, $i/$levels) + $min - 1; 92f61105deSAdrian Lang } 93f61105deSAdrian Lang 94f61105deSAdrian Lang // assign weights 95f61105deSAdrian Lang foreach($tags as $tag => $cnt){ 96f61105deSAdrian Lang foreach($tresholds as $tresh => $val){ 97f61105deSAdrian Lang if($cnt <= $val){ 98f61105deSAdrian Lang $tags[$tag] = $tresh; 99f61105deSAdrian Lang break; 100f61105deSAdrian Lang } 101f61105deSAdrian Lang $tags[$tag] = $levels; 102f61105deSAdrian Lang } 103f61105deSAdrian Lang } 104f61105deSAdrian Lang return $tags; 105f61105deSAdrian Lang } 106f61105deSAdrian Lang 107f61105deSAdrian Lang public function html_cloud($tags, $type, $func, $wrap = true, $return = false) { 108f61105deSAdrian Lang $ret = ''; 1090dbdc3fcSAdrian Lang if ($wrap) $ret .= '<ul class="tagging_cloud clearfix">'; 110f61105deSAdrian Lang if (count($tags) === 0) { 111f61105deSAdrian Lang // Produce valid XHTML (ul needs a child) 112f61105deSAdrian Lang $this->setupLocale(); 113f61105deSAdrian Lang $ret .= '<li><div class="li">' . $this->lang['js']['no' . $type . 's'] . '</div></li>'; 114f61105deSAdrian Lang } else { 115f61105deSAdrian Lang $tags = $this->cloudData($tags); 116f61105deSAdrian Lang foreach ($tags as $val => $size) { 117f61105deSAdrian Lang $ret .= '<li class="t' . $size . '"><div class="li">'; 118f61105deSAdrian Lang $ret .= call_user_func($func, $val); 119f61105deSAdrian Lang $ret .= '</div></li>'; 120f61105deSAdrian Lang } 121f61105deSAdrian Lang } 122f61105deSAdrian Lang if ($wrap) $ret .= '</ul>'; 123f61105deSAdrian Lang if ($return) return $ret; 124f61105deSAdrian Lang echo $ret; 125f61105deSAdrian Lang } 126f61105deSAdrian Lang 127f61105deSAdrian Lang private function linkToSearch($tag) { 128f61105deSAdrian Lang return '<a href="' . hsc($this->getTagSearchURL($tag)) . '">' . 129f61105deSAdrian Lang $tag . '</a>'; 130f61105deSAdrian Lang } 131f61105deSAdrian Lang 132f61105deSAdrian Lang public function tpl_tags() { 133f61105deSAdrian Lang global $ID; 134f61105deSAdrian Lang global $INFO; 135f61105deSAdrian Lang global $lang; 136f61105deSAdrian Lang $tags = $this->getTags(array('pid' => $ID), 'tag'); 137f61105deSAdrian Lang $this->html_cloud($tags, 'tag', array($this, 'linkToSearch')); 138f61105deSAdrian Lang 139f61105deSAdrian Lang if (isset($_SERVER['REMOTE_USER']) && $INFO['writable']) { 140f61105deSAdrian Lang $lang['btn_tagging_edit'] = $lang['btn_secedit']; 141f61105deSAdrian Lang echo html_btn('tagging_edit', $ID, '', array()); 142289f50bdSAndreas Gohr $form = new Doku_Form(array('id' => 'tagging__edit')); 143e4543b6dSAdrian Lang $form->addHidden('tagging[id]', $ID); 144289f50bdSAndreas Gohr $form->addHidden('call', 'plugin_tagging_save'); 145e4543b6dSAdrian Lang $form->addElement(form_makeTextField('tagging[tags]', implode(', ', array_keys($this->getTags(array('pid' => $ID, 'tagger' => $_SERVER['REMOTE_USER']), 'tag'))))); 146289f50bdSAndreas Gohr $form->addElement(form_makeButton('submit', 'save', $lang['btn_save'], array('id' => 'tagging__edit_save'))); 147289f50bdSAndreas Gohr $form->addElement(form_makeButton('submit', 'cancel', $lang['btn_cancel'], array('id' => 'tagging__edit_cancel'))); 148f61105deSAdrian Lang $form->printForm(); 149f61105deSAdrian Lang } 150f61105deSAdrian Lang } 151872edc7cSRené Corinth 152*8a1a3846SAndreas Gohr /** 153*8a1a3846SAndreas Gohr * @return array 154*8a1a3846SAndreas Gohr */ 155872edc7cSRené Corinth public function getAllTags(){ 156872edc7cSRené Corinth 157872edc7cSRené Corinth $db = $this->getDb(); 158*8a1a3846SAndreas Gohr $res = $db->query('SELECT pid, tag, tagger FROM taggings ORDER BY tag'); 159872edc7cSRené Corinth 160872edc7cSRené Corinth $tags_tmp = $db->res2arr($res); 161872edc7cSRené Corinth $tags = array(); 162872edc7cSRené Corinth foreach ($tags_tmp as $tag) { 163872edc7cSRené Corinth 164872edc7cSRené Corinth $tags[$tag['tag']]['pid'][] = $tag['pid']; 165872edc7cSRené Corinth 166872edc7cSRené Corinth if (isset($tags[$tag['tag']]['count'])) { 167872edc7cSRené Corinth $tags[$tag['tag']]['count']++; 168*8a1a3846SAndreas Gohr $tags[$tag['tag']]['tagger'][] = $tag['tagger']; 169872edc7cSRené Corinth } else { 170872edc7cSRené Corinth $tags[$tag['tag']]['count'] = 1; 171*8a1a3846SAndreas Gohr $tags[$tag['tag']]['tagger'] = array($tag['tagger']); 172872edc7cSRené Corinth } 173872edc7cSRené Corinth } 174872edc7cSRené Corinth return $tags; 175872edc7cSRené Corinth } 176872edc7cSRené Corinth 177*8a1a3846SAndreas Gohr /** 178*8a1a3846SAndreas Gohr * Renames a tag 179*8a1a3846SAndreas Gohr * 180*8a1a3846SAndreas Gohr * @param string $formerTagName 181*8a1a3846SAndreas Gohr * @param string $newTagName 182*8a1a3846SAndreas Gohr */ 183872edc7cSRené Corinth public function renameTag($formerTagName, $newTagName) { 184872edc7cSRené Corinth 185872edc7cSRené Corinth if(empty($formerTagName) || empty($newTagName)) { 186*8a1a3846SAndreas Gohr msg($this->getLang("admin enter tag names"), -1); 187*8a1a3846SAndreas Gohr return; 188872edc7cSRené Corinth } 189872edc7cSRené Corinth 190872edc7cSRené Corinth $db = $this->getDb(); 191872edc7cSRené Corinth 192872edc7cSRené Corinth $res = $db->query('SELECT pid FROM taggings WHERE tag="'. $formerTagName .'"'); 193872edc7cSRené Corinth $check = $db->res2arr($res); 194872edc7cSRené Corinth 195872edc7cSRené Corinth if (empty($check)) { 196*8a1a3846SAndreas Gohr msg($this->getLang("admin tag does not exists"), -1); 197*8a1a3846SAndreas Gohr return; 198872edc7cSRené Corinth } 199872edc7cSRené Corinth 200872edc7cSRené Corinth $res = $db->query("UPDATE taggings SET tag='".$newTagName."' WHERE tag='" . $formerTagName . "'"); 201872edc7cSRené Corinth $db->res2arr($res); 202872edc7cSRené Corinth 203*8a1a3846SAndreas Gohr msg($this->getLang("admin saved"), 1); 204*8a1a3846SAndreas Gohr return; 205872edc7cSRené Corinth } 206872edc7cSRené Corinth 207f61105deSAdrian Lang} 208