Completed
Pull Request — master (#2077)
by Joas
13:01 queued 03:50
created

ShareesAPIController::search()   C

Complexity

Conditions 11
Paths 29

Size

Total Lines 44
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 28
nc 29
nop 5
dl 0
loc 44
rs 5.2653
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Björn Schießle <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 * @author Thomas Müller <[email protected]>
9
 *
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
namespace OCA\Files_Sharing\Controller;
26
27
use OCP\AppFramework\Http;
28
use OCP\AppFramework\OCS\OCSBadRequestException;
29
use OCP\AppFramework\OCSController;
30
use OCP\Contacts\IManager;
31
use OCP\IGroup;
32
use OCP\IGroupManager;
33
use OCP\ILogger;
34
use OCP\IRequest;
35
use OCP\IUser;
36
use OCP\IUserManager;
37
use OCP\IConfig;
38
use OCP\IUserSession;
39
use OCP\IURLGenerator;
40
use OCP\Share;
41
42
class ShareesAPIController extends OCSController {
43
44
	/** @var IGroupManager */
45
	protected $groupManager;
46
47
	/** @var IUserManager */
48
	protected $userManager;
49
50
	/** @var IManager */
51
	protected $contactsManager;
52
53
	/** @var IConfig */
54
	protected $config;
55
56
	/** @var IUserSession */
57
	protected $userSession;
58
59
	/** @var IURLGenerator */
60
	protected $urlGenerator;
61
62
	/** @var ILogger */
63
	protected $logger;
64
65
	/** @var \OCP\Share\IManager */
66
	protected $shareManager;
67
68
	/** @var bool */
69
	protected $shareWithGroupOnly = false;
70
71
	/** @var bool */
72
	protected $shareeEnumeration = true;
73
74
	/** @var int */
75
	protected $offset = 0;
76
77
	/** @var int */
78
	protected $limit = 10;
79
80
	/** @var array */
81
	protected $result = [
82
		'exact' => [
83
			'users' => [],
84
			'groups' => [],
85
			'remotes' => [],
86
			'emails' => [],
87
		],
88
		'users' => [],
89
		'groups' => [],
90
		'remotes' => [],
91
		'emails' => [],
92
	];
93
94
	protected $reachedEndFor = [];
95
96
	/**
97
	 * @param string $appName
98
	 * @param IRequest $request
99
	 * @param IGroupManager $groupManager
100
	 * @param IUserManager $userManager
101
	 * @param IManager $contactsManager
102
	 * @param IConfig $config
103
	 * @param IUserSession $userSession
104
	 * @param IURLGenerator $urlGenerator
105
	 * @param ILogger $logger
106
	 * @param \OCP\Share\IManager $shareManager
107
	 */
108
	public function __construct($appName,
109
								IRequest $request,
110
								IGroupManager $groupManager,
111
								IUserManager $userManager,
112
								IManager $contactsManager,
113
								IConfig $config,
114
								IUserSession $userSession,
115
								IURLGenerator $urlGenerator,
116
								ILogger $logger,
117
								\OCP\Share\IManager $shareManager) {
118
		parent::__construct($appName, $request);
119
120
		$this->groupManager = $groupManager;
121
		$this->userManager = $userManager;
122
		$this->contactsManager = $contactsManager;
123
		$this->config = $config;
124
		$this->userSession = $userSession;
125
		$this->urlGenerator = $urlGenerator;
126
		$this->logger = $logger;
127
		$this->shareManager = $shareManager;
128
	}
129
130
	/**
131
	 * @param string $search
132
	 */
133
	protected function getUsers($search) {
134
		$this->result['users'] = $this->result['exact']['users'] = $users = [];
135
136
		$userGroups = [];
137
		if ($this->shareWithGroupOnly) {
138
			// Search in all the groups this user is part of
139
			$userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
0 ignored issues
show
Bug introduced by
It seems like $this->userSession->getUser() can be null; however, getUserGroupIds() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
140
			foreach ($userGroups as $userGroup) {
141
				$usersTmp = $this->groupManager->displayNamesInGroup($userGroup, $search, $this->limit, $this->offset);
142
				foreach ($usersTmp as $uid => $userDisplayName) {
143
					$users[$uid] = $userDisplayName;
144
				}
145
			}
146
		} else {
147
			// Search in all users
148
			$usersTmp = $this->userManager->searchDisplayName($search, $this->limit, $this->offset);
149
150
			foreach ($usersTmp as $user) {
151
				$users[$user->getUID()] = $user->getDisplayName();
152
			}
153
		}
154
155 View Code Duplication
		if (!$this->shareeEnumeration || sizeof($users) < $this->limit) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
156
			$this->reachedEndFor[] = 'users';
157
		}
158
159
		$foundUserById = false;
160
		foreach ($users as $uid => $userDisplayName) {
161
			if (strtolower($uid) === strtolower($search) || strtolower($userDisplayName) === strtolower($search)) {
162
				if (strtolower($uid) === strtolower($search)) {
163
					$foundUserById = true;
164
				}
165
				$this->result['exact']['users'][] = [
166
					'label' => $userDisplayName,
167
					'value' => [
168
						'shareType' => Share::SHARE_TYPE_USER,
169
						'shareWith' => $uid,
170
					],
171
				];
172 View Code Duplication
			} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
173
				$this->result['users'][] = [
174
					'label' => $userDisplayName,
175
					'value' => [
176
						'shareType' => Share::SHARE_TYPE_USER,
177
						'shareWith' => $uid,
178
					],
179
				];
180
			}
181
		}
182
183
		if ($this->offset === 0 && !$foundUserById) {
184
			// On page one we try if the search result has a direct hit on the
185
			// user id and if so, we add that to the exact match list
186
			$user = $this->userManager->get($search);
187
			if ($user instanceof IUser) {
188
				$addUser = true;
189
190
				if ($this->shareWithGroupOnly) {
191
					// Only add, if we have a common group
192
					$commonGroups = array_intersect($userGroups, $this->groupManager->getUserGroupIds($user));
193
					$addUser = !empty($commonGroups);
194
				}
195
196
				if ($addUser) {
197
					array_push($this->result['exact']['users'], [
198
						'label' => $user->getDisplayName(),
199
						'value' => [
200
							'shareType' => Share::SHARE_TYPE_USER,
201
							'shareWith' => $user->getUID(),
202
						],
203
					]);
204
				}
205
			}
206
		}
207
208
		if (!$this->shareeEnumeration) {
209
			$this->result['users'] = [];
210
		}
211
	}
212
213
	/**
214
	 * @param string $search
215
	 */
216
	protected function getGroups($search) {
217
		$this->result['groups'] = $this->result['exact']['groups'] = [];
218
219
		$groups = $this->groupManager->search($search, $this->limit, $this->offset);
220
		$groups = array_map(function (IGroup $group) { return $group->getGID(); }, $groups);
221
222 View Code Duplication
		if (!$this->shareeEnumeration || sizeof($groups) < $this->limit) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
223
			$this->reachedEndFor[] = 'groups';
224
		}
225
226
		$userGroups =  [];
227
		if (!empty($groups) && $this->shareWithGroupOnly) {
228
			// Intersect all the groups that match with the groups this user is a member of
229
			$userGroups = $this->groupManager->getUserGroups($this->userSession->getUser());
230
			$userGroups = array_map(function (IGroup $group) { return $group->getGID(); }, $userGroups);
231
			$groups = array_intersect($groups, $userGroups);
232
		}
233
234
		foreach ($groups as $gid) {
235
			if (strtolower($gid) === strtolower($search)) {
236
				$this->result['exact']['groups'][] = [
237
					'label' => $gid,
238
					'value' => [
239
						'shareType' => Share::SHARE_TYPE_GROUP,
240
						'shareWith' => $gid,
241
					],
242
				];
243 View Code Duplication
			} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
244
				$this->result['groups'][] = [
245
					'label' => $gid,
246
					'value' => [
247
						'shareType' => Share::SHARE_TYPE_GROUP,
248
						'shareWith' => $gid,
249
					],
250
				];
251
			}
252
		}
253
254
		if ($this->offset === 0 && empty($this->result['exact']['groups'])) {
255
			// On page one we try if the search result has a direct hit on the
256
			// user id and if so, we add that to the exact match list
257
			$group = $this->groupManager->get($search);
258
			if ($group instanceof IGroup && (!$this->shareWithGroupOnly || in_array($group->getGID(), $userGroups))) {
259
				array_push($this->result['exact']['groups'], [
260
					'label' => $group->getGID(),
261
					'value' => [
262
						'shareType' => Share::SHARE_TYPE_GROUP,
263
						'shareWith' => $group->getGID(),
264
					],
265
				]);
266
			}
267
		}
268
269
		if (!$this->shareeEnumeration) {
270
			$this->result['groups'] = [];
271
		}
272
	}
273
274
	/**
275
	 * @param string $search
276
	 * @return array
277
	 */
278
	protected function getRemote($search) {
279
		$result = ['results' => [], 'exact' => []];
280
281
		// Search in contacts
282
		//@todo Pagination missing
283
		$addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']);
284
		$result['exactIdMatch'] = false;
285
		foreach ($addressBookContacts as $contact) {
286
			if (isset($contact['isLocalSystemBook'])) {
287
				continue;
288
			}
289
			if (isset($contact['CLOUD'])) {
290
				$cloudIds = $contact['CLOUD'];
291
				if (!is_array($cloudIds)) {
292
					$cloudIds = [$cloudIds];
293
				}
294
				foreach ($cloudIds as $cloudId) {
295
					list(, $serverUrl) = $this->splitUserRemote($cloudId);
296
					if (strtolower($contact['FN']) === strtolower($search) || strtolower($cloudId) === strtolower($search)) {
297
						if (strtolower($cloudId) === strtolower($search)) {
298
							$result['exactIdMatch'] = true;
299
						}
300
						$result['exact'][] = [
301
							'label' => $contact['FN'] . " ($cloudId)",
302
							'value' => [
303
								'shareType' => Share::SHARE_TYPE_REMOTE,
304
								'shareWith' => $cloudId,
305
								'server' => $serverUrl,
306
							],
307
						];
308 View Code Duplication
					} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
309
						$result['results'][] = [
310
							'label' => $contact['FN'] . " ($cloudId)",
311
							'value' => [
312
								'shareType' => Share::SHARE_TYPE_REMOTE,
313
								'shareWith' => $cloudId,
314
								'server' => $serverUrl,
315
							],
316
						];
317
					}
318
				}
319
			}
320
		}
321
322
		if (!$this->shareeEnumeration) {
323
			$result['results'] = [];
324
		}
325
326
		if (!$result['exactIdMatch'] && substr_count($search, '@') >= 1 && $this->offset === 0) {
327
			$result['exact'][] = [
328
				'label' => $search,
329
				'value' => [
330
					'shareType' => Share::SHARE_TYPE_REMOTE,
331
					'shareWith' => $search,
332
				],
333
			];
334
		}
335
336
		$this->reachedEndFor[] = 'remotes';
337
338
		return $result;
339
	}
340
341
	/**
342
	 * split user and remote from federated cloud id
343
	 *
344
	 * @param string $address federated share address
345
	 * @return array [user, remoteURL]
346
	 * @throws \Exception
347
	 */
348
	public function splitUserRemote($address) {
349
		if (strpos($address, '@') === false) {
350
			throw new \Exception('Invalid Federated Cloud ID');
351
		}
352
353
		// Find the first character that is not allowed in user names
354
		$id = str_replace('\\', '/', $address);
355
		$posSlash = strpos($id, '/');
356
		$posColon = strpos($id, ':');
357
358 View Code Duplication
		if ($posSlash === false && $posColon === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
359
			$invalidPos = strlen($id);
360
		} else if ($posSlash === false) {
361
			$invalidPos = $posColon;
362
		} else if ($posColon === false) {
363
			$invalidPos = $posSlash;
364
		} else {
365
			$invalidPos = min($posSlash, $posColon);
366
		}
367
368
		// Find the last @ before $invalidPos
369
		$pos = $lastAtPos = 0;
370 View Code Duplication
		while ($lastAtPos !== false && $lastAtPos <= $invalidPos) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
371
			$pos = $lastAtPos;
372
			$lastAtPos = strpos($id, '@', $pos + 1);
373
		}
374
375 View Code Duplication
		if ($pos !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
376
			$user = substr($id, 0, $pos);
377
			$remote = substr($id, $pos + 1);
378
			$remote = $this->fixRemoteURL($remote);
379
			if (!empty($user) && !empty($remote)) {
380
				return array($user, $remote);
381
			}
382
		}
383
384
		throw new \Exception('Invalid Federated Cloud ID');
385
	}
386
387
	/**
388
	 * Strips away a potential file names and trailing slashes:
389
	 * - http://localhost
390
	 * - http://localhost/
391
	 * - http://localhost/index.php
392
	 * - http://localhost/index.php/s/{shareToken}
393
	 *
394
	 * all return: http://localhost
395
	 *
396
	 * @param string $remote
397
	 * @return string
398
	 */
399 View Code Duplication
	protected function fixRemoteURL($remote) {
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...
400
		$remote = str_replace('\\', '/', $remote);
401
		if ($fileNamePosition = strpos($remote, '/index.php')) {
402
			$remote = substr($remote, 0, $fileNamePosition);
403
		}
404
		$remote = rtrim($remote, '/');
405
406
		return $remote;
407
	}
408
409
	/**
410
	 * @NoAdminRequired
411
	 *
412
	 * @param string $search
413
	 * @param string $itemType
414
	 * @param int $page
415
	 * @param int $perPage
416
	 * @param int|int[] $shareType
417
	 * @return Http\DataResponse
418
	 * @throws OCSBadRequestException
419
	 */
420
	public function search($search = '', $itemType = null, $page = 1, $perPage = 200, $shareType = null) {
421
		if ($perPage <= 0) {
422
			throw new OCSBadRequestException('Invalid perPage argument');
423
		}
424
		if ($page <= 0) {
425
			throw new OCSBadRequestException('Invalid page');
426
		}
427
428
		$shareTypes = [
429
			Share::SHARE_TYPE_USER,
430
		];
431
432
		if ($itemType === 'file' || $itemType === 'folder') {
433
			if ($this->shareManager->allowGroupSharing()) {
434
				$shareTypes[] = Share::SHARE_TYPE_GROUP;
435
			}
436
437
			if ($this->isRemoteSharingAllowed($itemType)) {
438
				$shareTypes[] = Share::SHARE_TYPE_REMOTE;
439
			}
440
441
			if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) {
442
				$shareTypes[] = Share::SHARE_TYPE_EMAIL;
443
			}
444
		} else {
445
			$shareTypes[] = Share::SHARE_TYPE_GROUP;
446
			$shareTypes[] = Share::SHARE_TYPE_EMAIL;
447
		}
448
449
		if (isset($_GET['shareType']) && is_array($_GET['shareType'])) {
450
			$shareTypes = array_intersect($shareTypes, $_GET['shareType']);
451
			sort($shareTypes);
452
		} else if (is_numeric($shareType)) {
453
			$shareTypes = array_intersect($shareTypes, [(int) $shareType]);
454
			sort($shareTypes);
455
		}
456
457
		$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
458
		$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
459
		$this->limit = (int) $perPage;
460
		$this->offset = $perPage * ($page - 1);
461
462
		return $this->searchSharees($search, $itemType, $shareTypes, $page, $perPage);
463
	}
464
465
	/**
466
	 * Method to get out the static call for better testing
467
	 *
468
	 * @param string $itemType
469
	 * @return bool
470
	 */
471
	protected function isRemoteSharingAllowed($itemType) {
472
		try {
473
			$backend = Share::getBackend($itemType);
474
			return $backend->isShareTypeAllowed(Share::SHARE_TYPE_REMOTE);
475
		} catch (\Exception $e) {
476
			return false;
477
		}
478
	}
479
480
	/**
481
	 * Testable search function that does not need globals
482
	 *
483
	 * @param string $search
484
	 * @param string $itemType
485
	 * @param array $shareTypes
486
	 * @param int $page
487
	 * @param int $perPage
488
	 * @return Http\DataResponse
489
	 * @throws OCSBadRequestException
490
	 */
491
	protected function searchSharees($search, $itemType, array $shareTypes, $page, $perPage) {
492
		// Verify arguments
493
		if ($itemType === null) {
494
			throw new OCSBadRequestException('Missing itemType');
495
		}
496
497
		// Get users
498
		if (in_array(Share::SHARE_TYPE_USER, $shareTypes)) {
499
			$this->getUsers($search);
500
		}
501
502
		// Get groups
503
		if (in_array(Share::SHARE_TYPE_GROUP, $shareTypes)) {
504
			$this->getGroups($search);
505
		}
506
507
		// Get remote
508
		$remoteResults = ['results' => [], 'exact' => [], 'exactIdMatch' => false];
509
		if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes)) {
510
			$remoteResults = $this->getRemote($search);
511
		}
512
513
		$mailResults = ['results' => [], 'exact' => [], 'exactIdMatch' => false];
514
		if (in_array(Share::SHARE_TYPE_EMAIL, $shareTypes)) {
515
			$mailResults = $this->getEmail($search);
516
		}
517
518
		// if we have a exact match, either for the federated cloud id or for the
519
		// email address we only return the exact match. It is highly unlikely
520
		// that the exact same email address and federated cloud id exists
521
		if ($mailResults['exactIdMatch'] && !$remoteResults['exactIdMatch']) {
522
			$this->result['emails'] = $mailResults['results'];
523
			$this->result['exact']['emails'] = $mailResults['exact'];
524
		} else if (!$mailResults['exactIdMatch'] && $remoteResults['exactIdMatch']) {
525
			$this->result['remotes'] = $remoteResults['results'];
526
			$this->result['exact']['remotes'] = $remoteResults['exact'];
527
		} else {
528
			$this->result['remotes'] = $remoteResults['results'];
529
			$this->result['exact']['remotes'] = $remoteResults['exact'];
530
			$this->result['emails'] = $mailResults['results'];
531
			$this->result['exact']['emails'] = $mailResults['exact'];
532
		}
533
534
		$response = new Http\DataResponse($this->result);
535
536
		if (sizeof($this->reachedEndFor) < 3) {
537
			$response->addHeader('Link', $this->getPaginationLink($page, [
538
				'search' => $search,
539
				'itemType' => $itemType,
540
				'shareType' => $shareTypes,
541
				'perPage' => $perPage,
542
			]));
543
		}
544
545
		return $response;
546
	}
547
548
	/**
549
	 * @param string $search
550
	 * @return array
551
	 */
552
	protected function getEmail($search) {
553
		$result = ['results' => [], 'exact' => []];
554
555
		// Search in contacts
556
		//@todo Pagination missing
557
		$addressBookContacts = $this->contactsManager->search($search, ['EMAIL', 'FN']);
558
		$result['exactIdMatch'] = false;
559
		foreach ($addressBookContacts as $contact) {
560
			if (isset($contact['isLocalSystemBook'])) {
561
				continue;
562
			}
563
			if (isset($contact['EMAIL'])) {
564
				$emailAddresses = $contact['EMAIL'];
565
				if (!is_array($emailAddresses)) {
566
					$emailAddresses = [$emailAddresses];
567
				}
568
				foreach ($emailAddresses as $emailAddress) {
569
					if (strtolower($contact['FN']) === strtolower($search) || strtolower($emailAddress) === strtolower($search)) {
570
						if (strtolower($emailAddress) === strtolower($search)) {
571
							$result['exactIdMatch'] = true;
572
						}
573
						$result['exact'][] = [
574
							'label' => $contact['FN'] . " ($emailAddress)",
575
							'value' => [
576
								'shareType' => Share::SHARE_TYPE_EMAIL,
577
								'shareWith' => $emailAddress,
578
							],
579
						];
580 View Code Duplication
					} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
581
						$result['results'][] = [
582
							'label' => $contact['FN'] . " ($emailAddress)",
583
							'value' => [
584
								'shareType' => Share::SHARE_TYPE_EMAIL,
585
								'shareWith' => $emailAddress,
586
							],
587
						];
588
					}
589
				}
590
			}
591
		}
592
593
		if (!$this->shareeEnumeration) {
594
			$result['results'] = [];
595
		}
596
597
		if (!$result['exactIdMatch'] && filter_var($search, FILTER_VALIDATE_EMAIL)) {
598
			$result['exact'][] = [
599
				'label' => $search,
600
				'value' => [
601
					'shareType' => Share::SHARE_TYPE_EMAIL,
602
					'shareWith' => $search,
603
				],
604
			];
605
		}
606
607
		$this->reachedEndFor[] = 'emails';
608
609
		return $result;
610
	}
611
612
	/**
613
	 * Generates a bunch of pagination links for the current page
614
	 *
615
	 * @param int $page Current page
616
	 * @param array $params Parameters for the URL
617
	 * @return string
618
	 */
619
	protected function getPaginationLink($page, array $params) {
620
		if ($this->isV2()) {
621
			$url = $this->urlGenerator->getAbsoluteURL('/ocs/v2.php/apps/files_sharing/api/v1/sharees') . '?';
622
		} else {
623
			$url = $this->urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/sharees') . '?';
624
		}
625
		$params['page'] = $page + 1;
626
		$link = '<' . $url . http_build_query($params) . '>; rel="next"';
627
628
		return $link;
629
	}
630
631
	/**
632
	 * @return bool
633
	 */
634
	protected function isV2() {
635
		return $this->request->getScriptName() === '/ocs/v2.php';
636
	}
637
}
638