Completed
Push — master ( 6387aa...9c4eeb )
by Maxence
01:30
created

FilesService::updateDocument()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
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 OC\Share\Constants;
32
use OC\Share\Share;
33
use OCA\Files_FullTextSearch\Exceptions\FileIsNotIndexableException;
34
use OCA\Files_FullTextSearch\Model\FilesDocument;
35
use OCA\Files_FullTextSearch\Provider\FilesProvider;
36
use OCA\FullTextSearch\Exceptions\InterruptException;
37
use OCA\FullTextSearch\Exceptions\TickDoesNotExistException;
38
use OCA\FullTextSearch\Model\DocumentAccess;
39
use OCA\FullTextSearch\Model\Index;
40
use OCA\FullTextSearch\Model\IndexDocument;
41
use OCA\FullTextSearch\Model\Runner;
42
use OCP\Files\File;
43
use OCP\Files\FileInfo;
44
use OCP\Files\Folder;
45
use OCP\Files\InvalidPathException;
46
use OCP\Files\IRootFolder;
47
use OCP\Files\Node;
48
use OCP\Files\NotFoundException;
49
use OCP\Files\NotPermittedException;
50
use OCP\IUserManager;
51
use OCP\Share\IManager;
52
53
class FilesService {
54
55
	const DOCUMENT_TYPE = 'files';
56
57
	const MIMETYPE_TEXT = 'files_text';
58
	const MIMETYPE_PDF = 'files_pdf';
59
	const MIMETYPE_OFFICE = 'files_office';
60
	const MIMETYPE_IMAGE = 'files_image';
61
	const MIMETYPE_AUDIO = 'files_audio';
62
63
64
	/** @var IRootFolder */
65
	private $rootFolder;
66
67
	/** @var IUserManager */
68
	private $userManager;
69
70
	/** @var IManager */
71
	private $shareManager;
72
73
	/** @var ConfigService */
74
	private $configService;
75
76
	/** @var ExternalFilesService */
77
	private $externalFilesService;
78
79
	/** @var MiscService */
80
	private $miscService;
81
82
83
	/**
84
	 * FilesService constructor.
85
	 *
86
	 * @param IRootFolder $rootFolder
87
	 * @param IUserManager $userManager
88
	 * @param IManager $shareManager
89
	 * @param ConfigService $configService
90
	 * @param ExternalFilesService $externalFilesService
91
	 * @param MiscService $miscService
92
	 *
93
	 * @internal param IProviderFactory $factory
94
	 */
95
	public function __construct(
96
		IRootFolder $rootFolder, IUserManager $userManager, IManager $shareManager,
97
		ConfigService $configService, ExternalFilesService $externalFilesService,
98
		MiscService $miscService
99
	) {
100
		$this->rootFolder = $rootFolder;
101
		$this->userManager = $userManager;
102
		$this->shareManager = $shareManager;
103
104
		$this->configService = $configService;
105
		$this->externalFilesService = $externalFilesService;
106
		$this->miscService = $miscService;
107
	}
108
109
110
	/**
111
	 * @param Runner $runner
112
	 * @param string $userId
113
	 *
114
	 * @return FilesDocument[]
115
	 * @throws InterruptException
116
	 * @throws InvalidPathException
117
	 * @throws NotFoundException
118
	 * @throws TickDoesNotExistException
119
	 */
120
	public function getFilesFromUser(Runner $runner, $userId) {
121
122
		$this->externalFilesService->initExternalFilesForUser($userId);
123
124
		/** @var Folder $files */
125
		$files = $this->rootFolder->getUserFolder($userId)
126
								  ->get('/');
127
		$result = $this->getFilesFromDirectory($runner, $userId, $files);
128
129
		return $result;
130
	}
131
132
133
	/**
134
	 * @param Runner $runner
135
	 * @param string $userId
136
	 * @param Folder $node
137
	 *
138
	 * @return FilesDocument[]
139
	 * @throws InterruptException
140
	 * @throws InvalidPathException
141
	 * @throws NotFoundException
142
	 * @throws TickDoesNotExistException
143
	 */
144
	public function getFilesFromDirectory(Runner $runner, $userId, Folder $node) {
145
		$documents = [];
146
147
		if ($node->nodeExists('.noindex')) {
148
			return $documents;
149
		}
150
151
		$files = $node->getDirectoryListing();
152
		foreach ($files as $file) {
153
			$runner->update('getFilesFromDirectory');
154
			try {
155
				$document = $this->generateFilesDocumentFromFile($file, $userId);
156
				$documents[] = $document;
157
			} catch (FileIsNotIndexableException $e) {
158
				/** goto next file */
159
			}
160
161
			if ($file->getType() === FileInfo::TYPE_FOLDER) {
162
				/** @var $file Folder */
163
				$documents =
164
					array_merge($documents, $this->getFilesFromDirectory($runner, $userId, $file));
165
			}
166
		}
167
168
		return $documents;
169
	}
170
171
172
	/**
173
	 * @param Node $file
174
	 *
175
	 * @param string $viewerId
176
	 *
177
	 * @return FilesDocument
178
	 * @throws FileIsNotIndexableException
179
	 * @throws InvalidPathException
180
	 * @throws NotFoundException
181
	 */
182
	private function generateFilesDocumentFromFile(Node $file, $viewerId = '') {
183
184
		$this->fileMustBeIndexable($file);
185
		$document = new FilesDocument(FilesProvider::FILES_PROVIDER_ID, $file->getId());
186
187
		$ownerId = $file->getOwner()
188
						->getUID();
189
190
		$document->setType($file->getType())
191
				 ->setOwnerId($ownerId)
192
				 ->setViewerId($viewerId)
193
				 ->setModifiedTime($file->getMTime())
194
				 ->setMimetype($file->getMimetype());
195
196
		return $document;
197
	}
198
199
200
	/**
201
	 * @param Node $file
202
	 *
203
	 * @throws FileIsNotIndexableException
204
	 * @throws NotFoundException
205
	 */
206
	private function fileMustBeIndexable(Node $file) {
207
		$this->externalFilesService->externalFileMustBeIndexable($file);
208
	}
209
210
211
	/**
212
	 * @param string $userId
213
	 * @param string $path
214
	 *
215
	 * @return Node
216
	 * @throws NotFoundException
217
	 */
218
	public function getFileFromPath($userId, $path) {
219
		return $this->rootFolder->getUserFolder($userId)
220
								->get($path);
221
	}
222
223
224
	/**
225
	 * @param string $userId
226
	 * @param int $fileId
227
	 *
228
	 * @return Node
229
	 */
230
	public function getFileFromId($userId, $fileId) {
231
232
		$files = $this->rootFolder->getUserFolder($userId)
233
								  ->getById($fileId);
234
235
		if (sizeof($files) === 0) {
236
			return null;
237
		}
238
239
		$file = array_shift($files);
240
241
		return $file;
242
	}
243
244
245
	/**
246
	 * @param int $fileId
247
	 * @param string $viewerId
248
	 *
249
	 * @return string
250
	 */
251
	private function getPathFromViewerId($fileId, $viewerId) {
252
253
		$viewerFiles = $this->rootFolder->getUserFolder($viewerId)
254
										->getById($fileId);
255
256
		if (sizeof($viewerFiles) === 0) {
257
			return '';
258
		}
259
260
		$file = array_shift($viewerFiles);
261
262
		// TODO: better way to do this : we remove the '/userid/files/'
263
		$path = MiscService::noEndSlash(substr($file->getPath(), 8 + strlen($viewerId)));
264
265
		return $path;
266
	}
267
268
269
	/**
270
	 * @param IndexDocument $document
271
	 */
272
	public function setDocumentInfo(IndexDocument $document) {
273
274
		$viewerId = $document->getAccess()
275
							 ->getViewerId();
276
277
		$viewerFiles = $this->rootFolder->getUserFolder($viewerId)
278
										->getById($document->getId());
279
280
		if (sizeof($viewerFiles) === 0) {
281
			return;
282
		}
283
		// we only take the first file
284
		$file = array_shift($viewerFiles);
285
286
		// TODO: better way to do this : we remove the '/userId/files/'
287
		$path = MiscService::noEndSlash(substr($file->getPath(), 7 + strlen($viewerId)));
288
		$document->setInfo('path', $path);
289
		$document->setInfo('filename', $file->getName());
290
	}
291
292
293
	/**
294
	 * @param IndexDocument $document
295
	 */
296
	public function setDocumentTitle(IndexDocument $document) {
297
		$document->setTitle($document->getInfo('path'));
298
	}
299
300
301
	/**
302
	 * @param IndexDocument $document
303
	 */
304
	public function setDocumentLink(IndexDocument $document) {
305
306
		$path = $document->getInfo('path');
307
		$dir = substr($path, 0, -strlen($document->getInfo('filename')));
308
		$filename = $document->getInfo('filename');
309
310
		$document->setLink('/index.php/apps/files/?dir=' . $dir . '&scrollto=' . $filename);
311
	}
312
313
314
	/**
315
	 * @param int $fileId
316
	 *
317
	 * @return string
318
	 */
319
	private function getWebdavId($fileId) {
320
		$instanceId = $this->configService->getSystemValue('instanceid');
321
322
		return sprintf("%08s", $fileId) . $instanceId;
323
	}
324
325
326
	/**
327
	 * @param IndexDocument $document
328
	 *
329
	 * @throws InvalidPathException
330
	 * @throws NotFoundException
331
	 */
332
	public function setDocumentMore(IndexDocument $document) {
333
334
		$access = $document->getAccess();
335
		$file = $this->getFileFromId($access->getViewerId(), $document->getId());
336
337
		if ($file === null) {
338
			return;
339
		}
340
341
		// TODO: better way to do this : we remove the '/userid/files/'
342
		$path = MiscService::noEndSlash(substr($file->getPath(), 7 + strlen($access->getViewerId())));
343
344
		$more = [
345
			'webdav'             => $this->getWebdavId($document->getId()),
346
			'path'               => $path,
347
			'timestamp'          => $file->getMTime(), // FIXME: get the creation date of the file
348
			'mimetype'           => $file->getMimetype(),
349
			'modified_timestamp' => $file->getMTime(),
350
			'etag'               => $file->getEtag(),
351
			'permissions'        => $file->getPermissions(),
352
			'size'               => $file->getSize(),
353
			'favorite'           => false // FIXME: get the favorite status
354
		];
355
356
		$document->setMore($more);
357
	}
358
359
360
	/**
361
	 * @param FilesDocument[] $documents
362
	 *
363
	 * @return FilesDocument[]
364
	 */
365
	public function generateDocuments($documents) {
366
367
		$index = [];
368
369
		foreach ($documents as $document) {
370
			if (!($document instanceof FilesDocument)) {
371
				continue;
372
			}
373
374
			$document->setPath($this->getPathFromViewerId($document->getId(), $document->getViewerId()));
375
376
			try {
377
				$this->updateDocumentFromFilesDocument($document);
378
			} catch (Exception $e) {
379
				// TODO - update $document with a error status instead of just ignore !
380
				$document->getIndex()
381
						 ->setStatus(Index::INDEX_IGNORE);
382
				echo 'Exception: ' . json_encode($e->getTrace()) . ' - ' . $e->getMessage() . "\n";
383
			}
384
385
			$index[] = $document;
386
		}
387
388
		return $index;
389
	}
390
391
392
	/**
393
	 * @param IndexDocument $document
394
	 *
395
	 * @return bool
396
	 */
397
	public function isDocumentUpToDate($document) {
398
		$index = $document->getIndex();
399
400
		if ($index->getStatus() !== Index::INDEX_OK) {
401
			return false;
402
		}
403
404
		if ($index->getLastIndex() >= $document->getModifiedTime()) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return $index->getLastIn...ent->getModifiedTime();.
Loading history...
405
			return true;
406
		}
407
408
		return false;
409
	}
410
411
412
	/**
413
	 * @param Index $index
414
	 *
415
	 * @return FilesDocument
0 ignored issues
show
Documentation introduced by
Should the return type not be FilesDocument|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
416
	 * @throws InvalidPathException
417
	 * @throws NotFoundException
418
	 * @throws NotPermittedException
419
	 */
420
	public function updateDocument(Index $index) {
421
		try {
422
			$document = $this->generateDocumentFromIndex($index);
423
424
			return $document;
425
		} catch (FileIsNotIndexableException $e) {
426
			return null;
427
		}
428
	}
429
430
431
	/**
432
	 * @param FilesDocument $document
433
	 *
434
	 * @throws InvalidPathException
435
	 * @throws NotFoundException
436
	 * @throws NotPermittedException
437
	 */
438
	private function updateDocumentFromFilesDocument(FilesDocument $document) {
439
		$userFolder = $this->rootFolder->getUserFolder($document->getViewerId());
440
		$file = $userFolder->get($document->getPath());
441
442
		try {
443
			$this->updateDocumentFromFile($document, $file);
444
		} catch (FileIsNotIndexableException $e) {
445
			$document->getIndex()
446
					 ->setStatus(Index::INDEX_IGNORE);
447
		}
448
449
	}
450
451
452
	/**
453
	 * @param FilesDocument $document
454
	 * @param Node $file
455
	 *
456
	 * @throws FileIsNotIndexableException
457
	 * @throws InvalidPathException
458
	 * @throws NotFoundException
459
	 * @throws NotPermittedException
460
	 */
461
	private function updateDocumentFromFile(FilesDocument $document, Node $file) {
462
		$this->updateAccessFromFile($document, $file);
463
		$this->updateContentFromFile($document, $file);
464
	}
465
466
467
	/**
468
	 * @param Index $index
469
	 *
470
	 * @return FilesDocument
471
	 * @throws FileIsNotIndexableException
472
	 * @throws InvalidPathException
473
	 * @throws NotFoundException
474
	 * @throws NotPermittedException
475
	 */
476
	private function generateDocumentFromIndex(Index $index) {
477
478
		$file = $this->getFileFromId($index->getOwnerId(), $index->getDocumentId());
479
		if ($file === null) {
480
			$index->setStatus(Index::INDEX_REMOVE);
481
			$document = new FilesDocument($index->getProviderId(), $index->getDocumentId());
482
			$document->setIndex($index);
483
484
			return $document;
485
		}
486
487
		$document = $this->generateFilesDocumentFromFile($file, $index->getOwnerId());
488
		$document->setIndex($index);
489
490
		$this->updateDocumentFromFile($document, $file);
491
492
		return $document;
493
	}
494
495
496
	/**
497
	 * @param FilesDocument $document
498
	 * @param Node $file
499
	 *
500
	 * @throws FileIsNotIndexableException
501
	 * @throws InvalidPathException
502
	 * @throws NotFoundException
503
	 */
504
	private function updateAccessFromFile(FilesDocument $document, Node $file) {
505
506
		$index = $document->getIndex();
507
		if (!$index->isStatus(Index::INDEX_FULL)
508
			&& !$index->isStatus(FilesDocument::STATUS_FILE_ACCESS)) {
509
			return;
510
		}
511
512
		$access = $this->getDocumentAccessFromFile($file);
513
		$document->setAccess($access);
514
		$document->setInfo('share_names', $this->getShareNamesFromFile($file, $access));
515
		$document->getIndex()
516
				 ->setOwnerId(
517
					 $document->getAccess()
518
							  ->getOwnerId()
519
				 );
520
521
		$this->updateDocumentWithLocalFiles($document, $file);
522
		$this->externalFilesService->updateDocumentWithExternalFiles($document, $file);
523
524
	}
525
526
527
	/**
528
	 * @param FilesDocument $document
529
	 * @param Node $file
530
	 *
531
	 * @throws NotFoundException
532
	 */
533
	private function updateDocumentWithLocalFiles(FilesDocument $document, Node $file) {
534
535
		if ($file->getStorage()
536
				 ->isLocal() === false) {
537
			return;
538
		}
539
540
		$document->addTag('local');
541
	}
542
543
544
	/**
545
	 * @param FilesDocument $document
546
	 * @param Node $file
547
	 *
548
	 * @throws InvalidPathException
549
	 * @throws NotFoundException
550
	 * @throws NotPermittedException
551
	 */
552
	private function updateContentFromFile(FilesDocument $document, Node $file) {
553
554
		$document->setTitle($document->getPath());
555
556
		if (!$document->getIndex()
557
					  ->isStatus(Index::INDEX_CONTENT)
558
			|| $file->getType() !== FileInfo::TYPE_FILE) {
559
			return;
560
		}
561
562
		/** @var File $file */
563
		if ($file->getSize() <
564
			($this->configService->getAppValue(ConfigService::FILES_SIZE) * 1024 * 1024)) {
565
			$this->extractContentFromFileText($document, $file);
566
			$this->extractContentFromFileOffice($document, $file);
567
			$this->extractContentFromFilePDF($document, $file);
568
		} else {
569
			echo 'NON !';
570
		}
571
572
		if ($document->getContent() === null) {
573
			$document->getIndex()
574
					 ->unsetStatus(Index::INDEX_CONTENT);
575
		}
576
	}
577
578
579
	/**
580
	 * @param string $mimeType
581
	 *
582
	 * @return string
583
	 */
584
	private function parseMimeType($mimeType) {
585
586
		if ($mimeType === 'application/octet-stream'
587
			|| substr($mimeType, 0, 5) === 'text/') {
588
			return self::MIMETYPE_TEXT;
589
		}
590
591
		if ($mimeType === 'application/pdf') {
592
			return self::MIMETYPE_PDF;
593
		}
594
595
		$officeMimes = [
596
			'application/msword',
597
			'application/vnd.oasis.opendocument',
598
			'application/vnd.sun.xml',
599
			'application/vnd.openxmlformats-officedocument',
600
			'application/vnd.ms-word',
601
			'application/vnd.ms-powerpoint',
602
			'application/vnd.ms-excel',
603
			'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
604
		];
605
606
		if (in_array($mimeType, $officeMimes)) {
607
			return self::MIMETYPE_OFFICE;
608
		}
609
610
		return '';
611
	}
612
613
614
	/**
615
	 * @param FilesDocument $document
616
	 * @param File $file
617
	 *
618
	 * @throws NotPermittedException
619
	 */
620
	private function extractContentFromFileText(FilesDocument $document, File $file) {
621
622
		if ($this->parseMimeType($document->getMimeType()) !== self::MIMETYPE_TEXT) {
623
			return;
624
		}
625
626
		// on simple text file, elastic search+attachment pipeline can still detect language, useful ?
627
//		$document->setContent($file->getContent(), IndexDocument::NOT_ENCODED);
628
629
		// We try to avoid error with some base encoding of the document:
630
		$document->setContent(base64_encode($file->getContent()), IndexDocument::ENCODED_BASE64);
631
	}
632
633
634
	/**
635
	 * @param FilesDocument $document
636
	 * @param File $file
637
	 *
638
	 * @throws NotPermittedException
639
	 */
640 View Code Duplication
	private function extractContentFromFilePDF(FilesDocument $document, File $file) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
641
642
		if ($this->parseMimeType($document->getMimeType()) !== self::MIMETYPE_PDF) {
643
			return;
644
		}
645
646
		if ($this->configService->getAppValue('files_pdf') !== '1') {
647
			return;
648
		}
649
650
		$document->setContent(base64_encode($file->getContent()), IndexDocument::ENCODED_BASE64);
651
	}
652
653
654
	/**
655
	 * @param FilesDocument $document
656
	 * @param File $file
657
	 *
658
	 * @throws NotPermittedException
659
	 */
660 View Code Duplication
	private function extractContentFromFileOffice(FilesDocument $document, File $file) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
661
662
		if ($this->configService->getAppValue('files_office') !== '1') {
663
			return;
664
		}
665
666
		if ($this->parseMimeType($document->getMimeType()) !== self::MIMETYPE_OFFICE) {
667
			return;
668
		}
669
670
		$document->setContent(base64_encode($file->getContent()), IndexDocument::ENCODED_BASE64);
671
	}
672
673
674
	/**
675
	 * @param Node $file
676
	 *
677
	 * @return DocumentAccess
678
	 * @throws InvalidPathException
679
	 * @throws NotFoundException
680
	 */
681
	private function getDocumentAccessFromFile(Node $file) {
682
683
		$access = new DocumentAccess(
684
			$file->getOwner()
685
				 ->getUID()
686
		);
687
688
		list($users, $groups, $circles, $links) = $this->getSharesFromFileId($file->getId());
689
		$access->setUsers($users);
690
		$access->setGroups($groups);
691
		$access->setCircles($circles);
692
		$access->setLinks($links);
693
694
		return $access;
695
	}
696
697
698
	/**
699
	 * @param Node $file
700
	 * @param DocumentAccess $access
701
	 *
702
	 * @return array
703
	 * @throws InvalidPathException
704
	 * @throws NotFoundException
705
	 */
706
	private function getShareNamesFromFile(Node $file, DocumentAccess $access) {
707
		$shareNames = [];
708
709
		if ($file->getStorage()
710
				 ->isLocal() === false) {
711
			$shares = $this->externalFilesService->getAllSharesFromExternalFile($access);
712
		} else {
713
			$shares = $this->getAllSharesFromFile($file);
714
		}
715
716
		foreach ($shares as $user) {
717
			$shareNames[$user] = $this->getPathFromViewerId($file->getId(), $user);
718
		}
719
720
		return $shareNames;
721
	}
722
723
724
	/**
725
	 * @param Node $file
726
	 *
727
	 * @return array
728
	 */
729
	private function getAllSharesFromFile(Node $file) {
730
		$result = [];
731
732
		$shares = $this->shareManager->getAccessList($file);
733
		if (!array_key_exists('users', $shares)) {
734
			return $result;
735
		}
736
737
		foreach ($shares['users'] as $user) {
738
			if (in_array($user, $result) || $this->userManager->get($user) === null) {
739
				continue;
740
			}
741
742
			array_push($result, $user);
743
		}
744
745
		return $result;
746
	}
747
748
749
	/**
750
	 * @param $fileId
751
	 *
752
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
753
	 */
754
	private function getSharesFromFileId($fileId) {
755
756
		$users = $groups = $circles = $links = [];
757
		$shares = Share::getAllSharesForFileId($fileId);
758
759
		foreach ($shares as $share) {
760
			if ($share['parent'] !== null) {
761
				continue;
762
			}
763
764
			$this->parseUsersShares($share, $users);
765
			$this->parseUsersGroups($share, $groups);
766
			$this->parseUsersCircles($share, $circles);
767
			$this->parseUsersLinks($share, $links);
768
		}
769
770
		return [$users, $groups, $circles, $links];
771
	}
772
773
774
	/**
775
	 * @param array $share
776
	 * @param array $users
777
	 */
778 View Code Duplication
	private function parseUsersShares($share, &$users) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
779
		if ((int)$share['share_type'] !== Constants::SHARE_TYPE_USER) {
780
			return;
781
		}
782
783
		if (!in_array($share['share_with'], $users)) {
784
			$users[] = $share['share_with'];
785
		}
786
	}
787
788
789
	/**
790
	 * @param array $share
791
	 * @param array $groups
792
	 */
793 View Code Duplication
	private function parseUsersGroups($share, &$groups) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
794
		if ((int)$share['share_type'] !== Constants::SHARE_TYPE_GROUP) {
795
			return;
796
		}
797
798
		if (!in_array($share['share_with'], $groups)) {
799
			$groups[] = $share['share_with'];
800
		}
801
	}
802
803
804
	/**
805
	 * @param array $share
806
	 * @param array $circles
807
	 */
808 View Code Duplication
	private function parseUsersCircles($share, &$circles) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
809
		if ((int)$share['share_type'] !== Constants::SHARE_TYPE_CIRCLE) {
810
			return;
811
		}
812
813
		if (!in_array($share['share_with'], $circles)) {
814
			$circles[] = $share['share_with'];
815
		}
816
	}
817
818
819
	/**
820
	 * @param array $share
821
	 * @param array $links
822
	 */
823 View Code Duplication
	private function parseUsersLinks($share, &$links) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
824
		if ((int)$share['share_type'] !== Constants::SHARE_TYPE_LINK) {
825
			return;
826
		}
827
828
		if (!in_array($share['share_with'], $links)) {
829
			$links[] = $share['share_with'];
830
		}
831
	}
832
833
834
}