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