Completed
Pull Request — master (#32218)
by Thomas
50:41 queued 37:30
created

FedShareManager::createShare()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 9
dl 0
loc 63
rs 8.8072
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @author Viktar Dubiniuk <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2018, ownCloud GmbH
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace OCA\FederatedFileSharing;
23
24
use OCA\Files_Sharing\Activity;
25
use OCP\Activity\IManager as ActivityManager;
26
use OCP\Files\NotFoundException;
27
use OCP\IUserManager;
28
use OCP\Notification\IManager as NotificationManager;
29
use OCP\Share\IShare;
30
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
31
use Symfony\Component\EventDispatcher\GenericEvent;
32
33
/**
34
 * Class FedShareManager holds the share logic
35
 *
36
 * @package OCA\FederatedFileSharing
37
 */
38
class FedShareManager {
39
	const ACTION_URL = 'ocs/v1.php/apps/files_sharing/api/v1/remote_shares/pending/';
40
41
	/**
42
	 * @var FederatedShareProvider
43
	 */
44
	private $federatedShareProvider;
45
46
	/**
47
	 * @var Notifications
48
	 */
49
	private $notifications;
50
51
	/**
52
	 * @var IUserManager
53
	 */
54
	private $userManager;
55
56
	/**
57
	 * @var ActivityManager
58
	 */
59
	private $activityManager;
60
61
	/**
62
	 * @var NotificationManager
63
	 */
64
	private $notificationManager;
65
66
	/**
67
	 * @var AddressHandler
68
	 */
69
	private $addressHandler;
70
71
	/**
72
	 * @var EventDispatcherInterface
73
	 */
74
	private $eventDispatcher;
75
76
	/**
77
	 * FedShareManager constructor.
78
	 *
79
	 * @param FederatedShareProvider $federatedShareProvider
80
	 * @param Notifications $notifications
81
	 * @param IUserManager $userManager
82
	 * @param ActivityManager $activityManager
83
	 * @param NotificationManager $notificationManager
84
	 * @param AddressHandler $addressHandler
85
	 * @param EventDispatcherInterface $eventDispatcher
86
	 */
87
	public function __construct(FederatedShareProvider $federatedShareProvider,
88
								Notifications $notifications,
89
								IUserManager $userManager,
90
								ActivityManager $activityManager,
91
								NotificationManager $notificationManager,
92
								AddressHandler $addressHandler,
93
								EventDispatcherInterface $eventDispatcher
94
	) {
95
		$this->federatedShareProvider = $federatedShareProvider;
96
		$this->notifications = $notifications;
97
		$this->userManager = $userManager;
98
		$this->activityManager = $activityManager;
99
		$this->notificationManager = $notificationManager;
100
		$this->addressHandler = $addressHandler;
101
		$this->eventDispatcher = $eventDispatcher;
102
	}
103
104
	/**
105
	 * Create an incoming share
106
	 *
107
	 * @param string $shareWith
108
	 * @param string $remote
109
	 * @param int $remoteId
110
	 * @param string $owner
111
	 * @param string $name
112
	 * @param int $ownerFederatedId
113
	 * @param int $sharedByFederatedId
114
	 * @param string $sharedBy
115
	 * @param string $token
116
	 *
117
	 * @return void
118
	 */
119
	public function createShare($shareWith,
120
								$remote,
121
								$remoteId,
122
								$owner,
123
								$name,
124
								$ownerFederatedId,
125
								$sharedByFederatedId,
126
								$sharedBy,
127
								$token
128
	) {
129
		if ($ownerFederatedId === null) {
130
			$ownerFederatedId = $owner . '@' . $this->addressHandler->normalizeRemote($remote);
131
		}
132
		// if the owner of the share and the initiator are the same user
133
		// we also complete the federated share ID for the initiator
134
		if ($sharedByFederatedId === null && $owner === $sharedBy) {
135
			$sharedByFederatedId = $ownerFederatedId;
136
		}
137
138
		$shareId = $this->federatedShareProvider->addShare(
139
			$remote, $token, $name, $owner, $shareWith, $remoteId
140
		);
141
142
		$this->eventDispatcher->dispatch(
143
			'\OCA\FederatedFileSharing::remote_shareReceived',
144
			new GenericEvent(
145
				null,
146
				[
147
					'name' => $name,
148
					'targetuser' => $sharedByFederatedId,
149
					'owner' => $owner,
150
					'sharewith' => $shareWith,
151
					'sharedby' => $sharedBy,
152
					'remoteid' => $remoteId
153
				]
154
			)
155
		);
156
		$this->publishActivity(
157
			$shareWith,
158
			Activity::SUBJECT_REMOTE_SHARE_RECEIVED,
159
			[$ownerFederatedId, \trim($name, '/')],
160
			'files',
161
			'',
162
			'',
163
			''
164
		);
165
		$link = $this->getActionLink($shareId);
166
		$params = [$ownerFederatedId, $sharedByFederatedId, \trim($name, '/')];
167
		$notification = $this->createNotification($shareWith);
168
		$notification->setDateTime(new \DateTime())
169
			->setObject('remote_share', $shareId)
170
			->setSubject('remote_share', $params)
171
			->setMessage('remote_share', $params);
172
		$declineAction = $notification->createAction();
173
		$declineAction->setLabel('decline')
174
			->setLink($link, 'DELETE');
175
		$notification->addAction($declineAction);
176
		$acceptAction = $notification->createAction();
177
		$acceptAction->setLabel('accept')
178
			->setLink($link, 'POST');
179
		$notification->addAction($acceptAction);
180
		$this->notificationManager->notify($notification);
181
	}
182
183
	/**
184
	 * @param IShare $share
185
	 * @param int $remoteId
186
	 * @param string $shareWith
187
	 * @param int $permissions
188
	 *
189
	 * @return IShare
190
	 *
191
	 * @throws \OCP\Share\Exceptions\ShareNotFound
192
	 */
193
	public function reShare(IShare $share, $remoteId, $shareWith, $permissions) {
194
		$share->setPermissions($share->getPermissions() & $permissions);
195
		// the recipient of the initial share is now the initiator for the re-share
196
		$share->setSharedBy($share->getSharedWith());
197
		$share->setSharedWith($shareWith);
198
		$result = $this->federatedShareProvider->create($share);
199
		$this->federatedShareProvider->storeRemoteId(
200
			(int)$result->getId(),
201
			$remoteId
202
		);
203
		return $result;
204
	}
205
206
	/**
207
	 *
208
	 *
209
	 * @param IShare $share
210
	 *
211
	 * @throws \OCP\Files\InvalidPathException
212
	 * @throws \OCP\Files\NotFoundException
213
	 */
214 View Code Duplication
	public function acceptShare(IShare $share) {
215
		$uid = $this->getCorrectUid($share);
216
		$fileId = $share->getNode()->getId();
217
		list($file, $link) = $this->getFile($uid, $fileId);
218
		$this->publishActivity(
219
			$uid,
220
			Activity::SUBJECT_REMOTE_SHARE_ACCEPTED,
221
			[$share->getSharedWith(), \basename($file)],
222
			'files',
223
			$fileId,
224
			$file,
225
			$link
226
		);
227
		$this->notifyRemote($share, [$this->notifications, 'sendAcceptShare']);
228
	}
229
230
	/**
231
	 * Delete declined share and create a activity
232
	 *
233
	 * @param IShare $share
234
	 *
235
	 * @throws \OCP\Files\InvalidPathException
236
	 * @throws \OCP\Files\NotFoundException
237
	 */
238 View Code Duplication
	public function declineShare(IShare $share) {
239
		$this->notifyRemote($share, [$this->notifications, 'sendDeclineShare']);
240
		$uid = $this->getCorrectUid($share);
241
		$fileId = $share->getNode()->getId();
242
		$this->federatedShareProvider->removeShareFromTable($share);
243
		list($file, $link) = $this->getFile($uid, $fileId);
244
		$this->publishActivity(
245
			$uid,
246
			Activity::SUBJECT_REMOTE_SHARE_DECLINED,
247
			[$share->getSharedWith(), \basename($file)],
248
			'files',
249
			$fileId,
250
			$file,
251
			$link
252
		);
253
	}
254
255
	/**
256
	 * Unshare an item
257
	 *
258
	 * @param int $id
259
	 * @param string $token
260
	 *
261
	 * @return void
262
	 */
263
	public function unshare($id, $token) {
264
		$shareRow = $this->federatedShareProvider->unshare($id, $token);
265
		if ($shareRow === false) {
266
			return;
267
		}
268
		$remote = $this->addressHandler->normalizeRemote($shareRow['remote']);
269
		$owner = $shareRow['owner'] . '@' . $remote;
270
		$mountpoint = $shareRow['mountpoint'];
271
		$user = $shareRow['user'];
272
		if ($shareRow['accepted']) {
273
			$path = \trim($mountpoint, '/');
274
		} else {
275
			$path = \trim($shareRow['name'], '/');
276
		}
277
		$notification = $this->createNotification($user);
278
		$notification->setObject('remote_share', (int) $shareRow['id']);
279
		$this->notificationManager->markProcessed($notification);
280
		$this->publishActivity(
281
			$user,
282
			Activity::SUBJECT_REMOTE_SHARE_UNSHARED,
283
			[$owner, $path],
284
			'files',
285
			'',
286
			'',
287
			''
288
		);
289
	}
290
291
	/**
292
	 * @param IShare $share
293
	 *
294
	 * @return void
295
	 */
296
	public function revoke(IShare $share) {
297
		$this->federatedShareProvider->removeShareFromTable($share);
298
	}
299
300
	/**
301
	 * Update permissions
302
	 *
303
	 * @param IShare $share
304
	 * @param int $permissions
305
	 *
306
	 * @return void
307
	 */
308
	public function updatePermissions(IShare $share, $permissions) {
309
		$share->setPermissions($permissions);
310
		$this->federatedShareProvider->update($share);
311
	}
312
313
	/**
314
	 * @param IShare $share
315
	 * @param callable $callback
316
	 *
317
	 * @throws \OCP\Share\Exceptions\ShareNotFound
318
	 * @throws \OC\HintException
319
	 */
320
	protected function notifyRemote($share, $callback) {
321
		if ($share->getShareOwner() !== $share->getSharedBy()) {
322
			list(, $remote) = $this->addressHandler->splitUserRemote(
323
				$share->getSharedBy()
324
			);
325
			$remoteId = $this->federatedShareProvider->getRemoteId($share);
326
			$callback($remote, $remoteId, $share->getToken());
327
		}
328
	}
329
330
	/**
331
	 * Publish a new activity
332
	 *
333
	 * @param string $affectedUser
334
	 * @param string $subject
335
	 * @param array $subjectParams
336
	 * @param string $objectType
337
	 * @param int $objectId
338
	 * @param string $objectName
339
	 * @param string $link
340
	 *
341
	 * @return void
342
	 */
343
	protected function publishActivity($affectedUser,
344
									   $subject,
345
									   $subjectParams,
346
									   $objectType,
347
									   $objectId,
348
									   $objectName,
349
									   $link
350
	) {
351
		$event = $this->activityManager->generateEvent();
352
		$event->setApp(Activity::FILES_SHARING_APP)
353
			->setType(Activity::TYPE_REMOTE_SHARE)
354
			->setAffectedUser($affectedUser)
355
			->setSubject($subject, $subjectParams)
356
			->setObject($objectType, $objectId, $objectName)
357
			->setLink($link);
358
		$this->activityManager->publish($event);
359
	}
360
361
	/**
362
	 * Get a new notification
363
	 *
364
	 * @param string $uid
365
	 *
366
	 * @return \OCP\Notification\INotification
367
	 */
368
	protected function createNotification($uid) {
369
		$notification = $this->notificationManager->createNotification();
370
		$notification->setApp('files_sharing');
371
		$notification->setUser($uid);
372
		return $notification;
373
	}
374
375
	/**
376
	 * @param int $shareId
377
	 * @return string
378
	 */
379
	protected function getActionLink($shareId) {
380
		$urlGenerator = \OC::$server->getURLGenerator();
381
		$link = $urlGenerator->getAbsoluteURL(
382
			$urlGenerator->linkTo('', self::ACTION_URL . $shareId)
383
		);
384
		return $link;
385
	}
386
387
	/**
388
	 * Get file
389
	 *
390
	 * @param string $user
391
	 * @param int $fileSource
392
	 *
393
	 * @return array with internal path of the file and a absolute link to it
394
	 */
395
	protected function getFile($user, $fileSource) {
396
		\OC_Util::setupFS($user);
397
398
		try {
399
			$file = \OC\Files\Filesystem::getPath($fileSource);
400
		} catch (NotFoundException $e) {
401
			$file = null;
402
		}
403
		// FIXME:  use permalink here, see ViewController for reference
404
		$args = \OC\Files\Filesystem::is_dir($file)
405
			? ['dir' => $file]
406
			: ['dir' => \dirname($file), 'scrollto' => $file];
407
		$link = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
408
409
		return [$file, $link];
410
	}
411
412
	/**
413
	 * Check if we are the initiator or the owner of a re-share
414
	 * and return the correct UID
415
	 *
416
	 * @param IShare $share
417
	 *
418
	 * @return string
419
	 */
420
	protected function getCorrectUid(IShare $share) {
421
		if ($this->userManager->userExists($share->getShareOwner())) {
422
			return $share->getShareOwner();
423
		}
424
425
		return $share->getSharedBy();
426
	}
427
}
428