@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
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}