xref: /plugin/tagging/helper.php (revision 7e6afce65988c44cd4f284acac3cd0f37799a14c)
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        $db->init('tagging',dirname(__FILE__).'/db/');
18        return $db;
19    }
20
21    public function replaceTags($id, $user, $tags) {
22        $db = $this->getDB();
23        $db->query('BEGIN TRANSACTION');
24        $queries = array(array('DELETE FROM taggings WHERE pid = ? AND tagger = ?', $id, $user));
25        foreach ($tags as $tag) {
26            $queries[] = array('INSERT INTO taggings (pid, tagger, tag) VALUES(?, ?, ?)', $id, $user, $tag);
27        }
28
29        foreach ($queries as $query) {
30            if (!call_user_func_array(array($db, 'query'), $query)) {
31                $db->query('ROLLBACK TRANSACTION');
32                return false;
33            }
34        }
35        return $db->query('COMMIT TRANSACTION');
36    }
37
38    public function getTags($search, $return) {
39        $where = '1=1';
40        foreach($search as $k => $v) {
41            if ($k === 'tag') {
42                $k = 'UPPER(tag)';
43            }
44
45            if ($this->useLike($v)) {
46                $where .= " AND $k LIKE";
47            } else {
48                $where .= " AND $k =";
49            }
50
51            if ($k === 'UPPER(tag)') {
52                $where .= ' UPPER(?)';
53            } else {
54                $where .= ' ?';
55            }
56        }
57
58        $db = $this->getDB();
59        $res = $db->query('SELECT ' . $return . ', COUNT(*) ' .
60                          'FROM taggings WHERE ' . $where . ' GROUP BY ' . $return .
61                          ' ORDER BY tag',
62                          array_values($search));
63
64        $res = $db->res2arr($res);
65        $ret = array();
66        foreach ($res as $v) {
67            $ret[$v[$return]] = $v['COUNT(*)'];
68        }
69        return $ret;
70    }
71
72    private function useLike($v) {
73        return strpos($v, '%') === 0 || strrpos($v, '%') === strlen($v) - 1;
74    }
75
76    public function getTagSearchURL($tag) {
77        return '?do=search&id=' . $tag . '#' .
78               str_replace(' ', '_', strtolower($this->getLang('search_section_title')));
79    }
80
81    public function cloudData($tags, $levels = 10) {
82        $min = min($tags);
83        $max = max($tags);
84
85        // calculate tresholds
86        $tresholds = array();
87        for($i=0; $i<=$levels; $i++){
88            $tresholds[$i] = pow($max - $min + 1, $i/$levels) + $min - 1;
89        }
90
91        // assign weights
92        foreach($tags as $tag => $cnt){
93            foreach($tresholds as $tresh => $val){
94                if($cnt <= $val){
95                    $tags[$tag] = $tresh;
96                    break;
97                }
98                $tags[$tag] = $levels;
99            }
100        }
101        return $tags;
102    }
103
104    public function html_cloud($tags, $type, $func, $wrap = true, $return = false) {
105        $ret = '';
106        if ($wrap) $ret .= '<ul class="tagging_cloud clearfix">';
107        if (count($tags) === 0) {
108            // Produce valid XHTML (ul needs a child)
109            $this->setupLocale();
110            $ret .= '<li><div class="li">' . $this->lang['js']['no' . $type . 's'] . '</div></li>';
111        } else {
112            $tags = $this->cloudData($tags);
113            foreach ($tags as $val => $size) {
114                $ret .= '<li class="t' . $size . '"><div class="li">';
115                $ret .= call_user_func($func, $val);
116                $ret .= '</div></li>';
117            }
118        }
119        if ($wrap) $ret .= '</ul>';
120        if ($return) return $ret;
121        echo $ret;
122    }
123
124    private function linkToSearch($tag) {
125        return '<a href="' . hsc($this->getTagSearchURL($tag)) . '">' .
126               $tag . '</a>';
127    }
128
129    public function tpl_tags() {
130        global $ID;
131        global $INFO;
132        global $lang;
133        $tags = $this->getTags(array('pid' => $ID), 'tag');
134        $this->html_cloud($tags, 'tag', array($this, 'linkToSearch'));
135
136        if (isset($_SERVER['REMOTE_USER']) && $INFO['writable']) {
137            $lang['btn_tagging_edit'] = $lang['btn_secedit'];
138            echo html_btn('tagging_edit', $ID, '', array());
139            $form = new Doku_Form(array('id' => 'tagging_edit', 'style' => 'display: none;'));
140            $form->addHidden('tagging[id]', $ID);
141            $form->addElement(form_makeTextField('tagging[tags]', implode(', ', array_keys($this->getTags(array('pid' => $ID, 'tagger' => $_SERVER['REMOTE_USER']), 'tag')))));
142            $form->addElement(form_makeButton('submit', 'save', $lang['btn_save'], array('id' => 'tagging_edit_save')));
143            $form->addElement(form_makeButton('submit', 'cancel', $lang['btn_cancel'], array('id' => 'tagging_edit_cancel')));
144            $form->printForm();
145        }
146    }
147
148    public function getAllTags(){
149
150        $db = $this->getDb();
151        $res = $db->query('SELECT pid, tag FROM taggings ORDER BY tag');
152
153        $tags_tmp = $db->res2arr($res);
154        $tags = array();
155        foreach ($tags_tmp as $tag) {
156
157            $tags[$tag['tag']]['pid'][] = $tag['pid'];
158
159            if (isset($tags[$tag['tag']]['count'])) {
160                $tags[$tag['tag']]['count']++;
161            } else {
162                $tags[$tag['tag']]['count'] = 1;
163            }
164        }
165        return $tags;
166    }
167
168    public function renameTag($formerTagName, $newTagName) {
169
170        if(empty($formerTagName) || empty($newTagName)) {
171            return "admin enter tag names";
172        }
173
174        $db = $this->getDb();
175
176        $res = $db->query('SELECT pid FROM taggings WHERE tag="'. $formerTagName .'"');
177        $check = $db->res2arr($res);
178
179        if (empty($check)) {
180            return "admin tag does not exists";
181        }
182
183        $res = $db->query("UPDATE taggings SET tag='".$newTagName."' WHERE tag='" . $formerTagName . "'");
184        $db->res2arr($res);
185
186        return "admin saved";
187    }
188
189}
190