1<?php
2
3if(!defined('DOKU_INC')) die();
4
5class helper_plugin_labeled extends DokuWiki_Plugin {
6
7    private $labels = null;
8    private $lang_translation = null;
9
10    function __construct() {
11        global $conf;
12        if (isset($conf['lang'])) {
13            $path = DOKU_INC.'conf/lang/'.$conf['lang'].'/labeled.php';
14            if (file_exists($path)) {
15                @include($path);
16                $this->lang_translation = $lang;
17            }
18        }
19    }
20
21    function getDB() {
22        static $db;
23        if (!is_null($db)) {
24            return $db;
25        }
26
27        $db = plugin_load('helper', 'sqlite');
28        if (is_null($db)) {
29            msg('The labeled plugin needs the sqlite plugin', -1);
30            return false;
31        }
32        if($db->init('labeled', dirname(__FILE__).'/db/')){
33            return $db;
34        }
35        return false;
36    }
37
38    public function tpl_labels() {
39        global $ID;
40        $all = $this->getAllLabels();
41        if (count($all) === 0) return false;
42        $current = $this->getLabels($ID);
43        $result = '';
44        $result .=  '<div class="plugin_labeled"><ul>';
45
46        $edit = auth_quickaclcheck($ID) >= AUTH_EDIT;
47        foreach ($all as $label => $opts) {
48
49            $active = in_array($label, $current);
50
51            $color = ($active)?$opts['color']:'aaa';
52
53            $result .=  '<li class="labeled_'.($active?'':'in').'active" style="border-color:'.$color.';background-color:'.$color.'">';
54            if ($edit) {
55                $link = wl($ID,
56                    array(
57                        'do' => 'labeled',
58                        action_plugin_labeled_change::$act => $active?'remove':'add',
59                        'label' => $label
60                    )
61                );
62                $title = '';
63                $result .= sprintf('<a href="%s" title="%s">', $link, $title);
64            }
65            $result .=  hsc((isset($this->lang_translation[$label])) ? $this->lang_translation[$label] : $label);
66
67            if ($edit) $result .=  '</a>';
68            $result .=  '</li>';
69        }
70
71        $result .=  '</ul></div>';
72        return $result;
73    }
74
75    /**
76     * parse a string of tags.
77     * @param string $tags
78     * @return array single tags as array.
79     * FIXME can be deleted?
80     */
81    public function parseLabels($labels) {
82        $labels = explode(',', $labels);
83        foreach ($lables as &$label) {
84            $label = trim($label);
85        }
86        return $labels;
87    }
88
89    public function setLabels($labels, $id) {
90        if (auth_quickaclcheck($id) < AUTH_EDIT) {
91            return false;
92        }
93
94        $this->deleteLabels($id);
95
96        $db = $this->getDb();
97        foreach ($labels as $label) {
98            if (!$this->labelExists($label)) continue;
99            $db->query('INSERT INTO labeled (id, label) VALUES (?,?)', $id, $label);
100        }
101    }
102
103    public function changeColor($label, $newColor) {
104        global $INFO;
105        if (!$INFO['isadmin']) return;
106
107        $db = $this->getDb();
108        $db->query('UPDATE labels SET color=? WHERE name=?', $newColor, $label);
109    }
110
111    /**
112     * remove a label form a page
113     * @param string $label label to remove
114     * @param string $id    wiki page id
115     */
116    public function removeLabel($label, $id) {
117        if (auth_quickaclcheck($id) < AUTH_EDIT) {
118            return false;
119        }
120        $db = $this->getDb();
121        $db->query('DELETE FROM labeled WHERE id=? AND label=?', $id, $label);
122    }
123
124    /**
125     * delete all labels from a wikipage
126     * @param string $id the wikipage
127     * @return void
128     */
129    private function deleteLabels($id) {
130        if (auth_quickaclcheck($id) < AUTH_EDIT) {
131            return false;
132        }
133
134        $db = $this->getDb();
135        $db->query('DELETE FROM labeled WHERE id=?', $id);
136    }
137
138    /**
139     * add a single label to a wiki page
140     * @param string $label
141     * @param string $id wiki page
142     * @return void
143     */
144    public function addLabel($label, $id) {
145        $labels = $this->getLabels($id);
146        $labels[] = $label;
147        $labels = array_unique($labels);
148
149        $this->setLabels($labels, $id);
150    }
151
152    /**
153     * rename a label
154     * @param string $label old label name
155     * @param string $newLabel new label name
156     */
157    public function renameLabel($label, $newName) {
158        global $INFO;
159        if (!$INFO['isadmin']) return;
160
161        if (!$this->labelExists($label)) return;
162        $db = $this->getDb();
163        $db->query('UPDATE labels set name=? WHERE name=?', $newName, $label);
164        $db->query('UPDATE labeled set label=? WHERE label=?', $newName, $label);
165
166    }
167
168    /**
169     * get all labels
170     * @param string $id from wiki page id
171     * @return array list of all labels
172     */
173    public function getLabels($id) {
174        if (auth_quickaclcheck($id) < AUTH_READ) {
175            return false;
176        }
177
178        $db = $this->getDb();
179        $res = $db->query('SELECT label FROM labeled WHERE id=?', $id);
180
181        $labels = $db->res2arr($res);
182        $result = array();
183        foreach ($labels as $label) {
184            $result[] = $label['label'];
185        }
186        return $result;
187    }
188
189    /**
190     * check if a label exists
191     * @param string $label label to check
192     * @return boolean true if exists
193     */
194    public function labelExists($label) {
195        $labels = $this->getAllLabels();
196        return isset($labels[$label]);
197    }
198
199    /**
200     * @return array get an array of all available labels
201     * @param boolean $reload on true force a reload
202     */
203    public function getAllLabels($reload = false) {
204        if ($this->labels !== null && !$reload) return $this->labels;
205
206        $db = $this->getDb();
207        $res = $db->query('SELECT name, color, namespace, ordernr FROM labels ORDER BY ordernr');
208
209        $labels = $db->res2arr($res);
210
211        $this->labels = array();
212        foreach ($labels as $label) {
213            $this->labels[$label['name']] = $label;
214        }
215
216        return $this->labels;
217    }
218
219    /**
220     * Change the order of the labels
221     *
222     * @param string $name label name to change
223     * @param float $order ordering number
224     */
225    public function changeOrder($name, $order) {
226        global $INFO;
227        if (!$INFO['isadmin']) return;
228        if ($order === '') $order = 2147483647;
229        $db = $this->getDb();
230
231        $labels = $this->getAllLabels(true);
232        $labels[$name]['ordernr'] = $order;
233        uasort($labels, array($this, 'cmpOrder'));
234
235        $keys = array_keys($labels);
236        $kc = count($keys);
237        for ($i=0; $i<$kc; $i++) {
238            if ($labels[$keys[$i]]['ordernr'] == ($i+1)) {
239                continue;
240            }
241            $labels[$keys[$i]]['ordernr'] = $i+1;
242            $db->query('UPDATE labels SET ordernr=? WHERE name=?', ($i+1), $keys[$i]);
243        }
244        $this->getAllLabels(true);
245    }
246
247    public function cmpOrder($a, $b) {
248        if ($a['ordernr'] == $b['ordernr']) return 0;
249        return ($a['ordernr'] > $b['ordernr']) ? 1 : -1;
250    }
251
252    /**
253     * create a new label
254     * @param string $name   new name of the label
255     * @param string $color  hex color of the label
256     * @param boolean $order Ordering number
257     * @param string $ns     namespace filter for the label
258     */
259    public function createLabel($name, $color, $order = false, $ns = '') {
260        global $INFO;
261        if (!$INFO['isadmin']) return;
262
263        if ($this->labelExists($name)) return;
264
265        $ns = cleanID($ns);
266        $db = $this->getDb();
267        $db->query('INSERT INTO labels (name, color, namespace) VALUES (?,?,?)', $name, $color, $ns);
268    }
269
270    /**
271     * delete a label (and all uses of it)
272     * @param string $label label to delete
273     */
274    public function deleteLabel($label) {
275        global $INFO;
276        if (!$INFO['isadmin']) return;
277
278        $db = $this->getDb();
279        $db->query('DELETE FROM labels WHERE name=?', $label);
280        $db->query('DELETE FROM labeled WHERE label=?', $label);
281    }
282}
283