Completed
Push — master ( 3f43c1...51db49 )
by Maxence
03:26
created

SearchService::setDocumentLinkFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 6
nc 2
nop 3
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\Service;
28
29
30
use Exception;
31
use OCA\Files_FullTextSearch\Model\FilesDocument;
32
use OCA\FullTextSearch\Model\ExtendedTick;
33
use OCA\FullTextSearch\Model\Index;
34
use OCA\FullTextSearch\Model\SearchRequest;
35
use OCA\FullTextSearch\Model\SearchResult;
36
use OCP\Files\InvalidPathException;
37
use OCP\Files\Node;
38
use OCP\Files\NotFoundException;
39
40
class SearchService {
41
42
	/** @var string */
43
	private $userId;
44
45
	/** @var FilesService */
46
	private $filesService;
47
48
	/** @var ConfigService */
49
	private $configService;
50
51
	/** @var MiscService */
52
	private $miscService;
53
54
55
	/**
56
	 * SearchService constructor.
57
	 *
58
	 * @param string $userId
59
	 * @param FilesService $filesService
60
	 * @param ConfigService $configService
61
	 * @param MiscService $miscService
62
	 *
63
	 * @internal param IProviderFactory $factory
64
	 */
65
	public function __construct(
66
		$userId, FilesService $filesService, ConfigService $configService, MiscService $miscService
67
	) {
68
		$this->userId = $userId;
69
		$this->filesService = $filesService;
70
		$this->configService = $configService;
71
		$this->miscService = $miscService;
72
	}
73
74
75
	/**
76
	 * @param SearchRequest $request
77
	 */
78
	public function improveSearchRequest(SearchRequest $request) {
79
		$this->searchQueryShareNames($request);
80
		$this->searchQueryWithinDir($request);
81
		$this->searchQueryFiltersExtension($request);
82
		$this->searchQueryFiltersSource($request);
83
	}
84
85
86
	/**
87
	 * @param SearchRequest $request
88
	 */
89
	private function searchQueryShareNames(SearchRequest $request) {
90
		$username = MiscService::secureUsername($request->getAuthor());
91
		$request->addField('share_names.' . $username);
92
93
		$request->addWildcardField('title');
94
		$request->addWildcardField('share_names.' . $username);
95
	}
96
97
98
	/**
99
	 * @param SearchRequest $request
100
	 */
101
	private function searchQueryWithinDir(SearchRequest $request) {
102
103
		$currentDir = $request->getOption('files_within_dir');
104
		if ($currentDir === '') {
105
			return;
106
		}
107
108
		$username = MiscService::secureUsername($request->getAuthor());
109
		$currentDir = MiscService::noBeginSlash(MiscService::endSlash($currentDir));
110
		$request->addRegexFilters(
111
			[
112
				['share_names.' . $username => $currentDir . '*'],
113
				['title' => $currentDir . '*']
114
			]
115
		);
116
	}
117
118
119
	/**
120
	 * @param SearchRequest $request
121
	 */
122
	private function searchQueryFiltersExtension(SearchRequest $request) {
123
		$extension = $request->getOption('files_extension');
124
		if ($extension === '') {
125
			return;
126
		}
127
128
		$username = MiscService::secureUsername($request->getAuthor());
129
		$request->addRegexFilters(
130
			[
131
				['share_names.' . $username => '.*\.' . $extension],
132
				['title' => '.*\.' . $extension]
133
			]
134
		);
135
	}
136
137
138
	/**
139
	 * @param SearchRequest $request
140
	 */
141
	private function searchQueryFiltersSource(SearchRequest $request) {
142
143
		$local = $request->getOption('files_local');
144
		$external = $request->getOption('files_external');
145
		$groupFolders = $request->getOption('files_group_folders');
146
		$federated = $request->getOption('files_federated');
0 ignored issues
show
Unused Code introduced by
$federated is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
147
148
		if (count(array_unique([$local, $external, $groupFolders])) === 1) {
149
			return;
150
		}
151
152
		$this->addTagToSearchRequest($request, 'files_local', $local);
153
		$this->addTagToSearchRequest($request, 'files_external', $external);
154
		$this->addTagToSearchRequest($request, 'files_group_folders', $groupFolders);
155
	}
156
157
158
	/**
159
	 * @param SearchRequest $request
160
	 * @param string $tag
161
	 * @param mixed $cond
162
	 */
163
	private function addTagToSearchRequest(SearchRequest $request, $tag, $cond) {
164
		if ($cond === 1 || $cond === '1') {
165
			$request->addTag($tag);
166
		}
167
	}
168
169
170
	/**
171
	 * @param SearchResult $searchResult
172
	 */
173
	public function improveSearchResult(SearchResult $searchResult) {
174
		$indexDocuments = $searchResult->getDocuments();
175
		$filesDocuments = [];
176
		foreach ($indexDocuments as $indexDocument) {
177
178
			try {
179
				$filesDocument = FilesDocument::fromIndexDocument($indexDocument);
180
				$this->setDocumentInfo($filesDocument);
181
				$this->setDocumentTitle($filesDocument);
182
				$this->setDocumentLink($filesDocument);
183
184
				$filesDocuments[] = $filesDocument;
185
			} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
186
			}
187
		}
188
189
		$searchResult->setDocuments($filesDocuments);
190
	}
191
192
193
	/**
194
	 * @param FilesDocument $document
195
	 *
196
	 * @throws Exception
197
	 */
198
	private function setDocumentInfo(FilesDocument $document) {
199
		$index = new Index('files', $document->getId());
200
		$index->setOwnerId($this->userId);
201
202
		$document->setInfo('webdav', $this->getWebdavId($document->getId()));
203
204
		$file = $this->filesService->getFileFromIndex($index);
205
		$this->setDocumentInfoFromFile($document, $file);
206
	}
207
208
209
	/**
210
	 * @param FilesDocument $document
211
	 * @param Node $file
212
	 */
213
	private function setDocumentInfoFromFile(FilesDocument $document, Node $file) {
214
215
		// TODO: better way to do this : we remove the '/userId/files/'
216
		$path = MiscService::noEndSlash(substr($file->getPath(), 7 + strlen($this->userId)));
217
		$pathInfo = pathinfo($path);
218
219
		$document->setPath($path);
220
		$document->setInfo('type', $file->getType())
221
				 ->setInfo('file', $pathInfo['basename'])
222
				 ->setInfo('path', $pathInfo['dirname'])
223
				 ->setInfo('mime', $file->getMimetype())
224
				 ->setInfo('favorite', false); // FIXME: get the favorite status
225
226
		try {
227
			$document->setInfo('size', $file->getSize())
228
					 ->setInfo('mtime', $file->getMTime())
229
					 ->setInfo('etag', $file->getEtag())
230
					 ->setInfo('permissions', $file->getPermissions());
231
		} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
232
		}
233
	}
234
235
236
	/**
237
	 * @param FilesDocument $document
238
	 */
239
	private function setDocumentTitle(FilesDocument $document) {
240
		if (!is_null($document->getPath()) && $document->getPath() !== '') {
241
			$document->setTitle($document->getPath());
242
		} else {
243
			$document->setTitle('/' . $document->getTitle());
244
		}
245
	}
246
247
248
	/**
249
	 * @param FilesDocument $document
250
	 */
251
	private function setDocumentLink(FilesDocument $document) {
252
253
		$path = $document->getPath();
254
		$filename = $document->getInfo('file');
255
		$dir = substr($path, 0, -strlen($filename));
256
257
		$document->setLink(
258
			\OC::$server->getURLGenerator()
259
						->linkToRoute(
260
							'files.view.index',
261
							[
262
								'dir'      => $dir,
263
								'scrollto' => $filename,
264
							]
265
						)
266
		);
267
268
		$this->setDocumentLinkDir($document, $dir, $filename);
0 ignored issues
show
Unused Code introduced by
The call to SearchService::setDocumentLinkDir() has too many arguments starting with $filename.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
269
		$this->setDocumentLinkFile($document, $dir, $filename);
270
	}
271
272
273
	/**
274
	 * @param FilesDocument $document
275
	 * @param $dir
276
	 * @param $filename
277
	 */
278
	private function setDocumentLinkFile(FilesDocument $document, $dir, $filename) {
279
		if ($document->getInfo('type') !== 'file') {
280
			return;
281
		}
282
283
		$link = '/' . $this->configService->getSystemValue('webdav-root', 'remote.php/webdav');
284
		$link .= $dir . '/' . $filename;
285
286
		$document->setLink($link);
287
	}
288
289
290
	/**
291
	 * @param FilesDocument $document
292
	 * @param $dir
293
	 */
294
	private function setDocumentLinkDir(FilesDocument $document, $dir) {
295
		if ($document->getInfo('type') !== 'dir') {
296
			return;
297
		}
298
299
		$document->setLink(
300
			\OC::$server->getURLGenerator()
301
						->linkToRoute(
302
							'files.view.index',
303
							['dir' => $dir, 'fileid' => $document->getId()]
304
						)
305
		);
306
	}
307
308
	/**
309
	 * @param int $fileId
310
	 *
311
	 * @return string
312
	 */
313
	private function getWebdavId($fileId) {
314
		$instanceId = $this->configService->getSystemValue('instanceid');
315
316
		return sprintf("%08s", $fileId) . $instanceId;
317
	}
318
319
320
}