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