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