@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 PhabricatorFeedSearchEngine
4 extends PhabricatorApplicationSearchEngine {
5
6 public function getResultTypeDescription() {
7 return pht('Feed Stories');
8 }
9
10 public function getApplicationClassName() {
11 return PhabricatorFeedApplication::class;
12 }
13
14 public function newQuery() {
15 return new PhabricatorFeedQuery();
16 }
17
18 protected function shouldShowOrderField() {
19 return false;
20 }
21
22 protected function buildCustomSearchFields() {
23 return array(
24 id(new PhabricatorUsersSearchField())
25 ->setLabel(pht('Include Users'))
26 ->setKey('userPHIDs'),
27 // NOTE: This query is not executed with EdgeLogic, so we can't use
28 // a fancy logical datasource.
29 id(new PhabricatorSearchDatasourceField())
30 ->setDatasource(new PhabricatorProjectDatasource())
31 ->setLabel(pht('Include Projects'))
32 ->setKey('projectPHIDs'),
33 id(new PhabricatorSearchDateControlField())
34 ->setLabel(pht('Occurs After'))
35 ->setKey('rangeStart'),
36 id(new PhabricatorSearchDateControlField())
37 ->setLabel(pht('Occurs Before'))
38 ->setKey('rangeEnd'),
39
40 // NOTE: This is a legacy field retained only for backward
41 // compatibility. If the projects field used EdgeLogic, we could use
42 // `viewerprojects()` to execute an equivalent query.
43 id(new PhabricatorSearchCheckboxesField())
44 ->setKey('viewerProjects')
45 ->setOptions(
46 array(
47 'self' => pht('Include stories about projects I am a member of.'),
48 )),
49 );
50 }
51
52 protected function buildQueryFromParameters(array $map) {
53 $query = $this->newQuery();
54
55 $phids = array();
56 if ($map['userPHIDs']) {
57 $phids += array_fuse($map['userPHIDs']);
58 }
59
60 if ($map['projectPHIDs']) {
61 $phids += array_fuse($map['projectPHIDs']);
62 }
63
64 // NOTE: This value may be `true` for older saved queries, or
65 // `array('self')` for newer ones.
66 $viewer_projects = $map['viewerProjects'];
67 if ($viewer_projects) {
68 $viewer = $this->requireViewer();
69 $projects = id(new PhabricatorProjectQuery())
70 ->setViewer($viewer)
71 ->withMemberPHIDs(array($viewer->getPHID()))
72 ->execute();
73 $phids += array_fuse(mpull($projects, 'getPHID'));
74 }
75
76 if ($phids) {
77 $query->withFilterPHIDs($phids);
78 }
79
80 $range_min = $map['rangeStart'];
81 if ($range_min) {
82 $range_min = $range_min->getEpoch();
83 }
84
85 $range_max = $map['rangeEnd'];
86 if ($range_max) {
87 $range_max = $range_max->getEpoch();
88 }
89
90 if ($range_min && $range_max) {
91 if ($range_min > $range_max) {
92 throw new PhabricatorSearchConstraintException(
93 pht(
94 'The specified "Occurs Before" date is earlier in time than the '.
95 'specified "Occurs After" date, so this query can never match '.
96 'any results.'));
97 }
98 }
99
100 if ($range_min || $range_max) {
101 $query->withEpochInRange($range_min, $range_max);
102 }
103
104 return $query;
105 }
106
107 protected function getURI($path) {
108 return '/feed/'.$path;
109 }
110
111 protected function getBuiltinQueryNames() {
112 $names = array(
113 'all' => pht('All Stories'),
114 );
115
116 if ($this->requireViewer()->isLoggedIn()) {
117 $names['projects'] = pht('Project Tags');
118 }
119
120 return $names;
121 }
122
123 public function buildSavedQueryFromBuiltin($query_key) {
124
125 $query = $this->newSavedQuery();
126 $query->setQueryKey($query_key);
127
128 switch ($query_key) {
129 case 'all':
130 return $query;
131 case 'projects':
132 return $query->setParameter('viewerProjects', array('self'));
133 }
134
135 return parent::buildSavedQueryFromBuiltin($query_key);
136 }
137
138 protected function renderResultList(
139 array $objects,
140 PhabricatorSavedQuery $query,
141 array $handles) {
142
143 $builder = new PhabricatorFeedBuilder($objects);
144
145 if ($this->isPanelContext()) {
146 $builder->setShowHovercards(false);
147 } else {
148 $builder->setShowHovercards(true);
149 }
150
151 $builder->setUser($this->requireViewer());
152 $view = $builder->buildView();
153
154 $list = phutil_tag_div('phabricator-feed-frame', $view);
155
156 $result = new PhabricatorApplicationSearchResultView();
157 $result->setContent($list);
158
159 return $result;
160 }
161
162}