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