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() { 10*302a38efSAndreas Gohr static $db = null; 11f61105deSAdrian Lang if (!is_null($db)) { 12f61105deSAdrian Lang return $db; 13f61105deSAdrian Lang } 14f61105deSAdrian Lang 15*302a38efSAndreas Gohr /** @var helper_plugin_sqlite $db */ 16f61105deSAdrian Lang $db = plugin_load('helper', 'sqlite'); 17f61105deSAdrian Lang if (is_null($db)) { 18f61105deSAdrian Lang msg('The tagging plugin needs the sqlite plugin', -1); 19f61105deSAdrian Lang return false; 20f61105deSAdrian Lang } 217e6afce6SAndreas Gohr $db->init('tagging',dirname(__FILE__).'/db/'); 22*302a38efSAndreas Gohr $db->create_function('CLEANTAG', array($this, 'cleanTag'), 1); 23f61105deSAdrian Lang return $db; 24f61105deSAdrian Lang } 25f61105deSAdrian Lang 26*302a38efSAndreas Gohr /** 27*302a38efSAndreas Gohr * Canonicalizes the tag to its lower case nospace form 28*302a38efSAndreas Gohr * 29*302a38efSAndreas Gohr * @param $tag 30*302a38efSAndreas Gohr * @return string 31*302a38efSAndreas Gohr */ 32*302a38efSAndreas Gohr public function cleanTag($tag) { 33*302a38efSAndreas Gohr $tag = str_replace(' ', '', $tag); 34*302a38efSAndreas Gohr $tag = utf8_strtolower($tag); 35*302a38efSAndreas Gohr return $tag; 36*302a38efSAndreas Gohr } 37*302a38efSAndreas Gohr 38*302a38efSAndreas Gohr 39f61105deSAdrian Lang public function replaceTags($id, $user, $tags) { 40f61105deSAdrian Lang $db = $this->getDB(); 41f61105deSAdrian Lang $db->query('BEGIN TRANSACTION'); 42f61105deSAdrian Lang $queries = array(array('DELETE FROM taggings WHERE pid = ? AND tagger = ?', $id, $user)); 43f61105deSAdrian Lang foreach ($tags as $tag) { 44f61105deSAdrian Lang $queries[] = array('INSERT INTO taggings (pid, tagger, tag) VALUES(?, ?, ?)', $id, $user, $tag); 45f61105deSAdrian Lang } 46f61105deSAdrian Lang 47f61105deSAdrian Lang foreach ($queries as $query) { 48f61105deSAdrian Lang if (!call_user_func_array(array($db, 'query'), $query)) { 49f61105deSAdrian Lang $db->query('ROLLBACK TRANSACTION'); 50f61105deSAdrian Lang return false; 51f61105deSAdrian Lang } 52f61105deSAdrian Lang } 53f61105deSAdrian Lang return $db->query('COMMIT TRANSACTION'); 54f61105deSAdrian Lang } 55f61105deSAdrian Lang 56f61105deSAdrian Lang public function getTags($search, $return) { 57f61105deSAdrian Lang $where = '1=1'; 58f61105deSAdrian Lang foreach($search as $k => $v) { 59b2073787SDominik Eckelmann if ($k === 'tag') { 60*302a38efSAndreas Gohr $k = 'CLEANTAG(tag)'; 61b2073787SDominik Eckelmann } 62b2073787SDominik Eckelmann 63b2073787SDominik Eckelmann if ($this->useLike($v)) { 64b2073787SDominik Eckelmann $where .= " AND $k LIKE"; 65f61105deSAdrian Lang } else { 66b2073787SDominik Eckelmann $where .= " AND $k ="; 67b2073787SDominik Eckelmann } 68b2073787SDominik Eckelmann 69*302a38efSAndreas Gohr if ($k === 'CLEANTAG(tag)') { 70*302a38efSAndreas Gohr $where .= ' CLEANTAG(?)'; 71b2073787SDominik Eckelmann } else { 72b2073787SDominik Eckelmann $where .= ' ?'; 73f61105deSAdrian Lang } 74f61105deSAdrian Lang } 75b2073787SDominik Eckelmann 76f61105deSAdrian Lang $db = $this->getDB(); 77f61105deSAdrian Lang $res = $db->query('SELECT ' . $return . ', COUNT(*) ' . 780dbdc3fcSAdrian Lang 'FROM taggings WHERE ' . $where . ' GROUP BY ' . $return . 790dbdc3fcSAdrian Lang ' ORDER BY tag', 80f61105deSAdrian Lang array_values($search)); 81f61105deSAdrian Lang 82f61105deSAdrian Lang $res = $db->res2arr($res); 83f61105deSAdrian Lang $ret = array(); 84f61105deSAdrian Lang foreach ($res as $v) { 85f61105deSAdrian Lang $ret[$v[$return]] = $v['COUNT(*)']; 86f61105deSAdrian Lang } 87f61105deSAdrian Lang return $ret; 88f61105deSAdrian Lang } 89f61105deSAdrian Lang 90b2073787SDominik Eckelmann private function useLike($v) { 91b2073787SDominik Eckelmann return strpos($v, '%') === 0 || strrpos($v, '%') === strlen($v) - 1; 92b2073787SDominik Eckelmann } 93b2073787SDominik Eckelmann 94*302a38efSAndreas Gohr /** 95*302a38efSAndreas Gohr * Constructs the URL to search for a tag 96*302a38efSAndreas Gohr * 97*302a38efSAndreas Gohr * @param $tag 98*302a38efSAndreas Gohr * @return string 99*302a38efSAndreas Gohr */ 100f61105deSAdrian Lang public function getTagSearchURL($tag) { 101*302a38efSAndreas Gohr return '?do=search&id=' . rawurlencode($tag); 102f61105deSAdrian Lang } 103f61105deSAdrian Lang 104f61105deSAdrian Lang public function cloudData($tags, $levels = 10) { 105f61105deSAdrian Lang $min = min($tags); 106f61105deSAdrian Lang $max = max($tags); 107f61105deSAdrian Lang 108f61105deSAdrian Lang // calculate tresholds 109f61105deSAdrian Lang $tresholds = array(); 110f61105deSAdrian Lang for($i=0; $i<=$levels; $i++){ 111f61105deSAdrian Lang $tresholds[$i] = pow($max - $min + 1, $i/$levels) + $min - 1; 112f61105deSAdrian Lang } 113f61105deSAdrian Lang 114f61105deSAdrian Lang // assign weights 115f61105deSAdrian Lang foreach($tags as $tag => $cnt){ 116f61105deSAdrian Lang foreach($tresholds as $tresh => $val){ 117f61105deSAdrian Lang if($cnt <= $val){ 118f61105deSAdrian Lang $tags[$tag] = $tresh; 119f61105deSAdrian Lang break; 120f61105deSAdrian Lang } 121f61105deSAdrian Lang $tags[$tag] = $levels; 122f61105deSAdrian Lang } 123f61105deSAdrian Lang } 124f61105deSAdrian Lang return $tags; 125f61105deSAdrian Lang } 126f61105deSAdrian Lang 127f61105deSAdrian Lang public function html_cloud($tags, $type, $func, $wrap = true, $return = false) { 128f61105deSAdrian Lang $ret = ''; 1290dbdc3fcSAdrian Lang if ($wrap) $ret .= '<ul class="tagging_cloud clearfix">'; 130f61105deSAdrian Lang if (count($tags) === 0) { 131f61105deSAdrian Lang // Produce valid XHTML (ul needs a child) 132f61105deSAdrian Lang $this->setupLocale(); 133f61105deSAdrian Lang $ret .= '<li><div class="li">' . $this->lang['js']['no' . $type . 's'] . '</div></li>'; 134f61105deSAdrian Lang } else { 135f61105deSAdrian Lang $tags = $this->cloudData($tags); 136f61105deSAdrian Lang foreach ($tags as $val => $size) { 137f61105deSAdrian Lang $ret .= '<li class="t' . $size . '"><div class="li">'; 138f61105deSAdrian Lang $ret .= call_user_func($func, $val); 139f61105deSAdrian Lang $ret .= '</div></li>'; 140f61105deSAdrian Lang } 141f61105deSAdrian Lang } 142f61105deSAdrian Lang if ($wrap) $ret .= '</ul>'; 143f61105deSAdrian Lang if ($return) return $ret; 144f61105deSAdrian Lang echo $ret; 145f61105deSAdrian Lang } 146f61105deSAdrian Lang 147*302a38efSAndreas Gohr protected function linkToSearch($tag) { 148f61105deSAdrian Lang return '<a href="' . hsc($this->getTagSearchURL($tag)) . '">' . 149f61105deSAdrian Lang $tag . '</a>'; 150f61105deSAdrian Lang } 151f61105deSAdrian Lang 152f61105deSAdrian Lang public function tpl_tags() { 153f61105deSAdrian Lang global $ID; 154f61105deSAdrian Lang global $INFO; 155f61105deSAdrian Lang global $lang; 156f61105deSAdrian Lang $tags = $this->getTags(array('pid' => $ID), 'tag'); 157f61105deSAdrian Lang $this->html_cloud($tags, 'tag', array($this, 'linkToSearch')); 158f61105deSAdrian Lang 159f61105deSAdrian Lang if (isset($_SERVER['REMOTE_USER']) && $INFO['writable']) { 160f61105deSAdrian Lang $lang['btn_tagging_edit'] = $lang['btn_secedit']; 161f61105deSAdrian Lang echo html_btn('tagging_edit', $ID, '', array()); 162289f50bdSAndreas Gohr $form = new Doku_Form(array('id' => 'tagging__edit')); 163e4543b6dSAdrian Lang $form->addHidden('tagging[id]', $ID); 164289f50bdSAndreas Gohr $form->addHidden('call', 'plugin_tagging_save'); 165e4543b6dSAdrian Lang $form->addElement(form_makeTextField('tagging[tags]', implode(', ', array_keys($this->getTags(array('pid' => $ID, 'tagger' => $_SERVER['REMOTE_USER']), 'tag'))))); 166289f50bdSAndreas Gohr $form->addElement(form_makeButton('submit', 'save', $lang['btn_save'], array('id' => 'tagging__edit_save'))); 167289f50bdSAndreas Gohr $form->addElement(form_makeButton('submit', 'cancel', $lang['btn_cancel'], array('id' => 'tagging__edit_cancel'))); 168f61105deSAdrian Lang $form->printForm(); 169f61105deSAdrian Lang } 170f61105deSAdrian Lang } 171872edc7cSRené Corinth 1728a1a3846SAndreas Gohr /** 1738a1a3846SAndreas Gohr * @return array 1748a1a3846SAndreas Gohr */ 175872edc7cSRené Corinth public function getAllTags(){ 176872edc7cSRené Corinth 177872edc7cSRené Corinth $db = $this->getDb(); 1788a1a3846SAndreas Gohr $res = $db->query('SELECT pid, tag, tagger FROM taggings ORDER BY tag'); 179872edc7cSRené Corinth 180872edc7cSRené Corinth $tags_tmp = $db->res2arr($res); 181872edc7cSRené Corinth $tags = array(); 182872edc7cSRené Corinth foreach ($tags_tmp as $tag) { 183*302a38efSAndreas Gohr $tid = $this->cleanTag($tag['tag']); 184872edc7cSRené Corinth 185*302a38efSAndreas Gohr //$tags[$tid]['pid'][] = $tag['pid']; 186872edc7cSRené Corinth 187*302a38efSAndreas Gohr if (isset($tags[$tid]['count'])) { 188*302a38efSAndreas Gohr $tags[$tid]['count']++; 189*302a38efSAndreas Gohr $tags[$tid]['tagger'][] = $tag['tagger']; 190872edc7cSRené Corinth } else { 191*302a38efSAndreas Gohr $tags[$tid]['count'] = 1; 192*302a38efSAndreas Gohr $tags[$tid]['tagger'] = array($tag['tagger']); 193872edc7cSRené Corinth } 194872edc7cSRené Corinth } 195872edc7cSRené Corinth return $tags; 196872edc7cSRené Corinth } 197872edc7cSRené Corinth 1988a1a3846SAndreas Gohr /** 1998a1a3846SAndreas Gohr * Renames a tag 2008a1a3846SAndreas Gohr * 2018a1a3846SAndreas Gohr * @param string $formerTagName 2028a1a3846SAndreas Gohr * @param string $newTagName 2038a1a3846SAndreas Gohr */ 204872edc7cSRené Corinth public function renameTag($formerTagName, $newTagName) { 205872edc7cSRené Corinth 206872edc7cSRené Corinth if(empty($formerTagName) || empty($newTagName)) { 2078a1a3846SAndreas Gohr msg($this->getLang("admin enter tag names"), -1); 2088a1a3846SAndreas Gohr return; 209872edc7cSRené Corinth } 210872edc7cSRené Corinth 211872edc7cSRené Corinth $db = $this->getDb(); 212872edc7cSRené Corinth 213*302a38efSAndreas Gohr $res = $db->query('SELECT pid FROM taggings WHERE tag= ?', $formerTagName); 214872edc7cSRené Corinth $check = $db->res2arr($res); 215872edc7cSRené Corinth 216872edc7cSRené Corinth if (empty($check)) { 2178a1a3846SAndreas Gohr msg($this->getLang("admin tag does not exists"), -1); 2188a1a3846SAndreas Gohr return; 219872edc7cSRené Corinth } 220872edc7cSRené Corinth 221*302a38efSAndreas Gohr $res = $db->query("UPDATE taggings SET tag = ? WHERE tag = ?", $newTagName, $formerTagName); 222872edc7cSRené Corinth $db->res2arr($res); 223872edc7cSRené Corinth 2248a1a3846SAndreas Gohr msg($this->getLang("admin saved"), 1); 2258a1a3846SAndreas Gohr return; 226872edc7cSRené Corinth } 227872edc7cSRené Corinth 228f61105deSAdrian Lang} 229