@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 PonderQuestionSearchEngine
4 extends PhabricatorApplicationSearchEngine {
5
6 public function getResultTypeDescription() {
7 return pht('Ponder Questions');
8 }
9
10 public function getApplicationClassName() {
11 return PhabricatorPonderApplication::class;
12 }
13
14 public function newQuery() {
15 return id(new PonderQuestionQuery())
16 ->needProjectPHIDs(true);
17 }
18
19 protected function buildQueryFromParameters(array $map) {
20 $query = $this->newQuery();
21
22 if ($map['authorPHIDs']) {
23 $query->withAuthorPHIDs($map['authorPHIDs']);
24 }
25
26 if ($map['answerers']) {
27 $query->withAnswererPHIDs($map['answerers']);
28 }
29
30 if ($map['statuses']) {
31 $query->withStatuses($map['statuses']);
32 }
33
34 return $query;
35 }
36
37 protected function buildCustomSearchFields() {
38 return array(
39 id(new PhabricatorUsersSearchField())
40 ->setKey('authorPHIDs')
41 ->setAliases(array('authors'))
42 ->setLabel(pht('Authors')),
43 id(new PhabricatorUsersSearchField())
44 ->setKey('answerers')
45 ->setAliases(array('answerers'))
46 ->setLabel(pht('Answered By')),
47 id(new PhabricatorSearchCheckboxesField())
48 ->setLabel(pht('Status'))
49 ->setKey('statuses')
50 ->setOptions(PonderQuestionStatus::getQuestionStatusMap()),
51 );
52 }
53
54 protected function getURI($path) {
55 return '/ponder/'.$path;
56 }
57
58 protected function getBuiltinQueryNames() {
59 $names = array(
60 'recent' => pht('Recent Questions'),
61 'open' => pht('Open Questions'),
62 'resolved' => pht('Resolved Questions'),
63 'all' => pht('All Questions'),
64 );
65
66 if ($this->requireViewer()->isLoggedIn()) {
67 $names['authored'] = pht('Authored');
68 $names['answered'] = pht('Answered');
69 }
70
71 return $names;
72 }
73
74 public function buildSavedQueryFromBuiltin($query_key) {
75 $query = $this->newSavedQuery();
76 $query->setQueryKey($query_key);
77
78 switch ($query_key) {
79 case 'all':
80 return $query;
81 case 'open':
82 return $query->setParameter(
83 'statuses', array(PonderQuestionStatus::STATUS_OPEN));
84 case 'recent':
85 return $query->setParameter(
86 'statuses', array(
87 PonderQuestionStatus::STATUS_OPEN,
88 PonderQuestionStatus::STATUS_CLOSED_RESOLVED,
89 ));
90 case 'resolved':
91 return $query->setParameter(
92 'statuses', array(PonderQuestionStatus::STATUS_CLOSED_RESOLVED));
93 case 'authored':
94 return $query->setParameter(
95 'authorPHIDs',
96 array($this->requireViewer()->getPHID()));
97 case 'answered':
98 return $query->setParameter(
99 'answerers',
100 array($this->requireViewer()->getPHID()));
101 }
102
103 return parent::buildSavedQueryFromBuiltin($query_key);
104 }
105
106 protected function getRequiredHandlePHIDsForResultList(
107 array $questions,
108 PhabricatorSavedQuery $query) {
109 return mpull($questions, 'getAuthorPHID');
110 }
111
112 /**
113 * @param array<PonderQuestion> $questions
114 * @param PhabricatorSavedQuery $query
115 * @param array<PhabricatorObjectHandle> $handles
116 */
117 protected function renderResultList(
118 array $questions,
119 PhabricatorSavedQuery $query,
120 array $handles) {
121 assert_instances_of($questions, PonderQuestion::class);
122
123 $viewer = $this->requireViewer();
124
125 $proj_phids = array();
126 foreach ($questions as $question) {
127 foreach ($question->getProjectPHIDs() as $project_phid) {
128 $proj_phids[] = $project_phid;
129 }
130 }
131
132 $proj_handles = id(new PhabricatorHandleQuery())
133 ->setViewer($viewer)
134 ->withPHIDs($proj_phids)
135 ->execute();
136
137 $view = id(new PHUIObjectItemListView())
138 ->setUser($viewer);
139
140 foreach ($questions as $question) {
141 $color = PonderQuestionStatus::getQuestionStatusTagColor(
142 $question->getStatus());
143 $icon = PonderQuestionStatus::getQuestionStatusIcon(
144 $question->getStatus());
145 $full_status = PonderQuestionStatus::getQuestionStatusFullName(
146 $question->getStatus());
147 $item = new PHUIObjectItemView();
148 $item->setObjectName('Q'.$question->getID());
149 $item->setHeader($question->getTitle());
150 $item->setHref('/Q'.$question->getID());
151 $item->setObject($question);
152 $item->setStatusIcon($icon.' '.$color, $full_status);
153
154 $project_handles = array_select_keys(
155 $proj_handles,
156 $question->getProjectPHIDs());
157
158 $created_date = phabricator_date($question->getDateCreated(), $viewer);
159 $item->addIcon('none', $created_date);
160 $item->addByline(
161 pht(
162 'Asked by %s',
163 $handles[$question->getAuthorPHID()]->renderLink()));
164
165 // Render Closed Questions as striked in query results
166 $item->setDisabled($question->isStatusClosed());
167
168 $item->addAttribute(
169 pht(
170 '%s Answer(s)',
171 new PhutilNumber($question->getAnswerCount())));
172
173 if ($project_handles) {
174 $item->addAttribute(
175 id(new PHUIHandleTagListView())
176 ->setLimit(4)
177 ->setSlim(true)
178 ->setHandles($project_handles));
179 }
180
181 $view->addItem($item);
182 }
183
184 $result = new PhabricatorApplicationSearchResultView();
185 $result->setObjectList($view);
186 $result->setNoDataString(pht('No questions found.'));
187
188 return $result;
189 }
190
191 protected function getNewUserBody() {
192 $create_button = id(new PHUIButtonView())
193 ->setTag('a')
194 ->setText(pht('Ask a Question'))
195 ->setHref('/ponder/question/create/')
196 ->setColor(PHUIButtonView::GREEN);
197
198 $icon = $this->getApplication()->getIcon();
199 $app_name = $this->getApplication()->getName();
200 $view = id(new PHUIBigInfoView())
201 ->setIcon($icon)
202 ->setTitle(pht('Welcome to %s', $app_name))
203 ->setDescription(
204 pht('A simple questions and answers application for your teams.'))
205 ->addAction($create_button);
206
207 return $view;
208 }
209
210}