Completed
Push — master ( a89f9a...3036b1 )
by Morris
29:19 queued 12:13
created

Manager   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 605
Duplicated Lines 4.3 %

Coupling/Cohesion

Components 1
Dependencies 24

Importance

Changes 0
Metric Value
dl 26
loc 605
rs 5.035
c 0
b 0
f 0
wmc 57
lcom 1
cbo 24

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 23 1
B addShare() 0 53 5
A writeShareToDb() 0 8 1
B getShare() 0 24 10
A acceptShare() 0 46 4
A declineShare() 0 32 5
A processNotification() 0 7 1
A sendFeedbackToRemote() 0 32 5
A tryOCMEndPoint() 26 33 3
A stripPath() 0 4 1
A getMount() 0 7 1
A mountShare() 0 5 1
A getMountManager() 0 3 1
A setMountPoint() 0 16 1
B removeShare() 0 43 7
A removeReShares() 0 17 1
A removeUserShares() 0 20 3
A getOpenShares() 0 3 1
A getAcceptedShares() 0 3 1
A getShares() 0 23 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Manager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Manager, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Bjoern Schiessle <[email protected]>
6
 * @author Björn Schießle <[email protected]>
7
 * @author Daniel Hansson <[email protected]>
8
 * @author Joas Schilling <[email protected]>
9
 * @author Jörn Friedrich Dreyer <[email protected]>
10
 * @author Lukas Reschke <[email protected]>
11
 * @author Morris Jobke <[email protected]>
12
 * @author Robin Appelman <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 * @author Stefan Weil <[email protected]>
15
 *
16
 * @license AGPL-3.0
17
 *
18
 * This code is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU Affero General Public License, version 3,
20
 * as published by the Free Software Foundation.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
 * GNU Affero General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU Affero General Public License, version 3,
28
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
29
 *
30
 */
31
32
namespace OCA\Files_Sharing\External;
33
34
use OC\Files\Filesystem;
35
use OCA\Files_Sharing\Helper;
36
use OCP\Federation\ICloudFederationFactory;
37
use OCP\Federation\ICloudFederationProviderManager;
38
use OCP\Files;
39
use OCP\Files\Storage\IStorageFactory;
40
use OCP\Http\Client\IClientService;
41
use OCP\IDBConnection;
42
use OCP\IGroupManager;
43
use OCP\IUserManager;
44
use OCP\Notification\IManager;
45
use OCP\OCS\IDiscoveryService;
46
use OCP\Share;
47
48
class Manager {
49
	const STORAGE = '\OCA\Files_Sharing\External\Storage';
50
51
	/**
52
	 * @var string
53
	 */
54
	private $uid;
55
56
	/**
57
	 * @var IDBConnection
58
	 */
59
	private $connection;
60
61
	/**
62
	 * @var \OC\Files\Mount\Manager
63
	 */
64
	private $mountManager;
65
66
	/**
67
	 * @var IStorageFactory
68
	 */
69
	private $storageLoader;
70
71
	/**
72
	 * @var IClientService
73
	 */
74
	private $clientService;
75
76
	/**
77
	 * @var IManager
78
	 */
79
	private $notificationManager;
80
81
	/**
82
	 * @var IDiscoveryService
83
	 */
84
	private $discoveryService;
85
86
	/** @var ICloudFederationProviderManager */
87
	private $cloudFederationProviderManager;
88
89
	/** @var ICloudFederationFactory */
90
	private $cloudFederationFactory;
91
92
	/** @var IGroupManager  */
93
	private $groupManager;
94
95
	/** @var IUserManager */
96
	private $userManager;
97
98
	/**
99
	 * @param IDBConnection $connection
100
	 * @param \OC\Files\Mount\Manager $mountManager
101
	 * @param IStorageFactory $storageLoader
102
	 * @param IClientService $clientService
103
	 * @param IManager $notificationManager
104
	 * @param IDiscoveryService $discoveryService
105
	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
106
	 * @param ICloudFederationFactory $cloudFederationFactory
107
	 * @param IGroupManager $groupManager
108
	 * @param IUserManager $userManager
109
	 * @param string $uid
110
	 */
111
	public function __construct(IDBConnection $connection,
112
								\OC\Files\Mount\Manager $mountManager,
113
								IStorageFactory $storageLoader,
114
								IClientService $clientService,
115
								IManager $notificationManager,
116
								IDiscoveryService $discoveryService,
117
								ICloudFederationProviderManager $cloudFederationProviderManager,
118
								ICloudFederationFactory $cloudFederationFactory,
119
								IGroupManager $groupManager,
120
								IUserManager $userManager,
121
								$uid) {
122
		$this->connection = $connection;
123
		$this->mountManager = $mountManager;
124
		$this->storageLoader = $storageLoader;
125
		$this->clientService = $clientService;
126
		$this->uid = $uid;
127
		$this->notificationManager = $notificationManager;
128
		$this->discoveryService = $discoveryService;
129
		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
130
		$this->cloudFederationFactory = $cloudFederationFactory;
131
		$this->groupManager = $groupManager;
132
		$this->userManager = $userManager;
133
	}
134
135
	/**
136
	 * add new server-to-server share
137
	 *
138
	 * @param string $remote
139
	 * @param string $token
140
	 * @param string $password
141
	 * @param string $name
142
	 * @param string $owner
143
	 * @param int $shareType
144
	 * @param boolean $accepted
145
	 * @param string $user
146
	 * @param int $remoteId
147
	 * @param int $parent
148
	 * @return Mount|null
149
	 * @throws \Doctrine\DBAL\DBALException
150
	 */
151
	public function addShare($remote, $token, $password, $name, $owner, $shareType, $accepted=false, $user = null, $remoteId = -1, $parent = -1) {
152
153
		$user = $user ? $user : $this->uid;
154
		$accepted = $accepted ? 1 : 0;
155
		$name = Filesystem::normalizePath('/' . $name);
156
157
		if (!$accepted) {
158
			// To avoid conflicts with the mount point generation later,
159
			// we only use a temporary mount point name here. The real
160
			// mount point name will be generated when accepting the share,
161
			// using the original share item name.
162
			$tmpMountPointName = '{{TemporaryMountPointName#' . $name . '}}';
163
			$mountPoint = $tmpMountPointName;
164
			$hash = md5($tmpMountPointName);
165
			$data = [
166
				'remote'		=> $remote,
167
				'share_token'	=> $token,
168
				'password'		=> $password,
169
				'name'			=> $name,
170
				'owner'			=> $owner,
171
				'user'			=> $user,
172
				'mountpoint'	=> $mountPoint,
173
				'mountpoint_hash'	=> $hash,
174
				'accepted'		=> $accepted,
175
				'remote_id'		=> $remoteId,
176
				'share_type'    => $shareType,
177
			];
178
179
			$i = 1;
180
			while (!$this->connection->insertIfNotExist('*PREFIX*share_external', $data, ['user', 'mountpoint_hash'])) {
181
				// The external share already exists for the user
182
				$data['mountpoint'] = $tmpMountPointName . '-' . $i;
183
				$data['mountpoint_hash'] = md5($data['mountpoint']);
184
				$i++;
185
			}
186
			return null;
187
		}
188
189
		$mountPoint = Files::buildNotExistingFileName('/', $name);
190
		$mountPoint = Filesystem::normalizePath('/' . $mountPoint);
191
		$hash = md5($mountPoint);
192
193
		$this->writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType);
194
195
		$options = array(
196
			'remote'	=> $remote,
197
			'token'		=> $token,
198
			'password'	=> $password,
199
			'mountpoint'	=> $mountPoint,
200
			'owner'		=> $owner
201
		);
202
		return $this->mountShare($options);
203
	}
204
205
	/**
206
	 * write remote share to the database
207
	 *
208
	 * @param $remote
209
	 * @param $token
210
	 * @param $password
211
	 * @param $name
212
	 * @param $owner
213
	 * @param $user
214
	 * @param $mountPoint
215
	 * @param $hash
216
	 * @param $accepted
217
	 * @param $remoteId
218
	 * @param $parent
219
	 * @param $shareType
220
	 * @return bool
221
	 */
222
	private function writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType) {
223
		$query = $this->connection->prepare('
224
				INSERT INTO `*PREFIX*share_external`
225
					(`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`, `parent`, `share_type`)
226
				VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
227
			');
228
		return $query->execute(array($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType));
229
	}
230
231
	/**
232
	 * get share
233
	 *
234
	 * @param int $id share id
235
	 * @return mixed share of false
236
	 */
237
	public function getShare($id) {
238
		$getShare = $this->connection->prepare('
239
			SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`, `parent`, `share_type`, `password`, `mountpoint_hash`
240
			FROM  `*PREFIX*share_external`
241
			WHERE `id` = ?');
242
		$result = $getShare->execute(array($id));
243
244
		$share = $result ? $getShare->fetch() : [];
245
246
		$validShare = is_array($share) && isset($share['share_type']) && isset($share['user']);
247
248
		// check if the user is allowed to access it
249
		if ($validShare && (int)$share['share_type'] === Share::SHARE_TYPE_USER && $share['user'] === $this->uid) {
250
			return $share;
251
		} else if ($validShare && (int)$share['share_type'] === Share::SHARE_TYPE_GROUP) {
252
			$user = $this->userManager->get($this->uid);
253
			if ($this->groupManager->get($share['user'])->inGroup($user)) {
0 ignored issues
show
Bug introduced by
It seems like $user defined by $this->userManager->get($this->uid) on line 252 can be null; however, OCP\IGroup::inGroup() 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...
254
				return $share;
255
			}
256
		}
257
258
		return false;
259
260
	}
261
262
	/**
263
	 * accept server-to-server share
264
	 *
265
	 * @param int $id
266
	 * @return bool True if the share could be accepted, false otherwise
267
	 */
268
	public function acceptShare($id) {
269
270
		$share = $this->getShare($id);
271
		$result = false;
272
273
		if ($share) {
274
			\OC_Util::setupFS($this->uid);
275
			$shareFolder = Helper::getShareFolder();
276
			$mountPoint = Files::buildNotExistingFileName($shareFolder, $share['name']);
277
			$mountPoint = Filesystem::normalizePath($mountPoint);
278
			$hash = md5($mountPoint);
279
			$userShareAccepted = false;
280
281
			if((int)$share['share_type'] === Share::SHARE_TYPE_USER) {
282
				$acceptShare = $this->connection->prepare('
283
				UPDATE `*PREFIX*share_external`
284
				SET `accepted` = ?,
285
					`mountpoint` = ?,
286
					`mountpoint_hash` = ?
287
				WHERE `id` = ? AND `user` = ?');
288
				$userShareAccepted = $acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid));
289
			} else {
290
				$result = $this->writeShareToDb(
291
					$share['remote'],
292
					$share['share_token'],
293
					$share['password'],
294
					$share['name'],
295
					$share['owner'],
296
					$this->uid,
297
					$mountPoint, $hash, 1,
298
					$share['remote_id'],
299
					$id,
300
					$share['share_type']);
301
			}
302
			if ($userShareAccepted === true) {
303
				$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept');
304
				\OC_Hook::emit(Share::class, 'federated_share_added', ['server' => $share['remote']]);
305
				$result = true;
306
			}
307
		}
308
309
		// Make sure the user has no notification for something that does not exist anymore.
310
		$this->processNotification($id);
311
312
		return $result;
313
	}
314
315
	/**
316
	 * decline server-to-server share
317
	 *
318
	 * @param int $id
319
	 * @return bool True if the share could be declined, false otherwise
320
	 */
321
	public function declineShare($id) {
322
323
		$share = $this->getShare($id);
324
		$result = false;
325
326
		if ($share && (int)$share['share_type'] === Share::SHARE_TYPE_USER) {
327
			$removeShare = $this->connection->prepare('
328
				DELETE FROM `*PREFIX*share_external` WHERE `id` = ? AND `user` = ?');
329
			$removeShare->execute(array($id, $this->uid));
330
			$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
331
332
			$this->processNotification($id);
333
			$result = true;
334
		} else if ($share && (int)$share['share_type'] === Share::SHARE_TYPE_GROUP) {
335
			$result = $this->writeShareToDb(
336
				$share['remote'],
337
				$share['share_token'],
338
				$share['password'],
339
				$share['name'],
340
				$share['owner'],
341
				$this->uid,
342
				$share['mountpoint'],
343
				$share['mountpoint_hash'],
344
				0,
345
				$share['remote_id'],
346
				$id,
347
				$share['share_type']);
348
			$this->processNotification($id);
349
		}
350
351
		return $result;
352
	}
353
354
	/**
355
	 * @param int $remoteShare
356
	 */
357
	public function processNotification($remoteShare) {
358
		$filter = $this->notificationManager->createNotification();
359
		$filter->setApp('files_sharing')
360
			->setUser($this->uid)
361
			->setObject('remote_share', (int) $remoteShare);
362
		$this->notificationManager->markProcessed($filter);
363
	}
364
365
	/**
366
	 * inform remote server whether server-to-server share was accepted/declined
367
	 *
368
	 * @param string $remote
369
	 * @param string $token
370
	 * @param int $remoteId Share id on the remote host
371
	 * @param string $feedback
372
	 * @return boolean
373
	 */
374
	private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
375
376
		$result = $this->tryOCMEndPoint($remote, $token, $remoteId, $feedback);
377
378
		if($result === true) {
379
			return true;
380
		}
381
382
		$federationEndpoints = $this->discoveryService->discover($remote, 'FEDERATED_SHARING');
383
		$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
384
385
		$url = rtrim($remote, '/') . $endpoint . '/' . $remoteId . '/' . $feedback . '?format=' . Share::RESPONSE_FORMAT;
386
		$fields = array('token' => $token);
387
388
		$client = $this->clientService->newClient();
389
390
		try {
391
			$response = $client->post(
392
				$url,
393
				[
394
					'body' => $fields,
395
					'connect_timeout' => 10,
396
				]
397
			);
398
		} catch (\Exception $e) {
399
			return false;
400
		}
401
402
		$status = json_decode($response->getBody(), true);
403
404
		return ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200);
405
	}
406
407
	/**
408
	 * try send accept message to ocm end-point
409
	 *
410
	 * @param string $remoteDomain
411
	 * @param string $token
412
	 * @param $remoteId id of the share
413
	 * @param string $feedback
414
	 * @return bool
415
	 */
416
	protected function tryOCMEndPoint($remoteDomain, $token, $remoteId, $feedback) {
417
		switch ($feedback) {
418 View Code Duplication
			case 'accept':
419
				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
420
				$notification->setMessage(
421
					'SHARE_ACCEPTED',
422
					'file',
423
					$remoteId,
424
					[
425
						'sharedSecret' => $token,
426
						'message' => 'Recipient accept the share'
427
					]
428
429
				);
430
				return $this->cloudFederationProviderManager->sendNotification($remoteDomain, $notification);
431 View Code Duplication
			case 'decline':
432
				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
433
				$notification->setMessage(
434
					'SHARE_DECLINED',
435
					'file',
436
					$remoteId,
437
					[
438
						'sharedSecret' => $token,
439
						'message' => 'Recipient declined the share'
440
					]
441
442
				);
443
				return $this->cloudFederationProviderManager->sendNotification($remoteDomain, $notification);
444
		}
445
446
		return false;
447
448
	}
449
450
451
	/**
452
	 * remove '/user/files' from the path and trailing slashes
453
	 *
454
	 * @param string $path
455
	 * @return string
456
	 */
457
	protected function stripPath($path) {
458
		$prefix = '/' . $this->uid . '/files';
459
		return rtrim(substr($path, strlen($prefix)), '/');
460
	}
461
462
	public function getMount($data) {
463
		$data['manager'] = $this;
464
		$mountPoint = '/' . $this->uid . '/files' . $data['mountpoint'];
465
		$data['mountpoint'] = $mountPoint;
466
		$data['certificateManager'] = \OC::$server->getCertificateManager($this->uid);
467
		return new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader);
0 ignored issues
show
Documentation introduced by
$this->storageLoader is of type object<OCP\Files\Storage\IStorageFactory>, but the function expects a object<OC\Files\Storage\StorageFactory>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
468
	}
469
470
	/**
471
	 * @param array $data
472
	 * @return Mount
473
	 */
474
	protected function mountShare($data) {
475
		$mount = $this->getMount($data);
476
		$this->mountManager->addMount($mount);
477
		return $mount;
478
	}
479
480
	/**
481
	 * @return \OC\Files\Mount\Manager
482
	 */
483
	public function getMountManager() {
484
		return $this->mountManager;
485
	}
486
487
	/**
488
	 * @param string $source
489
	 * @param string $target
490
	 * @return bool
491
	 */
492
	public function setMountPoint($source, $target) {
493
		$source = $this->stripPath($source);
494
		$target = $this->stripPath($target);
495
		$sourceHash = md5($source);
496
		$targetHash = md5($target);
497
498
		$query = $this->connection->prepare('
499
			UPDATE `*PREFIX*share_external`
500
			SET `mountpoint` = ?, `mountpoint_hash` = ?
501
			WHERE `mountpoint_hash` = ?
502
			AND `user` = ?
503
		');
504
		$result = (bool)$query->execute(array($target, $targetHash, $sourceHash, $this->uid));
505
506
		return $result;
507
	}
508
509
	public function removeShare($mountPoint) {
510
511
		$mountPointObj = $this->mountManager->find($mountPoint);
512
		$id = $mountPointObj->getStorage()->getCache()->getId('');
513
514
		$mountPoint = $this->stripPath($mountPoint);
515
		$hash = md5($mountPoint);
516
517
		$getShare = $this->connection->prepare('
518
			SELECT `remote`, `share_token`, `remote_id`, `share_type`, `id`
519
			FROM  `*PREFIX*share_external`
520
			WHERE `mountpoint_hash` = ? AND `user` = ?');
521
		$result = $getShare->execute(array($hash, $this->uid));
522
523
		$share = $getShare->fetch();
524
		$getShare->closeCursor();
525
		if ($result && (int)$share['share_type'] === Share::SHARE_TYPE_USER) {
526
			try {
527
				$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
528
			} catch (\Exception $e) {
529
				// if we fail to notify the remote (probably cause the remote is down)
530
				// we still want the share to be gone to prevent undeletable remotes
531
			}
532
533
			$query = $this->connection->prepare('
534
			DELETE FROM `*PREFIX*share_external`
535
			WHERE `id` = ?
536
			');
537
			$result = (bool)$query->execute(array((int)$share['id']));
538
		} else if ($result && (int)$share['share_type'] === Share::SHARE_TYPE_GROUP) {
539
			$query = $this->connection->prepare('
540
				UPDATE `*PREFIX*share_external`
541
				SET `accepted` = ?
542
				WHERE `id` = ?');
543
			$result = (bool)$query->execute(array(0, (int)$share['id']));
544
		}
545
546
		if($result) {
547
			$this->removeReShares($id);
548
		}
549
550
		return $result;
551
	}
552
553
	/**
554
	 * remove re-shares from share table and mapping in the federated_reshares table
555
	 *
556
	 * @param $mountPointId
557
	 */
558
	protected function removeReShares($mountPointId) {
559
		$selectQuery = $this->connection->getQueryBuilder();
560
		$query = $this->connection->getQueryBuilder();
561
		$selectQuery->select('id')->from('share')
562
			->where($selectQuery->expr()->eq('file_source', $query->createNamedParameter($mountPointId)));
563
		$select = $selectQuery->getSQL();
564
565
566
		$query->delete('federated_reshares')
567
			->where($query->expr()->in('share_id', $query->createFunction('(' . $select . ')')));
568
		$query->execute();
569
570
		$deleteReShares = $this->connection->getQueryBuilder();
571
		$deleteReShares->delete('share')
572
			->where($deleteReShares->expr()->eq('file_source', $deleteReShares->createNamedParameter($mountPointId)));
573
		$deleteReShares->execute();
574
	}
575
576
	/**
577
	 * remove all shares for user $uid if the user was deleted
578
	 *
579
	 * @param string $uid
580
	 * @return bool
581
	 */
582
	public function removeUserShares($uid) {
583
		$getShare = $this->connection->prepare('
584
			SELECT `remote`, `share_token`, `remote_id`
585
			FROM  `*PREFIX*share_external`
586
			WHERE `user` = ?');
587
		$result = $getShare->execute(array($uid));
588
589
		if ($result) {
590
			$shares = $getShare->fetchAll();
591
			foreach($shares as $share) {
592
				$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
593
			}
594
		}
595
596
		$query = $this->connection->prepare('
597
			DELETE FROM `*PREFIX*share_external`
598
			WHERE `user` = ?
599
		');
600
		return (bool)$query->execute(array($uid));
601
	}
602
603
	/**
604
	 * return a list of shares which are not yet accepted by the user
605
	 *
606
	 * @return array list of open server-to-server shares
607
	 */
608
	public function getOpenShares() {
609
		return $this->getShares(false);
610
	}
611
612
	/**
613
	 * return a list of shares which are accepted by the user
614
	 *
615
	 * @return array list of accepted server-to-server shares
616
	 */
617
	public function getAcceptedShares() {
618
		return $this->getShares(true);
619
	}
620
621
	/**
622
	 * return a list of shares for the user
623
	 *
624
	 * @param bool|null $accepted True for accepted only,
625
	 *                            false for not accepted,
626
	 *                            null for all shares of the user
627
	 * @return array list of open server-to-server shares
628
	 */
629
	private function getShares($accepted) {
630
		$user = $this->userManager->get($this->uid);
631
		$groups = $this->groupManager->getUserGroups($user);
632
		$userGroups = [];
633
		foreach ($groups as $group) {
634
			$userGroups[] = $group->getGID();
635
		}
636
637
		$query = 'SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`
638
		          FROM `*PREFIX*share_external` 
639
				  WHERE (`user` = ? OR `user` IN (?))';
640
		$parameters = [$this->uid, implode(',',$userGroups)];
641
		if (!is_null($accepted)) {
642
			$query .= ' AND `accepted` = ?';
643
			$parameters[] = (int) $accepted;
644
		}
645
		$query .= ' ORDER BY `id` ASC';
646
647
		$shares = $this->connection->prepare($query);
648
		$result = $shares->execute($parameters);
649
650
		return $result ? $shares->fetchAll() : [];
651
	}
652
}
653