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