1<?php
2
3namespace dokuwiki\plugin\bez\struct;
4
5use dokuwiki\plugin\struct\meta\ValidationException;
6use dokuwiki\plugin\struct\types\AbstractMultiBaseType;
7
8class BezType extends AbstractMultiBaseType {
9
10    const BEZ_TABLE_CODES = array(
11        '' => 'thread',
12        'k' => 'thread_comment',
13        'z' => 'task',
14        'zk' => 'task_comment'
15    );
16
17    protected $config = array(
18        'autocomplete' => array(
19            'maxresult' => 10
20        ),
21    );
22
23    /**
24     * Output the stored data
25     *
26     * @param string $value the value stored in the database
27     * @param \Doku_Renderer $R the renderer currently used to render the data
28     * @param string $mode The mode the output is rendered in (eg. XHTML)
29     * @return bool true if $mode could be satisfied
30     */
31    public function renderValue($value, \Doku_Renderer $R, $mode) {
32        preg_match('/#([a-z]*)([0-9]+)/', $value, $matches);
33        list(,$code, $id) = $matches;
34        $title = $value;
35
36        $anchor = '';
37        $id_key = 'id';
38        switch ($code) {
39            case '':
40                $table = 'thread';
41                break;
42            case 'k':
43                $table = 'thread';
44                $anchor = '#k' . $id;
45
46                /** @var helper_plugin_sqlite $sqlite */
47                $sqlite = plugin_load('helper', 'bez_db')->getDB();
48                $res = $sqlite->query("SELECT thread_id FROM thread_comment WHERE id=?", $id);
49                $id = $res->fetchColumn();
50                break;
51            case 'z':
52                $table = 'task';
53                $id_key = 'tid';
54                break;
55            case 'zk':
56                $table = 'task';
57                $id_key = 'tid';
58                $anchor = '#zk' . $id;
59
60                /** @var helper_plugin_sqlite $sqlite */
61                $sqlite = plugin_load('helper', 'bez_db')->getDB();
62                $res = $sqlite->query("SELECT task_id FROM task_comment WHERE id=?", $id);
63                $id = $res->fetchColumn();
64                break;
65        }
66
67        $wl = wl("bez:$table:$id_key:$id") . $anchor;
68        $R->doc .= '<a href="'.$wl.'">'.$title.'</a>';
69
70
71        return true;
72    }
73
74    /**
75     * Cleans the link
76     *
77     * @param string $rawvalue
78     * @return string
79     */
80    public function validate($rawvalue) {
81        preg_match('/#([a-z]*)([0-9]+)/', $rawvalue, $matches);
82        list(,$code, $id) = $matches;
83
84        if (!is_numeric($id)) {
85            throw new ValidationException('Invalid BEZ reference');
86        }
87
88        if (!in_array($code, array_keys(self::BEZ_TABLE_CODES))) {
89                throw new ValidationException('Invalid BEZ reference');
90        }
91
92        $table = self::BEZ_TABLE_CODES[$code];
93
94        /** @var helper_plugin_sqlite $sqlite */
95        $sqlite = plugin_load('helper', 'bez_db')->getDB();
96        $res = $sqlite->query("SELECT COUNT(*) FROM $table WHERE id=?", $id);
97        $count = $res->fetchColumn();
98        if ($count == 0) {
99            throw new ValidationException(ucfirst($table) . " with id: $id doesn't exists.");
100        }
101
102        return $rawvalue;
103    }
104
105    /**
106     * Autocompletion support for pages
107     *
108     * @return array
109     */
110    public function handleAjax() {
111        global $INPUT;
112
113        // check minimum length
114        $lookup = trim($INPUT->str('search'));
115        if(utf8_strlen($lookup) < 1) return array();
116        if ($lookup[0] != '#') return array();
117
118        preg_match('/#([a-z]*)([0-9]+)/', $lookup, $matches);
119        list(,$code, $id) = $matches;
120
121        if (!is_numeric($id)) return array();
122        if (!in_array($code, array_keys(self::BEZ_TABLE_CODES))) return array();
123
124        $table = self::BEZ_TABLE_CODES[$code];
125
126        // results wanted?
127        $max = (int)$this->config['autocomplete']['maxresult'];
128        if($max <= 0) return array();
129
130        $bez_db_helper = plugin_load('helper', 'bez_db');
131
132        /** @var helper_plugin_sqlite $sqlite */
133        $sqlite = $bez_db_helper->getDB();
134
135        $fields = array('id');
136        if ($table == 'thread' || $table == 'task') {
137            $fields[] = 'state';
138        }
139
140        $sql = "SELECT " . implode(',', $fields) . " FROM $table WHERE id LIKE ? LIMIT $max";
141        $res = $sqlite->query($sql, $id . '%');
142
143        $result = array();
144        while ($row = $res->fetch(\PDO::FETCH_ASSOC)) {
145
146            $name = $value = '#' . $code . $row['id'];
147            if ($table == 'thread' || $table == 'task') {
148                $state = $bez_db_helper->getLang('state_' . $row['state']);
149                $name .= ' (' . $state . ')';
150            }
151
152            $result[] = array(
153                'label' => $name,
154                'value' => $value
155            );
156        }
157
158        return $result;
159    }
160}