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