@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 286 lines 6.1 kB view raw
1<?php 2 3/** 4 * Query symbol information (class and function names and location), returning 5 * a list of matching @{class:PhabricatorRepositorySymbol} objects and possibly 6 * attached data. 7 * 8 * @task config Configuring the Query 9 * @task exec Executing the Query 10 * @task internal Internals 11 */ 12final class DiffusionSymbolQuery extends PhabricatorOffsetPagedQuery { 13 14 private $viewer; 15 private $context; 16 private $namePrefix; 17 private $name; 18 19 private $repositoryPHIDs; 20 private $language; 21 private $type; 22 23 private $needPaths; 24 private $needRepositories; 25 26 27/* -( Configuring the Query )---------------------------------------------- */ 28 29 /** 30 * @task config 31 */ 32 public function setViewer(PhabricatorUser $viewer) { 33 $this->viewer = $viewer; 34 return $this; 35 } 36 37 /** 38 * @task config 39 */ 40 public function getViewer() { 41 return $this->viewer; 42 } 43 44 /** 45 * @task config 46 */ 47 public function setContext($context) { 48 $this->context = $context; 49 return $this; 50 } 51 52 53 /** 54 * @task config 55 */ 56 public function setName($name) { 57 $this->name = $name; 58 return $this; 59 } 60 61 62 /** 63 * @task config 64 */ 65 public function setNamePrefix($name_prefix) { 66 $this->namePrefix = $name_prefix; 67 return $this; 68 } 69 70 71 /** 72 * @task config 73 */ 74 public function withRepositoryPHIDs(array $repository_phids) { 75 $this->repositoryPHIDs = $repository_phids; 76 return $this; 77 } 78 79 80 /** 81 * @task config 82 */ 83 public function setLanguage($language) { 84 $this->language = $language; 85 return $this; 86 } 87 88 89 /** 90 * @task config 91 */ 92 public function setType($type) { 93 $this->type = $type; 94 return $this; 95 } 96 97 98 /** 99 * @task config 100 */ 101 public function needPaths($need_paths) { 102 $this->needPaths = $need_paths; 103 return $this; 104 } 105 106 107 /** 108 * @task config 109 */ 110 public function needRepositories($need_repositories) { 111 $this->needRepositories = $need_repositories; 112 return $this; 113 } 114 115 116/* -( Specialized Query )-------------------------------------------------- */ 117 118 public function existsSymbolsInRepository($repository_phid) { 119 $this 120 ->withRepositoryPHIDs(array($repository_phid)) 121 ->setLimit(1); 122 123 $symbol = new PhabricatorRepositorySymbol(); 124 $conn_r = $symbol->establishConnection('r'); 125 126 $data = queryfx_all( 127 $conn_r, 128 'SELECT * FROM %T %Q %Q', 129 $symbol->getTableName(), 130 $this->buildWhereClause($conn_r), 131 $this->buildLimitClause($conn_r)); 132 133 return (!empty($data)); 134 } 135 136/* -( Executing the Query )------------------------------------------------ */ 137 138 139 /** 140 * @task exec 141 */ 142 public function execute() { 143 if ($this->name && $this->namePrefix) { 144 throw new Exception( 145 pht('You can not set both a name and a name prefix!')); 146 } else if (!$this->name && !$this->namePrefix) { 147 throw new Exception( 148 pht('You must set a name or a name prefix!')); 149 } 150 151 $symbol = new PhabricatorRepositorySymbol(); 152 $conn_r = $symbol->establishConnection('r'); 153 154 $data = queryfx_all( 155 $conn_r, 156 'SELECT * FROM %T %Q %Q %Q', 157 $symbol->getTableName(), 158 $this->buildWhereClause($conn_r), 159 $this->buildOrderClause($conn_r), 160 $this->buildLimitClause($conn_r)); 161 162 $symbols = $symbol->loadAllFromArray($data); 163 164 if ($symbols) { 165 if ($this->needPaths) { 166 $this->loadPaths($symbols); 167 } 168 if ($this->needRepositories) { 169 $symbols = $this->loadRepositories($symbols); 170 } 171 172 } 173 174 175 return $symbols; 176 } 177 178 179/* -( Internals )---------------------------------------------------------- */ 180 181 182 /** 183 * @task internal 184 */ 185 private function buildOrderClause($conn_r) { 186 return qsprintf( 187 $conn_r, 188 'ORDER BY symbolName ASC'); 189 } 190 191 192 /** 193 * @task internal 194 */ 195 protected function buildWhereClause(AphrontDatabaseConnection $conn) { 196 $where = array(); 197 198 if (isset($this->context)) { 199 $where[] = qsprintf( 200 $conn, 201 'symbolContext = %s', 202 $this->context); 203 } 204 205 if ($this->name) { 206 $where[] = qsprintf( 207 $conn, 208 'symbolName = %s', 209 $this->name); 210 } 211 212 if ($this->namePrefix) { 213 $where[] = qsprintf( 214 $conn, 215 'symbolName LIKE %>', 216 $this->namePrefix); 217 } 218 219 if ($this->repositoryPHIDs) { 220 $where[] = qsprintf( 221 $conn, 222 'repositoryPHID IN (%Ls)', 223 $this->repositoryPHIDs); 224 } 225 226 if ($this->language) { 227 $where[] = qsprintf( 228 $conn, 229 'symbolLanguage = %s', 230 $this->language); 231 } 232 233 if ($this->type) { 234 $where[] = qsprintf( 235 $conn, 236 'symbolType = %s', 237 $this->type); 238 } 239 240 return $this->formatWhereClause($conn, $where); 241 } 242 243 244 /** 245 * @param array<PhabricatorRepositorySymbol> $symbols 246 * @task internal 247 */ 248 private function loadPaths(array $symbols) { 249 assert_instances_of($symbols, PhabricatorRepositorySymbol::class); 250 $path_map = queryfx_all( 251 id(new PhabricatorRepository())->establishConnection('r'), 252 'SELECT * FROM %T WHERE id IN (%Ld)', 253 PhabricatorRepository::TABLE_PATH, 254 mpull($symbols, 'getPathID')); 255 $path_map = ipull($path_map, 'path', 'id'); 256 foreach ($symbols as $symbol) { 257 $symbol->attachPath(idx($path_map, $symbol->getPathID())); 258 } 259 } 260 261 /** 262 * @param array<PhabricatorRepositorySymbol> $symbols 263 * @task internal 264 */ 265 private function loadRepositories(array $symbols) { 266 assert_instances_of($symbols, PhabricatorRepositorySymbol::class); 267 268 $repos = id(new PhabricatorRepositoryQuery()) 269 ->setViewer($this->viewer) 270 ->withPHIDs(mpull($symbols, 'getRepositoryPHID')) 271 ->execute(); 272 $repos = mpull($repos, null, 'getPHID'); 273 274 $visible = array(); 275 foreach ($symbols as $symbol) { 276 $repository = idx($repos, $symbol->getRepositoryPHID()); 277 // repository is null mean "user can't view repo", so hide the symbol 278 if ($repository) { 279 $symbol->attachRepository($repository); 280 $visible[] = $symbol; 281 } 282 } 283 return $visible; 284 } 285 286}