@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 PhabricatorSearchHovercardController
4 extends PhabricatorSearchBaseController {
5
6 public function shouldAllowPublic() {
7 return true;
8 }
9
10 public function handleRequest(AphrontRequest $request) {
11 $viewer = $this->getViewer();
12
13 $cards = $request->getJSONMap('cards');
14
15 // If object names are provided, look them up and pretend they were
16 // passed as additional PHIDs. This is primarily useful for debugging,
17 // since you don't have to go look up user PHIDs to preview their
18 // hovercards.
19 $names = $request->getStrList('names');
20 if ($names) {
21 $named_objects = id(new PhabricatorObjectQuery())
22 ->setViewer($viewer)
23 ->withNames($names)
24 ->execute();
25
26 foreach ($named_objects as $object) {
27 $cards[] = array(
28 'objectPHID' => $object->getPHID(),
29 );
30 }
31 }
32
33 $object_phids = array();
34 $handle_phids = array();
35 $context_phids = array();
36 foreach ($cards as $card) {
37 if (!is_array($card)) { // ignore external fuzzing noise
38 $card = array();
39 }
40 $object_phid = idx($card, 'objectPHID');
41
42 $handle_phids[] = $object_phid;
43 $object_phids[] = $object_phid;
44
45 $context_phid = idx($card, 'contextPHID');
46
47 if ($context_phid) {
48 $object_phids[] = $context_phid;
49 $context_phids[] = $context_phid;
50 }
51 }
52
53 $handles = id(new PhabricatorHandleQuery())
54 ->setViewer($viewer)
55 ->withPHIDs($handle_phids)
56 ->execute();
57
58 $objects = id(new PhabricatorObjectQuery())
59 ->setViewer($viewer)
60 ->withPHIDs($object_phids)
61 ->execute();
62 $objects = mpull($objects, null, 'getPHID');
63
64 $context_objects = array_select_keys($objects, $context_phids);
65
66 if ($context_objects) {
67 PhabricatorPolicyFilterSet::loadHandleViewCapabilities(
68 $viewer,
69 $handles,
70 $context_objects);
71 }
72
73 $extensions =
74 PhabricatorHovercardEngineExtension::getAllEnabledExtensions();
75
76 $extension_maps = array();
77 foreach ($extensions as $extension_key => $extension) {
78 $extension->setViewer($viewer);
79
80 $extension_phids = array();
81 foreach ($objects as $phid => $object) {
82 if ($extension->canRenderObjectHovercard($object)) {
83 $extension_phids[$phid] = $phid;
84 }
85 }
86
87 $extension_maps[$extension_key] = $extension_phids;
88 }
89
90 $extension_data = array();
91 foreach ($extensions as $extension_key => $extension) {
92 $extension_phids = $extension_maps[$extension_key];
93 if (!$extension_phids) {
94 unset($extensions[$extension_key]);
95 continue;
96 }
97
98 $extension_data[$extension_key] = $extension->willRenderHovercards(
99 array_select_keys($objects, $extension_phids));
100 }
101
102 $results = array();
103 foreach ($cards as $card_key => $card) {
104 if (!is_array($card)) { // ignore external fuzzing noise
105 $card = array();
106 }
107 $object_phid = idx($card, 'objectPHID');
108
109 $handle = $handles[$object_phid];
110 $object = idx($objects, $object_phid);
111
112 $context_phid = idx($card, 'contextPHID');
113 if ($context_phid) {
114 $context_object = idx($context_objects, $context_phid);
115 } else {
116 $context_object = null;
117 }
118
119 $hovercard = id(new PHUIHovercardView())
120 ->setUser($viewer)
121 ->setObjectHandle($handle);
122
123 if ($context_object) {
124 if ($handle->hasCapabilities()) {
125 if (!$handle->hasViewCapability($context_object)) {
126 $hovercard->setIsExiled(true);
127 }
128 }
129 }
130
131 if ($object) {
132 $hovercard->setObject($object);
133
134 foreach ($extension_maps as $extension_key => $extension_phids) {
135 if (isset($extension_phids[$object_phid])) {
136 $extensions[$extension_key]->renderHovercard(
137 $hovercard,
138 $handle,
139 $object,
140 $extension_data[$extension_key]);
141 }
142 }
143 }
144
145 $results[$card_key] = $hovercard;
146 }
147
148 if ($request->isAjax()) {
149 return id(new AphrontAjaxResponse())->setContent(
150 array(
151 'cards' => $results,
152 ));
153 }
154
155 foreach ($results as $result_key => $hovercard) {
156 $results[$result_key] = phutil_tag('div',
157 array(
158 'class' => 'ml',
159 ),
160 $hovercard);
161 }
162
163 return $this->newPage()
164 ->appendChild($results)
165 ->setShowFooter(false);
166 }
167
168}