|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Files_FullTextSearch - Index the content of your files |
|
4
|
|
|
* |
|
5
|
|
|
* This file is licensed under the Affero General Public License version 3 or |
|
6
|
|
|
* later. See the COPYING file. |
|
7
|
|
|
* |
|
8
|
|
|
* @author Maxence Lange <[email protected]> |
|
9
|
|
|
* @copyright 2018 |
|
10
|
|
|
* @license GNU AGPL version 3 or any later version |
|
11
|
|
|
* |
|
12
|
|
|
* This program is free software: you can redistribute it and/or modify |
|
13
|
|
|
* it under the terms of the GNU Affero General Public License as |
|
14
|
|
|
* published by the Free Software Foundation, either version 3 of the |
|
15
|
|
|
* License, or (at your option) any later version. |
|
16
|
|
|
* |
|
17
|
|
|
* This program is distributed in the hope that it will be useful, |
|
18
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
19
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
20
|
|
|
* GNU Affero General Public License for more details. |
|
21
|
|
|
* |
|
22
|
|
|
* You should have received a copy of the GNU Affero General Public License |
|
23
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
24
|
|
|
* |
|
25
|
|
|
*/ |
|
26
|
|
|
|
|
27
|
|
|
namespace OCA\Files_FullTextSearch\Provider; |
|
28
|
|
|
|
|
29
|
|
|
use OCA\Files_FullTextSearch\AppInfo\Application; |
|
30
|
|
|
use OCA\Files_FullTextSearch\Exceptions\FileIsNotIndexableException; |
|
31
|
|
|
use OCA\Files_FullTextSearch\Model\FilesDocument; |
|
32
|
|
|
use OCA\Files_FullTextSearch\Service\ConfigService; |
|
33
|
|
|
use OCA\Files_FullTextSearch\Service\ElasticSearchService; |
|
34
|
|
|
use OCA\Files_FullTextSearch\Service\FilesService; |
|
35
|
|
|
use OCA\Files_FullTextSearch\Service\MiscService; |
|
36
|
|
|
use OCA\Files_FullTextSearch\Service\SearchService; |
|
37
|
|
|
use OCA\FullTextSearch\IFullTextSearchPlatform; |
|
38
|
|
|
use OCA\FullTextSearch\IFullTextSearchProvider; |
|
39
|
|
|
use OCA\FullTextSearch\Model\Index; |
|
40
|
|
|
use OCA\FullTextSearch\Model\IndexDocument; |
|
41
|
|
|
use OCA\FullTextSearch\Model\IndexOptions; |
|
42
|
|
|
use OCA\FullTextSearch\Model\Runner; |
|
43
|
|
|
use OCA\FullTextSearch\Model\SearchRequest; |
|
44
|
|
|
use OCA\FullTextSearch\Model\SearchResult; |
|
45
|
|
|
use OCP\AppFramework\QueryException; |
|
46
|
|
|
use OCP\Files\InvalidPathException; |
|
47
|
|
|
use OCP\Files\NotFoundException; |
|
48
|
|
|
use OCP\Files\NotPermittedException; |
|
49
|
|
|
use OCP\IL10N; |
|
50
|
|
|
|
|
51
|
|
|
class FilesProvider implements IFullTextSearchProvider { |
|
52
|
|
|
|
|
53
|
|
|
|
|
54
|
|
|
const FILES_PROVIDER_ID = 'files'; |
|
55
|
|
|
|
|
56
|
|
|
|
|
57
|
|
|
/** @var IL10N */ |
|
58
|
|
|
private $l10n; |
|
59
|
|
|
|
|
60
|
|
|
/** @var ConfigService */ |
|
61
|
|
|
private $configService; |
|
62
|
|
|
|
|
63
|
|
|
/** @var FilesService */ |
|
64
|
|
|
private $filesService; |
|
65
|
|
|
|
|
66
|
|
|
/** @var SearchService */ |
|
67
|
|
|
private $searchService; |
|
68
|
|
|
|
|
69
|
|
|
/** @var ElasticSearchService */ |
|
70
|
|
|
private $elasticSearchService; |
|
71
|
|
|
|
|
72
|
|
|
/** @var MiscService */ |
|
73
|
|
|
private $miscService; |
|
74
|
|
|
|
|
75
|
|
|
|
|
76
|
|
|
/** @var Runner */ |
|
77
|
|
|
private $runner; |
|
78
|
|
|
|
|
79
|
|
|
/** @var IndexOptions */ |
|
80
|
|
|
private $indexOptions = []; |
|
81
|
|
|
|
|
82
|
|
|
|
|
83
|
|
View Code Duplication |
public function __construct( |
|
|
|
|
|
|
84
|
|
|
IL10N $l10n, ConfigService $configService, FilesService $filesService, |
|
85
|
|
|
SearchService $searchService, ElasticSearchService $elasticSearchService, |
|
86
|
|
|
MiscService $miscService |
|
87
|
|
|
) { |
|
88
|
|
|
$this->l10n = $l10n; |
|
89
|
|
|
$this->configService = $configService; |
|
90
|
|
|
$this->filesService = $filesService; |
|
91
|
|
|
$this->searchService = $searchService; |
|
92
|
|
|
$this->elasticSearchService = $elasticSearchService; |
|
93
|
|
|
$this->miscService = $miscService; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* return unique id of the provider |
|
98
|
|
|
*/ |
|
99
|
|
|
public function getId() { |
|
100
|
|
|
return self::FILES_PROVIDER_ID; |
|
101
|
|
|
} |
|
102
|
|
|
|
|
103
|
|
|
|
|
104
|
|
|
/** |
|
105
|
|
|
* return name of the provider |
|
106
|
|
|
*/ |
|
107
|
|
|
public function getName() { |
|
108
|
|
|
return 'Files'; |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
|
|
112
|
|
|
/** |
|
113
|
|
|
* @deprecated |
|
114
|
|
|
* @return string |
|
115
|
|
|
*/ |
|
116
|
|
|
public function getVersion() { |
|
117
|
|
|
return ''; |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
|
|
121
|
|
|
/** |
|
122
|
|
|
* @return array |
|
123
|
|
|
*/ |
|
124
|
|
|
public function getConfiguration() { |
|
125
|
|
|
return $this->configService->getConfig(); |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* @deprecated |
|
131
|
|
|
* @return string |
|
132
|
|
|
*/ |
|
133
|
|
|
public function getAppId() { |
|
134
|
|
|
return ''; |
|
135
|
|
|
} |
|
136
|
|
|
|
|
137
|
|
|
|
|
138
|
|
|
public function setRunner(Runner $runner) { |
|
139
|
|
|
$this->runner = $runner; |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
|
|
143
|
|
|
/** |
|
144
|
|
|
* @param IndexOptions $options |
|
145
|
|
|
*/ |
|
146
|
|
|
public function setIndexOptions($options) { |
|
147
|
|
|
$this->indexOptions = $options; |
|
148
|
|
|
} |
|
149
|
|
|
|
|
150
|
|
|
|
|
151
|
|
|
/** |
|
152
|
|
|
* @return array |
|
|
|
|
|
|
153
|
|
|
*/ |
|
154
|
|
|
public function getOptionsTemplate() { |
|
155
|
|
|
// 'template' => 'options.panel', |
|
156
|
|
|
return [ |
|
157
|
|
|
'panel' => [ |
|
158
|
|
|
'options' => [ |
|
159
|
|
|
[ |
|
160
|
|
|
'name' => 'files_within_dir', |
|
161
|
|
|
'title' => $this->l10n->t('Within current directory'), |
|
162
|
|
|
'type' => 'checkbox' |
|
163
|
|
|
], |
|
164
|
|
|
[ |
|
165
|
|
|
'name' => 'files_local', |
|
166
|
|
|
'title' => $this->l10n->t('Within local files'), |
|
167
|
|
|
'type' => 'checkbox' |
|
168
|
|
|
], |
|
169
|
|
|
[ |
|
170
|
|
|
'name' => 'files_external', |
|
171
|
|
|
'title' => $this->l10n->t('Within external files'), |
|
172
|
|
|
'type' => 'checkbox' |
|
173
|
|
|
], |
|
174
|
|
|
[ |
|
175
|
|
|
'name' => 'files_group_folders', |
|
176
|
|
|
'title' => $this->l10n->t('Within group folders'), |
|
177
|
|
|
'type' => 'checkbox' |
|
178
|
|
|
], |
|
179
|
|
|
[ |
|
180
|
|
|
'name' => 'files_extension', |
|
181
|
|
|
'title' => $this->l10n->t('Filter by extension'), |
|
182
|
|
|
'type' => 'input', |
|
183
|
|
|
'size' => 'small', |
|
184
|
|
|
'placeholder' => 'txt' |
|
185
|
|
|
] |
|
186
|
|
|
] |
|
187
|
|
|
], |
|
188
|
|
|
'navigation' => [ |
|
189
|
|
|
'icon' => 'icon-fts-files', |
|
190
|
|
|
'options' => [ |
|
191
|
|
|
[ |
|
192
|
|
|
'name' => 'files_local', |
|
193
|
|
|
'title' => $this->l10n->t('Local Files'), |
|
194
|
|
|
'type' => 'checkbox' |
|
195
|
|
|
], |
|
196
|
|
|
[ |
|
197
|
|
|
'name' => 'files_external', |
|
198
|
|
|
'title' => $this->l10n->t('External Files'), |
|
199
|
|
|
'type' => 'checkbox' |
|
200
|
|
|
], |
|
201
|
|
|
[ |
|
202
|
|
|
'name' => 'files_group_folders', |
|
203
|
|
|
'title' => $this->l10n->t('Group Folders'), |
|
204
|
|
|
'type' => 'checkbox' |
|
205
|
|
|
], |
|
206
|
|
|
[ |
|
207
|
|
|
'name' => 'files_extension', |
|
208
|
|
|
'title' => $this->l10n->t('Extension'), |
|
209
|
|
|
'type' => 'input', |
|
210
|
|
|
'size' => 'small', |
|
211
|
|
|
'placeholder' => 'txt' |
|
212
|
|
|
] |
|
213
|
|
|
] |
|
214
|
|
|
] |
|
215
|
|
|
]; |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
|
|
|
|
219
|
|
|
/** |
|
220
|
|
|
* @deprecated |
|
221
|
|
|
*/ |
|
222
|
|
|
public function getOptions() { |
|
223
|
|
|
return $this->getOptionsTemplate(); |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
|
|
227
|
|
|
/** |
|
228
|
|
|
* called when loading all providers. |
|
229
|
|
|
* |
|
230
|
|
|
* Loading some containers. |
|
231
|
|
|
* |
|
232
|
|
|
* @throws QueryException |
|
233
|
|
|
*/ |
|
234
|
|
|
public function loadProvider() { |
|
235
|
|
|
$app = new Application(); |
|
236
|
|
|
|
|
237
|
|
|
$container = $app->getContainer(); |
|
238
|
|
|
$this->configService = $container->query(ConfigService::class); |
|
239
|
|
|
$this->filesService = $container->query(FilesService::class); |
|
240
|
|
|
$this->searchService = $container->query(SearchService::class); |
|
241
|
|
|
$this->elasticSearchService = $container->query(ElasticSearchService::class); |
|
242
|
|
|
$this->miscService = $container->query(MiscService::class); |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
|
|
246
|
|
|
/** |
|
247
|
|
|
* returns all indexable document for a user. |
|
248
|
|
|
* There is no need to fill the document with content at this point. |
|
249
|
|
|
* |
|
250
|
|
|
* $platform is provided if the mapping needs to be changed. |
|
251
|
|
|
* |
|
252
|
|
|
* @param string $userId |
|
253
|
|
|
* |
|
254
|
|
|
* @return IndexDocument[] |
|
|
|
|
|
|
255
|
|
|
* @throws InvalidPathException |
|
256
|
|
|
* @throws NotFoundException |
|
257
|
|
|
*/ |
|
258
|
|
|
public function generateIndexableDocuments($userId) { |
|
259
|
|
|
$files = $this->filesService->getFilesFromUser($userId, $this->indexOptions); |
|
260
|
|
|
|
|
261
|
|
|
return $files; |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
|
|
265
|
|
|
/** |
|
266
|
|
|
* generate documents prior to the indexing. |
|
267
|
|
|
* throw NoResultException if no more result |
|
268
|
|
|
* |
|
269
|
|
|
* @param IndexDocument[] $chunk |
|
270
|
|
|
* |
|
271
|
|
|
* @return IndexDocument[] |
|
272
|
|
|
* @deprecated |
|
273
|
|
|
*/ |
|
274
|
|
|
public function fillIndexDocuments($chunk) { |
|
275
|
|
|
return []; |
|
276
|
|
|
} |
|
277
|
|
|
|
|
278
|
|
|
|
|
279
|
|
|
/** |
|
280
|
|
|
* @param IndexDocument $document |
|
281
|
|
|
*/ |
|
282
|
|
|
public function fillIndexDocument(IndexDocument $document) { |
|
283
|
|
|
/** @var FilesDocument $document */ |
|
284
|
|
|
$this->filesService->generateDocument($document); |
|
285
|
|
|
$this->updateRunnerInfo('info', $document->getMimetype()); |
|
286
|
|
|
} |
|
287
|
|
|
|
|
288
|
|
|
|
|
289
|
|
|
/** |
|
290
|
|
|
* @param IndexDocument $document |
|
291
|
|
|
* |
|
292
|
|
|
* @return bool |
|
293
|
|
|
*/ |
|
294
|
|
|
public function isDocumentUpToDate($document) { |
|
295
|
|
|
return $this->filesService->isDocumentUpToDate($document); |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
|
|
|
|
299
|
|
|
/** |
|
300
|
|
|
* @param Index $index |
|
301
|
|
|
* |
|
302
|
|
|
* @return IndexDocument |
|
|
|
|
|
|
303
|
|
|
* @throws InvalidPathException |
|
304
|
|
|
* @throws NotFoundException |
|
305
|
|
|
* @throws NotPermittedException |
|
306
|
|
|
* @throws FileIsNotIndexableException |
|
307
|
|
|
*/ |
|
308
|
|
|
public function updateDocument(Index $index) { |
|
309
|
|
|
$document = $this->filesService->updateDocument($index); |
|
310
|
|
|
$this->updateRunnerInfo('info', $document->getMimetype()); |
|
311
|
|
|
|
|
312
|
|
|
return $document; |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
|
|
316
|
|
|
/** |
|
317
|
|
|
* @param IFullTextSearchPlatform $platform |
|
318
|
|
|
*/ |
|
319
|
|
|
public function onInitializingIndex(IFullTextSearchPlatform $platform) { |
|
320
|
|
|
$this->elasticSearchService->onInitializingIndex($platform); |
|
321
|
|
|
} |
|
322
|
|
|
|
|
323
|
|
|
|
|
324
|
|
|
/** |
|
325
|
|
|
* @param IFullTextSearchPlatform $platform |
|
326
|
|
|
*/ |
|
327
|
|
|
public function onResettingIndex(IFullTextSearchPlatform $platform) { |
|
328
|
|
|
$this->elasticSearchService->onResettingIndex($platform); |
|
329
|
|
|
} |
|
330
|
|
|
|
|
331
|
|
|
|
|
332
|
|
|
/** |
|
333
|
|
|
* not used yet |
|
334
|
|
|
*/ |
|
335
|
|
|
public function unloadProvider() { |
|
336
|
|
|
} |
|
337
|
|
|
|
|
338
|
|
|
|
|
339
|
|
|
/** |
|
340
|
|
|
* before a search, improve the request |
|
341
|
|
|
* |
|
342
|
|
|
* @param SearchRequest $request |
|
343
|
|
|
*/ |
|
344
|
|
|
public function improveSearchRequest(SearchRequest $request) { |
|
345
|
|
|
$this->searchService->improveSearchRequest($request); |
|
346
|
|
|
} |
|
347
|
|
|
|
|
348
|
|
|
|
|
349
|
|
|
/** |
|
350
|
|
|
* after a search, improve results |
|
351
|
|
|
* |
|
352
|
|
|
* @param SearchResult $searchResult |
|
353
|
|
|
*/ |
|
354
|
|
|
public function improveSearchResult(SearchResult $searchResult) { |
|
355
|
|
|
$this->searchService->improveSearchResult($searchResult); |
|
356
|
|
|
} |
|
357
|
|
|
|
|
358
|
|
|
|
|
359
|
|
|
/** |
|
360
|
|
|
* @param string $info |
|
361
|
|
|
* @param string $value |
|
362
|
|
|
*/ |
|
363
|
|
|
private function updateRunnerInfo($info, $value) { |
|
364
|
|
|
if ($this->runner === null) { |
|
365
|
|
|
return; |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
$this->runner->setInfo($info, $value); |
|
369
|
|
|
} |
|
370
|
|
|
|
|
371
|
|
|
|
|
372
|
|
|
} |
|
373
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.