1<?php 2 3if(!defined('DOKU_INC')) die(); 4class helper_plugin_tagging extends DokuWiki_Action_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 (strpos($v, '%') === 0 || strrpos($v, '%') === strlen($v)) { 44 $where .= " AND $k LIKE ?"; 45 } else { 46 $where .= " AND $k = ?"; 47 } 48 } 49 $db = $this->getDB(); 50 $res = $db->query('SELECT ' . $return . ', COUNT(*) ' . 51 'FROM taggings WHERE ' . $where . ' GROUP BY ' . $return . 52 ' ORDER BY tag', 53 array_values($search)); 54 55 $res = $db->res2arr($res); 56 $ret = array(); 57 foreach ($res as $v) { 58 $ret[$v[$return]] = $v['COUNT(*)']; 59 } 60 return $ret; 61 } 62 63 public function getTagSearchURL($tag) { 64 return '?do=search&id=' . $tag . '#' . 65 str_replace(' ', '_', strtolower($this->getLang('search_section_title'))); 66 } 67 68 public function cloudData($tags, $levels = 10) { 69 $min = min($tags); 70 $max = max($tags); 71 72 // calculate tresholds 73 $tresholds = array(); 74 for($i=0; $i<=$levels; $i++){ 75 $tresholds[$i] = pow($max - $min + 1, $i/$levels) + $min - 1; 76 } 77 78 // assign weights 79 foreach($tags as $tag => $cnt){ 80 foreach($tresholds as $tresh => $val){ 81 if($cnt <= $val){ 82 $tags[$tag] = $tresh; 83 break; 84 } 85 $tags[$tag] = $levels; 86 } 87 } 88 return $tags; 89 } 90 91 public function html_cloud($tags, $type, $func, $wrap = true, $return = false) { 92 $ret = ''; 93 if ($wrap) $ret .= '<ul class="tagging_cloud clearfix">'; 94 if (count($tags) === 0) { 95 // Produce valid XHTML (ul needs a child) 96 $this->setupLocale(); 97 $ret .= '<li><div class="li">' . $this->lang['js']['no' . $type . 's'] . '</div></li>'; 98 } else { 99 $tags = $this->cloudData($tags); 100 foreach ($tags as $val => $size) { 101 $ret .= '<li class="t' . $size . '"><div class="li">'; 102 $ret .= call_user_func($func, $val); 103 $ret .= '</div></li>'; 104 } 105 } 106 if ($wrap) $ret .= '</ul>'; 107 if ($return) return $ret; 108 echo $ret; 109 } 110 111 private function linkToSearch($tag) { 112 return '<a href="' . hsc($this->getTagSearchURL($tag)) . '">' . 113 $tag . '</a>'; 114 } 115 116 public function tpl_tags() { 117 global $ID; 118 global $INFO; 119 global $lang; 120 $tags = $this->getTags(array('pid' => $ID), 'tag'); 121 $this->html_cloud($tags, 'tag', array($this, 'linkToSearch')); 122 123 if (isset($_SERVER['REMOTE_USER']) && $INFO['writable']) { 124 $lang['btn_tagging_edit'] = $lang['btn_secedit']; 125 echo html_btn('tagging_edit', $ID, '', array()); 126 $form = new Doku_Form(array('id' => 'tagging_edit', 'style' => 'display: none;')); 127 $form->addHidden('id', $ID); 128 $form->addElement(form_makeTextField('tags', implode(', ', array_keys($this->getTags(array('pid' => $ID, 'tagger' => $_SERVER['REMOTE_USER']), 'tag'))))); 129 $form->addElement(form_makeButton('submit', 'save', $lang['btn_save'], array('id' => 'tagging_edit_save'))); 130 $form->addElement(form_makeButton('submit', 'cancel', $lang['btn_cancel'], array('id' => 'tagging_edit_cancel'))); 131 $form->printForm(); 132 } 133 } 134} 135