@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 PhabricatorFileSearchEngine
4 extends PhabricatorApplicationSearchEngine {
5
6 public function getResultTypeDescription() {
7 return pht('Files');
8 }
9
10 public function getApplicationClassName() {
11 return PhabricatorFilesApplication::class;
12 }
13
14 public function canUseInPanelContext() {
15 return false;
16 }
17
18 public function newQuery() {
19 $query = new PhabricatorFileQuery();
20 $query->withIsDeleted(false);
21 return $query;
22 }
23
24 protected function buildCustomSearchFields() {
25 return array(
26 id(new PhabricatorUsersSearchField())
27 ->setKey('authorPHIDs')
28 ->setAliases(array('author', 'authors'))
29 ->setLabel(pht('Authors'))
30 ->setDescription(
31 pht('Search for objects created by specific authors.')),
32 id(new PhabricatorSearchThreeStateField())
33 ->setKey('explicit')
34 ->setLabel(pht('Upload Source'))
35 ->setDescription(
36 pht('Search for files which were explicitly uploaded.'))
37 ->setOptions(
38 pht('(Show All)'),
39 pht('Show Only Manually Uploaded Files'),
40 pht('Hide Manually Uploaded Files')),
41 id(new PhabricatorSearchDateField())
42 ->setKey('createdStart')
43 ->setLabel(pht('Created After'))
44 ->setDescription(
45 pht('Search for files created after a certain date.')),
46 id(new PhabricatorSearchDateField())
47 ->setKey('createdEnd')
48 ->setLabel(pht('Created Before'))
49 ->setDescription(
50 pht('Search for files created before a certain date.')),
51 id(new PhabricatorSearchTextField())
52 ->setLabel(pht('Name Contains'))
53 ->setKey('name')
54 ->setDescription(pht('Search for files by name substring.')),
55 );
56 }
57
58 protected function getDefaultFieldOrder() {
59 return array(
60 '...',
61 'createdStart',
62 'createdEnd',
63 );
64 }
65
66 protected function buildQueryFromParameters(array $map) {
67 $query = $this->newQuery();
68
69 if ($map['authorPHIDs']) {
70 $query->withAuthorPHIDs($map['authorPHIDs']);
71 }
72
73 if ($map['explicit'] !== null) {
74 $query->showOnlyExplicitUploads($map['explicit']);
75 }
76
77 if ($map['createdStart']) {
78 $query->withDateCreatedAfter($map['createdStart']);
79 }
80
81 if ($map['createdEnd']) {
82 $query->withDateCreatedBefore($map['createdEnd']);
83 }
84
85 if ($map['name'] !== null) {
86 $query->withNameNgrams($map['name']);
87 }
88
89 return $query;
90 }
91
92 protected function getURI($path) {
93 return '/file/'.$path;
94 }
95
96 protected function getBuiltinQueryNames() {
97 $names = array();
98
99 if ($this->requireViewer()->isLoggedIn()) {
100 $names['authored'] = pht('Authored');
101 }
102
103 $names += array(
104 'all' => pht('All'),
105 );
106
107 return $names;
108 }
109
110 public function buildSavedQueryFromBuiltin($query_key) {
111 $query = $this->newSavedQuery();
112 $query->setQueryKey($query_key);
113
114 switch ($query_key) {
115 case 'all':
116 return $query;
117 case 'authored':
118 $author_phid = array($this->requireViewer()->getPHID());
119 return $query
120 ->setParameter('authorPHIDs', $author_phid)
121 ->setParameter('explicit', true);
122 }
123
124 return parent::buildSavedQueryFromBuiltin($query_key);
125 }
126
127 protected function getRequiredHandlePHIDsForResultList(
128 array $files,
129 PhabricatorSavedQuery $query) {
130
131 // Remove non-manually created files which do not have an author
132 return mpull(mfilter($files, 'getAuthorPHID'), 'getAuthorPHID');
133 }
134
135 /**
136 * @param array<PhabricatorFile> $files
137 * @param PhabricatorSavedQuery $query
138 * @param array<PhabricatorObjectHandle> $handles
139 */
140 protected function renderResultList(
141 array $files,
142 PhabricatorSavedQuery $query,
143 array $handles) {
144
145 assert_instances_of($files, PhabricatorFile::class);
146
147 $request = $this->getRequest();
148 if ($request) {
149 $highlighted_ids = $request->getStrList('h');
150 } else {
151 $highlighted_ids = array();
152 }
153
154 $viewer = $this->requireViewer();
155
156 $highlighted_ids = array_fill_keys($highlighted_ids, true);
157
158 $list_view = id(new PHUIObjectItemListView())
159 ->setUser($viewer);
160
161 foreach ($files as $file) {
162 $id = $file->getID();
163 $phid = $file->getPHID();
164 $name = $file->getName();
165 $file_uri = $this->getApplicationURI("/info/{$phid}/");
166
167 $date_created = phabricator_datetime($file->getDateCreated(), $viewer);
168 $author_phid = $file->getAuthorPHID();
169 if ($author_phid) {
170 $author_link = $handles[$author_phid]->renderLink();
171 $uploaded = pht('Uploaded by %s on %s', $author_link, $date_created);
172 } else {
173 $uploaded = pht('Uploaded on %s', $date_created);
174 }
175
176 $item = id(new PHUIObjectItemView())
177 ->setObject($file)
178 ->setObjectName("F{$id}")
179 ->setHeader($name)
180 ->setHref($file_uri)
181 ->addAttribute($uploaded)
182 ->addIcon('none', phutil_format_bytes($file->getByteSize()));
183
184 $ttl = $file->getTTL();
185 if ($ttl !== null) {
186 $item->addIcon('blame', pht('Temporary'));
187 }
188
189 if ($file->getIsPartial()) {
190 $item->addIcon('fa-exclamation-triangle orange', pht('Partial'));
191 }
192
193 if (isset($highlighted_ids[$id])) {
194 $item->setEffect('highlighted');
195 }
196
197 $list_view->addItem($item);
198 }
199
200 $list_view->appendChild(id(new PhabricatorGlobalUploadTargetView())
201 ->setUser($viewer));
202
203
204 $result = new PhabricatorApplicationSearchResultView();
205 $result->setContent($list_view);
206
207 return $result;
208 }
209
210 protected function getNewUserBody() {
211 $create_button = id(new PHUIButtonView())
212 ->setTag('a')
213 ->setText(pht('Upload a File'))
214 ->setHref('/file/upload/')
215 ->setColor(PHUIButtonView::GREEN);
216
217 $icon = $this->getApplication()->getIcon();
218 $app_name = $this->getApplication()->getName();
219 $view = id(new PHUIBigInfoView())
220 ->setIcon($icon)
221 ->setTitle(pht('Welcome to %s', $app_name))
222 ->setDescription(
223 pht('Just a place for files.'))
224 ->addAction($create_button);
225
226 return $view;
227 }
228
229}