Completed
Pull Request — master (#32545)
by Tom
09:02
created

TransferRequestManager::newTransferRequest()   B

Complexity

Conditions 8
Paths 10

Size

Total Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 10
nop 3
dl 0
loc 55
rs 7.7373
c 0
b 0
f 0

How to fix   Long Method   

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
namespace OCA\Files\Service\TransferOwnership;
4
5
use OC\Command\CommandJob;
6
use OCA\Files\BackgroundJob\TransferOwnership;
7
use OCP\AppFramework\Db\DoesNotExistException;
8
use OCP\AppFramework\Utility\ITimeFactory;
9
use OCP\BackgroundJob\IJobList;
10
use OCP\Files\Folder;
11
use OCP\Files\IRootFolder;
12
use OCP\Files\NotFoundException;
13
use OCP\Files\NotPermittedException;
14
use OCP\Files\Storage\IPersistentLockingStorage;
15
use OCP\IL10N;
16
use OCP\IURLGenerator;
17
use OCP\IUser;
18
use OCP\IUserManager;
19
use OCP\L10N\IFactory;
20
use OCP\Lock\Persistent\ILock;
21
use OCP\Notification\IManager;
22
use OCP\Notification\INotification;
23
use OCP\Notification\INotifier;
24
use OCP\Util;
25
26
class TransferRequestManager implements INotifier {
27
28
	/** @var IRootFolder */
29
	protected $rootFolder;
30
	/** @var IManager */
31
	protected $notificationManager;
32
	/** @var IUserManager  */
33
	protected $userManager;
34
	/** @var ITimeFactory */
35
	protected $timeFactory;
36
	/** @var TransferRequestMapper  */
37
	protected $requestMapper;
38
	/** @var IURLGenerator  */
39
	protected $urlGenerator;
40
	/** @var IFactory */
41
	protected $factory;
42
	/** @var IJobList */
43
	protected $jobList;
44
45
	public function __construct(
46
		IRootFolder $rootFolder,
47
		IManager $notificationManager,
48
		IUserManager $userManager,
49
		ITimeFactory $timeFactory,
50
		TransferRequestMapper $requestMapper,
51
		IURLGenerator $urlGenerator,
52
		IFactory $factory,
53
		IJobList $jobList) {
54
		$this->rootFolder = $rootFolder;
55
		$this->notificationManager = $notificationManager;
56
		$this->userManager = $userManager;
57
		$this->timeFactory = $timeFactory;
58
		$this->requestMapper = $requestMapper;
59
		$this->urlGenerator = $urlGenerator;
60
		$this->factory = $factory;
61
		$this->jobList = $jobList;
62
	}
63
64
	/**
65
	 * @param IUser $sourceUser
66
	 * @param IUser $destinationUser
67
	 * @param $fileId
68
	 * @throws NotFoundException
69
	 * @throws \Exception
70
	 */
71
	public function newTransferRequest(IUser $sourceUser, IUser $destinationUser, $fileId) {
72
		// Cannot give to self
73
		if ($sourceUser->getUID() === $destinationUser->getUID()) {
74
			throw new \Exception('Cannot transfer to self');
75
		}
76
		// Check node exists
77
		$sourceFolder = $this->rootFolder->getById($fileId)[0];
78
		// Check source user owns the node
79
		if ($sourceFolder->getOwner()->getUID() !== $sourceUser->getUID()) {
80
			throw new NotPermittedException('Cannot move a file you dont own');
81
		}
82
		// Check the folder is on persistent lockable storage otherwise we can't do this in the background
83
		if (!$sourceFolder->getStorage() instanceof IPersistentLockingStorage) {
84
			throw new \Exception('Source folder storage not lockable');
85
		}
86
		// Check therer is no request with the same signature
87
		if (count($this->requestMapper->findRequestWithSameSignature($sourceUser->getUID(), $destinationUser->getUID(), $fileId)) > 0) {
88
			// There is
89
			throw new \Exception('There is already a request to transfer this file/folder');
90
		}
91
		// Check we are not trying to request a transfer for a folder that is inside a current request
92
		$folder = $sourceFolder;
93
		$fileids = [$folder->getId()];
94
		while($folder->getPath() !== '/') {
95
			$folder = $folder->getParent();
96
			$fileids[] = $folder->getId();
97
		}
98
		if (count($this->requestMapper->findOpenRequestForGivenFiles($fileids)) > 0) {
99
			throw new \Exception('This file/folder is already pending an existing transfer');
100
		}
101
102
		// Create the transfer request object
103
		$request = new TransferRequest();
104
		$request->setRequestedTime($this->timeFactory->getTime());
105
		$request->setSourceUserId($sourceUser->getUID());
106
		$request->setDestinationUserId($destinationUser->getUID());
107
		$request->setFileId($fileId);
108
		$request = $this->requestMapper->insert($request);
109
110
		/** @var IPersistentLockingStorage $storage */
111
		$storage = $sourceFolder->getStorage();
112
		try {
113
			$storage->lockNodePersistent($sourceFolder->getInternalPath(), [
114
				'depth' => ILock::LOCK_DEPTH_INFINITE,
115
				'token' => $this->getLockTokenFromRequest($request),
0 ignored issues
show
Compatibility introduced by
$request of type object<OCP\AppFramework\Db\Entity> is not a sub-type of object<OCA\Files\Service...ership\TransferRequest>. It seems like you assume a child class of the class OCP\AppFramework\Db\Entity to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
116
				'timeout' => 60*60*2 // 2 hours to allow a cron run
117
			]);
118
		} catch (\Exception $e) {
119
			// Cleanup transfer request and fail
120
			$this->requestMapper->delete($request);
121
			throw $e;
122
		}
123
124
		$this->sendRequestNotification($request);
0 ignored issues
show
Compatibility introduced by
$request of type object<OCP\AppFramework\Db\Entity> is not a sub-type of object<OCA\Files\Service...ership\TransferRequest>. It seems like you assume a child class of the class OCP\AppFramework\Db\Entity to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
125
	}
126
127
	public function acceptRequest(TransferRequest $request) {
128 View Code Duplication
		if ($request->getAcceptedTime() !== null || $request->getActionedTime() !== null || $request->getRejectedTime() !== null) {
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...
129
			throw new \Exception('Already actioned, accepted or rejected');
130
		}
131
		// Create a background job, update accepted time
132
		$request->setAcceptedTime($this->timeFactory->getTime());
133
		$this->requestMapper->update($request);
134
		$sourcePath = $this->rootFolder->getUserFolder(
135
			$request->getSourceUserId())->getById($request->getFileId())[0]->getInternalPath();
136
		$this->jobList->add(TransferOwnership::class, json_encode([
137
			'sourcePath' => $sourcePath,
138
			'sourceUser' => $request->getSourceUserId(),
139
			'destinationUser' => $request->getDestinationUserId()
140
		]));
141
		$notification = $this->notificationManager->createNotification();
142
		$notification->setApp('files')
143
			->setUser($request->getDestinationUserId())
144
			->setObject('transfer_request', $request->getId());
145
		$this->notificationManager->markProcessed($notification);
146
	}
147
148
	public function rejectRequest(TransferRequest $request) {
149
		// Cleanup the lock, save reject timestamp
150 View Code Duplication
		if ($request->getAcceptedTime() !== null || $request->getActionedTime() !== null || $request->getRejectedTime() !== null) {
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...
151
			throw new \Exception('Already actioned, accepted or rejected');
152
		}
153
		// Create a background job, update accepted time
154
		$request->setRejectedTime($this->timeFactory->getTime());
155
		$this->requestMapper->update($request);
156
		$notification = $this->notificationManager->createNotification();
157
		$notification->setApp('files')
158
			->setUser($request->getDestinationUserId())
159
			->setObject('transfer_request', $request->getId());
160
		$this->notificationManager->markProcessed($notification);
161
		$file = $this->rootFolder->getById($request->getFileId())[0];
162
		/** @var IPersistentLockingStorage $storage */
163
		$storage = $file->getStorage();
164
		$storage->unlockNodePersistent($file->getInternalPath(), ['token' => $this->getLockTokenFromRequest($request)]);
165
	}
166
167
	public function deleteRequest(TransferRequest $request) {
168
		// Cleanup the lock and the notification
169
		$this->requestMapper->delete($request);
170
		$notification = $this->notificationManager->createNotification();
171
		$notification->setApp('files')
172
			->setUser($request->getDestinationUserId())
173
			->setObject('transfer_request', $request->getId());
174
		$this->notificationManager->markProcessed($notification);
175
		$file = $this->rootFolder->getById($request->getFileId())[0];
176
		/** @var IPersistentLockingStorage $storage */
177
		$storage = $file->getStorage();
178
		$storage->unlockNodePersistent($file->getInternalPath(), ['token' => $this->getLockTokenFromRequest($request)]);
179
	}
180
181
182
	/**
183
	 * @param TransferRequest $request the request object
184
	 */
185
	protected function sendRequestNotification(TransferRequest $request) {
186
		$time = new \DateTime();
187
		$time->setTimestamp($this->timeFactory->getTime());
188
		$notification = $this->notificationManager->createNotification();
189
		$notification->setApp('files')
190
			->setUser($request->getDestinationUserId())
191
			->setDateTime($time)
192
			->setObject('transfer_request', $request->getId());
193
194
		$notification->setIcon(
195
			$this->urlGenerator->imagePath('core', 'actions/give.svg')
196
		);
197
198
		$sourceUser = $this->userManager->get($request->getSourceUserId());
199
		$folder = $this->rootFolder->getById($request->getFileId())[0];
200
		$notification->setSubject("new_transfer_request");
201
		$notification->setMessage("new_transfer_request", [$sourceUser->getDisplayName(), $folder->getName(), Util::humanFileSize($folder->getSize())]);
202
203
		$endpoint = $this->urlGenerator->linkToRouteAbsolute(
204
			'files.Transfer.accept',
205
			['requestId' => $request->getId()]
206
		);
207
		$declineAction = $notification->createAction();
208
		$declineAction->setLabel('reject');
209
		$declineAction->setLink($endpoint, 'DELETE');
210
		$notification->addAction($declineAction);
211
212
		$acceptAction = $notification->createAction();
213
		$acceptAction->setLabel('accept');
214
		$acceptAction->setLink($endpoint, 'POST');
215
		$acceptAction->setPrimary(true);
216
		$notification->addAction($acceptAction);
217
218
		$this->notificationManager->notify($notification);
219
	}
220
221
	public function prepare(INotification $notification, $languageCode) {
222
		if ($notification->getApp() !== 'files') {
223
			throw new \InvalidArgumentException();
224
		}
225
226
		// Read the language from the notification
227
		$l = $this->factory->get('files', $languageCode);
228
229
		switch ($notification->getObjectType()) {
230
			case 'transfer_request':
231
				$requestId = $notification->getObjectId();
232
				try {
233
					$this->requestMapper->findById($requestId);
234
				} catch (DoesNotExistException $ex) {
235
					$this->notificationManager->markProcessed($notification);
236
					throw new \InvalidArgumentException();
237
				}
238
				return $this->formatNotification($notification, $l);
239
240
			default:
241
				throw new \InvalidArgumentException();
242
		}
243
	}
244
245
	protected function formatNotification(INotification $notification, IL10N $l) {
246
		switch($notification->getObjectType()) {
247
			case 'transfer_request':
248
				$notification->setParsedSubject((string) $l->t('A user would like to transfer a folder to you'));
249
				$notification->setParsedMessage(
250
					(string) $l->t(
251
						'"%1$s" requested to transfer "%2$s" to you (%3$s)"',
252
						$notification->getMessageParameters())
253
				);
254 View Code Duplication
				foreach ($notification->getActions() as $action) {
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...
255
					switch ($action->getLabel()) {
256
						case 'accept':
257
							$action->setParsedLabel(
258
								(string) $l->t('Accept')
259
							);
260
							break;
261
						case 'reject':
262
							$action->setParsedLabel(
263
								(string) $l->t('Decline')
264
							);
265
							break;
266
					}
267
					$notification->addParsedAction($action);
268
				}
269
				return $notification;
270
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
271 View Code Duplication
			case 'transfer_request_actioned_source':
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...
272
				$notification->setParsedSubject((string) $l->t('Transfer completed'));
273
				$notification->setParsedMessage(
274
					(string) $l->t(
275
						'"%1$s" accepted your transfer of "%2$s" and it was completed',
276
						$notification->getMessageParameters())
277
				);
278
				return $notification;
279
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
280 View Code Duplication
			case 'transfer_request_actioned_destination':
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...
281
				$notification->setParsedSubject((string) $l->t('Transfer completed'));
282
				$notification->setParsedMessage(
283
					(string) $l->t(
284
						'"%1$s" was transferred to you from "%2$s"',
285
						$notification->getMessageParameters())
286
				);
287
				return $notification;
288
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
289 View Code Duplication
			case 'transfer_request_failed_destination':
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...
290
				$notification->setParsedSubject((string) $l->t('Transfer failed'));
291
				$notification->setParsedMessage(
292
					(string) $l->t(
293
						'The transfer of "%1$s" from "%2$s failed. Ask the sender to try again."',
294
						$notification->getMessageParameters())
295
				);
296
				return $notification;
297
			break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
298 View Code Duplication
			case 'transfer_request_failed_source':
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...
299
				$notification->setParsedSubject((string) $l->t('Transfer failed'));
300
				$notification->setParsedMessage(
301
					(string) $l->t(
302
						'The transfer of "%1$s" to "%2$s" failed with message: "%3$s"',
303
						$notification->getMessageParameters())
304
				);
305
				return $notification;
306
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
307
			default:
308
				throw new \InvalidArgumentException('Not a notifcation that can be formatted by this class');
309
		}
310
311
	}
312
313
	public function actionRequest(TransferRequest $request) {
314
		$request->setActionedTime($this->timeFactory->getTime());
315
		$this->requestMapper->update($request);
316
		// Notify the source user it was accepted
317
		$this->notifyActioned($request);
318
	}
319
320
	/**
321
	 * Cleanup and notify
322
	 * @param TransferRequest $request
323
	 * @throws NotFoundException
324
	 * @throws \OCP\Files\InvalidPathException
325
	 */
326
	public function actionRequestFailure(TransferRequest $request, $message = null) {
327
		// Notify the users that it failed
328
		$this->notifyActionedFailure($request, $message);
329
		$this->cleanupRequest($request);
330
331
	}
332
333
	/**
334
	 * Tell the source user and destination user that the transfer has happened
335
	 * @param TransferRequest $request
336
	 * @throws NotFoundException
337
	 * @throws \OCP\Files\InvalidPathException
338
	 */
339 View Code Duplication
	public function notifyActioned(TransferRequest $request) {
340
		// Set to now
341
		$time = new \DateTime();
342
		$time->setTimestamp($request->getActionedTime());
343
		$notification = $this->notificationManager->createNotification();
344
		$notification->setApp('files')
345
			->setUser($request->getSourceUserId())
346
			->setDateTime($time)
347
			->setObject('transfer_request', $request->getId());
348
349
		$notification->setIcon(
350
			$this->urlGenerator->imagePath('core', 'actions/give.svg')
351
		);
352
353
		$destinationUser = $this->userManager->get($request->getDestinationUserId());
354
		$folder = $this->rootFolder->getById($request->getFileId())[0];
355
		$notification->setSubject("transfer_request_actioned_source");
356
		$notification->setMessage("transfer_request_actioned_source", [$destinationUser->getDisplayName(), $folder->getName()]);
357
		$this->notificationManager->notify($notification);
358
359
		// Set to now
360
		$time = new \DateTime();
361
		$time->setTimestamp($request->getActionedTime());
362
		$notification = $this->notificationManager->createNotification();
363
		$notification->setApp('files')
364
			->setUser($request->getDestinationUserId())
365
			->setDateTime($time)
366
			->setObject('transfer_request', $request->getId());
367
368
		$notification->setIcon(
369
			$this->urlGenerator->imagePath('core', 'actions/give.svg')
370
		);
371
372
		$sourceUser = $this->userManager->get($request->getSourceUserId());
373
		$folder = $this->rootFolder->getById($request->getFileId())[0];
374
		$notification->setSubject("transfer_request_actioned_destination");
375
		$notification->setMessage("transfer_request_actioned_destination", [$folder->getName(), $sourceUser->getDisplayName()]);
376
		$this->notificationManager->notify($notification);
377
	}
378
379
	/**
380
	 * Tell the source user and destination user that the transfer failed
381
	 * @param TransferRequest $request
382
	 * @throws NotFoundException
383
	 * @throws \OCP\Files\InvalidPathException
384
	 */
385 View Code Duplication
	public function notifyActionedFailure(TransferRequest $request, $message = null) {
386
		// Set to now
387
		$time = new \DateTime();
388
		$time->setTimestamp($this->timeFactory->getTime());
389
		$notification = $this->notificationManager->createNotification();
390
		$notification->setApp('files')
391
			->setUser($request->getSourceUserId())
392
			->setDateTime($time)
393
			->setObject('transfer_request', $request->getId());
394
395
		$notification->setIcon(
396
			$this->urlGenerator->imagePath('core', 'actions/give.svg')
397
		);
398
399
		$destinationUser = $this->userManager->get($request->getDestinationUserId());
400
		$folder = $this->rootFolder->getById($request->getFileId())[0];
401
		$notification->setSubject("transfer_request_failed_source");
402
		$notification->setMessage("transfer_request_failed_source", [$folder->getName(), $destinationUser->getDisplayName(), $message]);
403
		$this->notificationManager->notify($notification);
404
405
		// Set to now
406
		$time = new \DateTime();
407
		$time->setTimestamp($request->getActionedTime());
408
		$notification = $this->notificationManager->createNotification();
409
		$notification->setApp('files')
410
			->setUser($request->getDestinationUserId())
411
			->setDateTime($time)
412
			->setObject('transfer_request', $request->getId());
413
414
		$notification->setIcon(
415
			$this->urlGenerator->imagePath('core', 'actions/give.svg')
416
		);
417
418
		$sourceUser = $this->userManager->get($request->getSourceUserId());
419
		$folder = $this->rootFolder->getById($request->getFileId())[0];
420
		$notification->setSubject("transfer_request_failed_destination");
421
		$notification->setMessage("transfer_request_failed_destination", [$folder->getName(), $sourceUser->getDisplayName()]);
422
		$this->notificationManager->notify($notification);
423
	}
424
425
	/**
426
	 * Background job for cleaning up old requests, removes notifications, request and locks
427
	 */
428
	public function cleanup() {
429
		// Delete request that are older than 24 hours
430
		$oldRequests = $this->requestMapper->findOpenRequestsOlderThan(1);
431
		/** @var TransferRequest $request */
432
		foreach ($oldRequests as $request) {
433
			$this->cleanupRequest($request);
434
		}
435
	}
436
437
	/**
438
	 * Delete request, delete lock, and delete requested notification
439
	 * @param TransferRequest $request
440
	 */
441
	protected function cleanupRequest(TransferRequest $request) {
442
		// Remove the lock
443
		try {
444
			$file = $this->rootFolder->getById($request->getFileId())[0];
445
			/** @var IPersistentLockingStorage $storage */
446
			$storage = $file->getStorage();
447
			$storage->unlockNodePersistent($file->getInternalPath(), $this->getLockTokenFromRequest($request));
0 ignored issues
show
Documentation introduced by
$this->getLockTokenFromRequest($request) is of type string, but the function expects a array.

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...
448
		} catch (\Exception $e) {
449
			\OC::$server->getLogger()->logException($e, ['app' => 'files']);
450
		}
451
		// Now remove the request
452
		$this->requestMapper->delete($request);
453
		// And lets remove the notification to save confusion
454
		$notification = $this->notificationManager->createNotification();
455
		$notification->setApp('files')
456
			->setUser($request->getDestinationUserId())
457
			->setObject('transfer_request', $request->getId());
458
		$this->notificationManager->markProcessed($notification);
459
	}
460
461
	/**
462
	 * Helper to get the lock token id associated with a request
463
	 * @param TransferRequest $request
464
	 * @return string
465
	 */
466
	protected function getLockTokenFromRequest(TransferRequest $request) {
467
		return 'transfer-request-'.$request->getId();
468
	}
469
470
	/**
471
	 * Helper to get a request object from the mapper without another dep injection
472
	 * @param $requestId
473
	 * @return TransferRequest|\OCP\AppFramework\Db\Entity
474
	 * @throws DoesNotExistException
475
	 * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
476
	 */
477
	public function getRequestById($requestId) {
478
		return $this->requestMapper->findById($requestId);
479
	}
480
481
482
}