xref: /plugin/struct/types/User.php (revision a0b3799e3857209811ed06eddf7c60cec2980a26)
1<?php
2namespace dokuwiki\plugin\struct\types;
3
4use dokuwiki\plugin\struct\meta\QueryBuilder;
5use dokuwiki\plugin\struct\meta\StructException;
6use dokuwiki\plugin\struct\meta\ValidationException;
7
8class User extends AbstractMultiBaseType {
9
10    protected $config = array(
11        'existingonly' => true,
12        'autocomplete' => array(
13            'fullname' => true,
14            'mininput' => 2,
15            'maxresult' => 5,
16        ),
17    );
18
19    /**
20     * @param string $rawvalue the user to validate
21     * @return int|string|void
22     */
23    public function validate($rawvalue) {
24        $rawvalue = parent::validate($rawvalue);
25
26        if($this->config['existingonly']) {
27            /** @var \DokuWiki_Auth_Plugin $auth */
28            global $auth;
29            $info = $auth->getUserData($rawvalue, false);
30            if($info === false) throw new ValidationException('User not found', $rawvalue);
31        }
32
33        return $rawvalue;
34    }
35
36    /**
37     * @param string $value the user to display
38     * @param \Doku_Renderer $R
39     * @param string $mode
40     * @return bool
41     */
42    public function renderValue($value, \Doku_Renderer $R, $mode) {
43        if($mode == 'xhtml') {
44            $name = userlink($value);
45            $R->doc .= $name;
46        } else {
47            $name = userlink($value, true);
48            $R->cdata($name);
49        }
50        return true;
51    }
52
53    /**
54     * Autocompletion for user names
55     *
56     * @todo should we have any security mechanism? Currently everybody can look up users
57     * @return array
58     */
59    public function handleAjax() {
60        /** @var \DokuWiki_Auth_Plugin $auth */
61        global $auth;
62        global $INPUT;
63
64        if(!$auth->canDo('getUsers')) {
65            throw new StructException('The user backend can not search for users');
66        }
67
68        // check minimum length
69        $lookup = trim($INPUT->str('search'));
70        if(utf8_strlen($lookup) < $this->config['autocomplete']['mininput']) return array();
71
72        // results wanted?
73        $max = $this->config['autocomplete']['maxresult'];
74        if($max <= 0) return array();
75
76        // find users by login, fill up with names if wanted
77        $logins = (array) $auth->retrieveUsers(0, $max, array('user' => $lookup));
78        if((count($logins) < $max) && $this->config['autocomplete']['fullname']) {
79            $logins = array_merge($logins, (array) $auth->retrieveUsers(0, $max, array('name' => $lookup)));
80        }
81
82        // reformat result for jQuery UI Autocomplete
83        $users = array();
84        foreach($logins as $login => $info) {
85            $users[] = array(
86                'label' => $info['name'] . ' [' . $login . ']',
87                'value' => $login
88            );
89        }
90
91        return $users;
92    }
93
94    /**
95     * When handling `%lasteditor%` get the data from the `titles` table instead the `data_` table.
96     *
97     * @param QueryBuilder $QB
98     * @param string $tablealias
99     * @param string $colname
100     * @param string $alias
101     */
102    public function select(QueryBuilder $QB, $tablealias, $colname, $alias) {
103        if(is_a($this->context,'dokuwiki\plugin\struct\meta\UserColumn')) {
104            $rightalias = $QB->generateTableAlias();
105            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
106            $QB->addSelectStatement("$rightalias.lasteditor", $alias);
107            return;
108        }
109
110        parent::select($QB, $tablealias, $colname, $alias);
111    }
112
113    /**
114     * When sorting `%lasteditor%`, then sort the data from the `titles` table instead the `data_` table.
115     *
116     * @param QueryBuilder $QB
117     * @param string $tablealias
118     * @param string $colname
119     * @param string $order
120     */
121    public function sort(QueryBuilder $QB, $tablealias, $colname, $order) {
122        if(is_a($this->context,'dokuwiki\plugin\struct\meta\UserColumn')) {
123            $rightalias = $QB->generateTableAlias();
124            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
125            $QB->addOrderBy("$rightalias.lasteditor $order");
126            return;
127        }
128
129        $QB->addOrderBy("$tablealias.$colname $order");
130    }
131
132    /**
133     * When using `%lasteditor%`, we need to compare against the `title` table.
134     *
135     * @param QueryBuilder $QB
136     * @param string $tablealias
137     * @param string $colname
138     * @param string $comp
139     * @param string|\string[] $value
140     * @param string $op
141     */
142    public function filter(QueryBuilder $QB, $tablealias, $colname, $comp, $value, $op) {
143        if(is_a($this->context,'dokuwiki\plugin\struct\meta\UserColumn')) {
144            $rightalias = $QB->generateTableAlias();
145            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
146
147            // compare against page and title
148            $sub = $QB->filters()->where($op);
149            $pl = $QB->addValue($value);
150            $sub->whereOr("$rightalias.lasteditor $comp $pl");
151            return;
152        }
153
154        parent::filter($QB, $tablealias, $colname, $comp, $value, $op);
155    }
156
157}
158