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