@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
3final class DiffusionSymbolController extends DiffusionController {
4
5 public function handleRequest(AphrontRequest $request) {
6 $viewer = $this->getViewer();
7
8 // See T13638 for discussion of escaping.
9 $name = $request->getURIData('name');
10 $name = phutil_unescape_uri_path_component($name);
11
12 $query = id(new DiffusionSymbolQuery())
13 ->setViewer($viewer)
14 ->setName($name);
15
16 if ($request->getStr('context')) {
17 $query->setContext($request->getStr('context'));
18 }
19
20 if ($request->getStr('type')) {
21 $query->setType($request->getStr('type'));
22 }
23
24 if ($request->getStr('lang')) {
25 $query->setLanguage($request->getStr('lang'));
26 }
27
28 $repos = array();
29 if ($request->getStr('repositories')) {
30 $phids = $request->getStr('repositories');
31 $phids = explode(',', $phids);
32 $phids = array_filter($phids);
33
34 if ($phids) {
35 $repos = id(new PhabricatorRepositoryQuery())
36 ->setViewer($request->getUser())
37 ->withPHIDs($phids)
38 ->execute();
39
40 $repo_phids = mpull($repos, 'getPHID');
41 if ($repo_phids) {
42 $query->withRepositoryPHIDs($repo_phids);
43 }
44 }
45 }
46
47 $query->needPaths(true);
48 $query->needRepositories(true);
49
50 $symbols = $query->execute();
51
52 $external_query = id(new DiffusionExternalSymbolQuery())
53 ->withNames(array($name));
54
55 if ($request->getStr('context')) {
56 $external_query->withContexts(array($request->getStr('context')));
57 }
58
59 if ($request->getStr('type')) {
60 $external_query->withTypes(array($request->getStr('type')));
61 }
62
63 if ($request->getStr('lang')) {
64 $external_query->withLanguages(array($request->getStr('lang')));
65 }
66
67 if ($request->getStr('path')) {
68 $external_query->withPaths(array($request->getStr('path')));
69 }
70
71 if ($request->getInt('line')) {
72 $external_query->withLines(array($request->getInt('line')));
73 }
74
75 if ($request->getInt('char')) {
76 $external_query->withCharacterPositions(
77 array(
78 $request->getInt('char'),
79 ));
80 }
81
82 if ($repos) {
83 $external_query->withRepositories($repos);
84 }
85
86 $external_sources = id(new PhutilClassMapQuery())
87 ->setAncestorClass(DiffusionExternalSymbolsSource::class)
88 ->execute();
89
90 $results = array($symbols);
91 foreach ($external_sources as $source) {
92 $source_results = $source->executeQuery($external_query);
93
94 if (!is_array($source_results)) {
95 throw new Exception(
96 pht(
97 'Expected a list of results from external symbol source "%s".',
98 get_class($source)));
99 }
100
101 try {
102 assert_instances_of(
103 $source_results,
104 PhabricatorRepositorySymbol::class);
105 } catch (InvalidArgumentException $ex) {
106 throw new Exception(
107 pht(
108 'Expected a list of PhabricatorRepositorySymbol objects '.
109 'from external symbol source "%s".',
110 get_class($source)));
111 }
112
113 $results[] = $source_results;
114 }
115 $symbols = array_mergev($results);
116
117 if ($request->getBool('jump') && count($symbols) == 1) {
118 // If this is a clickthrough from Differential, just jump them
119 // straight to the target if we got a single hit.
120 $symbol = head($symbols);
121 return id(new AphrontRedirectResponse())
122 ->setIsExternal($symbol->isExternal())
123 ->setURI($symbol->getURI());
124 }
125
126 $rows = array();
127 foreach ($symbols as $symbol) {
128 $href = $symbol->getURI();
129
130 if ($symbol->isExternal()) {
131 $source = $symbol->getSource();
132 $location = $symbol->getLocation();
133 } else {
134 $repo = $symbol->getRepository();
135 $file = $symbol->getPath();
136 $line = $symbol->getLineNumber();
137
138 $source = $repo->getMonogram();
139 $location = $file.':'.$line;
140 }
141 $location = phutil_tag(
142 'a',
143 array(
144 'href' => $href,
145 ),
146 $location);
147
148 $rows[] = array(
149 $symbol->getSymbolType(),
150 $symbol->getSymbolContext(),
151 $symbol->getSymbolName(),
152 $symbol->getSymbolLanguage(),
153 $source,
154 $location,
155 );
156 }
157
158 $table = new AphrontTableView($rows);
159 $table->setHeaders(
160 array(
161 pht('Type'),
162 pht('Context'),
163 pht('Name'),
164 pht('Language'),
165 pht('Source'),
166 pht('Location'),
167 ));
168 $table->setColumnClasses(
169 array(
170 '',
171 '',
172 'pri',
173 '',
174 '',
175 '',
176 ));
177 $table->setNoDataString(
178 pht('No matching symbol could be found in any indexed repository.'));
179
180 $header = id(new PHUIHeaderView())
181 ->setHeader(pht('Similar Symbols'))
182 ->setHeaderIcon('fa-bullseye');
183
184 $crumbs = $this->buildApplicationCrumbs();
185 $crumbs->addTextCrumb(pht('Find Symbol'));
186 $crumbs->setBorder(true);
187
188 $view = id(new PHUITwoColumnView())
189 ->setHeader($header)
190 ->setFooter(array(
191 $table,
192 ));
193
194 return $this->newPage()
195 ->setTitle(pht('Find Symbol'))
196 ->setCrumbs($crumbs)
197 ->appendChild($view);
198 }
199
200}