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