Cancelled
Push — stable9 ( 288b72...c5926c )
by Lukas
919:15 queued 919:15
created

FilesHooks   C

Complexity

Total Complexity 78

Size/Duplication

Total Lines 523
Duplicated Lines 4.21 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 80.47%

Importance

Changes 9
Bugs 0 Features 3
Metric Value
wmc 78
c 9
b 0
f 3
lcom 1
cbo 2
dl 22
loc 523
ccs 206
cts 256
cp 0.8047
rs 5.4563

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A getCurrentUser() 0 3 1
A fileUpdate() 0 3 1
A fileDelete() 0 3 1
A fileRestore() 0 3 1
A getUserPathsFromPath() 0 3 1
A fileCreate() 0 7 2
C addNotificationsForFileAction() 0 33 7
A getSourcePathAndOwner() 0 16 3
B share() 11 11 6
B unShare() 11 11 6
A shareFileOrFolderWithUser() 0 23 3
B shareFileOrFolderWithGroup() 0 29 4
C addNotificationsForGroupUsers() 0 32 7
A fixPathsForShareExceptions() 0 14 2
B shareFileOrFolderByLink() 0 32 5
A shareNotificationForSharer() 0 16 3
A reshareNotificationForSharer() 0 16 3
D shareNotificationForOriginalOwners() 0 40 9
C addNotificationsForUser() 0 34 12

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 FilesHooks 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 FilesHooks, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @author Frank Karlitschek <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Thomas Müller <[email protected]>
6
 *
7
 * @copyright Copyright (c) 2016, ownCloud, Inc.
8
 * @license AGPL-3.0
9
 *
10
 * This code is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License, version 3,
12
 * as published by the Free Software Foundation.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License, version 3,
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
21
 *
22
 */
23
24
namespace OCA\Activity;
25
26
use OC\Files\Filesystem;
27
use OC\Files\View;
28
use OCA\Activity\Extension\Files;
29
use OCA\Activity\Extension\Files_Sharing;
30
use OCP\Activity\IManager;
31
use OCP\Files\Mount\IMountPoint;
32
use OCP\Files\NotFoundException;
33
use OCP\IDBConnection;
34
use OCP\IGroup;
35
use OCP\IGroupManager;
36
use OCP\IUser;
37
use OCP\Share;
38
use OCP\Util;
39
40
/**
41
 * The class to handle the filesystem hooks
42
 */
43
class FilesHooks {
44
	const USER_BATCH_SIZE = 50;
45
46
	/** @var \OCP\Activity\IManager */
47
	protected $manager;
48
49
	/** @var \OCA\Activity\Data */
50
	protected $activityData;
51
52
	/** @var \OCA\Activity\UserSettings */
53
	protected $userSettings;
54
55
	/** @var \OCP\IGroupManager */
56
	protected $groupManager;
57
58
	/** @var \OCP\IDBConnection */
59
	protected $connection;
60
61
	/** @var \OC\Files\View */
62
	protected $view;
63
64
	/** @var string|false */
65
	protected $currentUser;
66
67
	/**
68
	 * Constructor
69
	 *
70
	 * @param IManager $manager
71
	 * @param Data $activityData
72
	 * @param UserSettings $userSettings
73
	 * @param IGroupManager $groupManager
74
	 * @param View $view
75
	 * @param IDBConnection $connection
76
	 * @param string|false $currentUser
77
	 */
78 47
	public function __construct(IManager $manager, Data $activityData, UserSettings $userSettings, IGroupManager $groupManager, View $view, IDBConnection $connection, $currentUser) {
79 47
		$this->manager = $manager;
80 47
		$this->activityData = $activityData;
81 47
		$this->userSettings = $userSettings;
82 47
		$this->groupManager = $groupManager;
83 47
		$this->view = $view;
84 47
		$this->connection = $connection;
85 47
		$this->currentUser = $currentUser;
86 47
	}
87
88
	/**
89
	 * @return string|false Current UserID if logged in, false otherwise
90
	 */
91 2
	protected function getCurrentUser() {
92 2
		return $this->currentUser;
93
	}
94
95
	/**
96
	 * Store the create hook events
97
	 * @param string $path Path of the file that has been created
98
	 */
99 2
	public function fileCreate($path) {
100 2
		if ($this->getCurrentUser() !== false) {
101 1
			$this->addNotificationsForFileAction($path, Files::TYPE_SHARE_CREATED, 'created_self', 'created_by');
102 1
		} else {
103 1
			$this->addNotificationsForFileAction($path, Files::TYPE_SHARE_CREATED, '', 'created_public');
104
		}
105 2
	}
106
107
	/**
108
	 * Store the update hook events
109
	 * @param string $path Path of the file that has been modified
110
	 */
111 1
	public function fileUpdate($path) {
112 1
		$this->addNotificationsForFileAction($path, Files::TYPE_SHARE_CHANGED, 'changed_self', 'changed_by');
113 1
	}
114
115
	/**
116
	 * Store the delete hook events
117
	 * @param string $path Path of the file that has been deleted
118
	 */
119 1
	public function fileDelete($path) {
120 1
		$this->addNotificationsForFileAction($path, Files::TYPE_SHARE_DELETED, 'deleted_self', 'deleted_by');
121 1
	}
122
123
	/**
124
	 * Store the restore hook events
125
	 * @param string $path Path of the file that has been restored
126
	 */
127 1
	public function fileRestore($path) {
128 1
		$this->addNotificationsForFileAction($path, Files::TYPE_SHARE_RESTORED, 'restored_self', 'restored_by');
129 1
	}
130
131
	/**
132
	 * Creates the entries for file actions on $file_path
133
	 *
134
	 * @param string $filePath         The file that is being changed
135
	 * @param int    $activityType     The activity type
136
	 * @param string $subject          The subject for the actor
137
	 * @param string $subjectBy        The subject for other users (with "by $actor")
138
	 */
139 3
	protected function addNotificationsForFileAction($filePath, $activityType, $subject, $subjectBy) {
140
		// Do not add activities for .part-files
141 3
		if (substr($filePath, -5) === '.part') {
142 1
			return;
143
		}
144
145 2
		list($filePath, $uidOwner, $fileId) = $this->getSourcePathAndOwner($filePath);
146 2
		$affectedUsers = $this->getUserPathsFromPath($filePath, $uidOwner);
147 2
		$filteredStreamUsers = $this->userSettings->filterUsersBySetting(array_keys($affectedUsers), 'stream', $activityType);
148 2
		$filteredEmailUsers = $this->userSettings->filterUsersBySetting(array_keys($affectedUsers), 'email', $activityType);
149
150 2
		foreach ($affectedUsers as $user => $path) {
151 2
			if (empty($filteredStreamUsers[$user]) && empty($filteredEmailUsers[$user])) {
152 2
				continue;
153
			}
154
155 2
			if ($user === $this->currentUser) {
156 1
				$userSubject = $subject;
157 1
				$userParams = [[$fileId => $path]];
158 1
			} else {
159 1
				$userSubject = $subjectBy;
160 1
				$userParams = [[$fileId => $path], $this->currentUser];
161
			}
162
163 2
			$this->addNotificationsForUser(
164 2
				$user, $userSubject, $userParams,
165 2
				$fileId, $path, true,
166 2
				!empty($filteredStreamUsers[$user]),
167 2
				!empty($filteredEmailUsers[$user]) ? $filteredEmailUsers[$user] : 0,
168
				$activityType
169 2
			);
170 2
		}
171 2
	}
172
173
	/**
174
	 * Returns a "username => path" map for all affected users
175
	 *
176
	 * @param string $path
177
	 * @param string $uidOwner
178
	 * @return array
179
	 */
180
	protected function getUserPathsFromPath($path, $uidOwner) {
181
		return Share::getUsersSharingFile($path, $uidOwner, true, true);
182
	}
183
184
	/**
185
	 * Return the source
186
	 *
187
	 * @param string $path
188
	 * @return array
189
	 */
190
	protected function getSourcePathAndOwner($path) {
191
		$uidOwner = Filesystem::getOwner($path);
192
		$fileId = 0;
193
194
		if ($uidOwner !== $this->currentUser) {
195
			Filesystem::initMountPoints($uidOwner);
196
		}
197
		$info = Filesystem::getFileInfo($path);
198
		if ($info !== false) {
199
			$ownerView = new View('/' . $uidOwner . '/files');
200
			$fileId = (int) $info['fileid'];
201
			$path = $ownerView->getPath($fileId);
202
		}
203
204
		return array($path, $uidOwner, $fileId);
205
	}
206
207
	/**
208
	 * Manage sharing events
209
	 * @param array $params The hook params
210
	 */
211 3 View Code Duplication
	public function share($params) {
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...
212 3
		if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
213 3
			if ((int) $params['shareType'] === Share::SHARE_TYPE_USER) {
214 1
				$this->shareFileOrFolderWithUser($params['shareWith'], (int) $params['fileSource'], $params['itemType'], $params['fileTarget'], true);
215 3
			} else if ((int) $params['shareType'] === Share::SHARE_TYPE_GROUP) {
216 1
				$this->shareFileOrFolderWithGroup($params['shareWith'], (int) $params['fileSource'], $params['itemType'], $params['fileTarget'], (int) $params['id'], true);
217 2
			} else if ((int) $params['shareType'] === Share::SHARE_TYPE_LINK) {
218 1
				$this->shareFileOrFolderByLink((int) $params['fileSource'], $params['itemType'], $params['uidOwner'], true);
219 1
			}
220 3
		}
221 3
	}
222
223
	/**
224
	 * Manage sharing events
225
	 * @param array $params The hook params
226
	 */
227 View Code Duplication
	public function unShare($params) {
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...
228
		if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
229
			if ((int) $params['shareType'] === Share::SHARE_TYPE_USER) {
230
				$this->shareFileOrFolderWithUser($params['shareWith'], (int) $params['fileSource'], $params['itemType'], $params['fileTarget'], false);
231
			} else if ((int) $params['shareType'] === Share::SHARE_TYPE_GROUP) {
232
				$this->shareFileOrFolderWithGroup($params['shareWith'], (int) $params['fileSource'], $params['itemType'], $params['fileTarget'], (int) $params['id'], false);
233
			} else if ((int) $params['shareType'] === Share::SHARE_TYPE_LINK) {
234
				$this->shareFileOrFolderByLink((int) $params['fileSource'], $params['itemType'], $params['uidOwner'], false);
235
			}
236
		}
237
	}
238
239
	/**
240
	 * Sharing a file or folder with a user
241
	 *
242
	 * @param string $shareWith
243
	 * @param int $fileSource File ID that is being shared
244
	 * @param string $itemType File type that is being shared (file or folder)
245
	 * @param string $fileTarget File path
246
	 * @param bool $isSharing True if sharing, false if unsharing
247
	 */
248 2
	protected function shareFileOrFolderWithUser($shareWith, $fileSource, $itemType, $fileTarget, $isSharing) {
249 2
		if ($isSharing) {
250 2
			$actionSharer = 'shared_user_self';
251 2
			$actionOwner = 'reshared_user_by';
252 2
			$actionUser = 'shared_with_by';
253 2
		} else {
254
			$actionSharer = 'unshared_user_self';
255
			$actionOwner = 'unshared_user_by';
256
			$actionUser = 'unshared_by';
257
		}
258
259
		// User performing the share
260 2
		$this->shareNotificationForSharer($actionSharer, $shareWith, $fileSource, $itemType);
261 2
		$this->shareNotificationForOriginalOwners($this->currentUser, $actionOwner, $shareWith, $fileSource, $itemType);
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\FilesHooks:...tionForOriginalOwners() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
262
263
		// New shared user
264 2
		$this->addNotificationsForUser(
265 2
			$shareWith, $actionUser, [[$fileSource => $fileTarget], $this->currentUser],
266 2
			(int) $fileSource, $fileTarget, ($itemType === 'file'),
267 2
			$this->userSettings->getUserSetting($shareWith, 'stream', Files_Sharing::TYPE_SHARED),
268 2
			$this->userSettings->getUserSetting($shareWith, 'email', Files_Sharing::TYPE_SHARED) ? $this->userSettings->getUserSetting($shareWith, 'setting', 'batchtime') : 0
269 2
		);
270 2
	}
271
272
	/**
273
	 * Sharing a file or folder with a group
274
	 *
275
	 * @param string $shareWith
276
	 * @param int $fileSource File ID that is being shared
277
	 * @param string $itemType File type that is being shared (file or folder)
278
	 * @param string $fileTarget File path
279
	 * @param int $shareId The Share ID of this share
280
	 * @param bool $isSharing True if sharing, false if unsharing
281
	 */
282 6
	protected function shareFileOrFolderWithGroup($shareWith, $fileSource, $itemType, $fileTarget, $shareId, $isSharing) {
283 6
		if ($isSharing) {
284 6
			$actionSharer = 'shared_group_self';
285 6
			$actionOwner = 'reshared_group_by';
286 6
			$actionUser = 'shared_with_by';
287 6
		} else {
288
			$actionSharer = 'unshared_group_self';
289
			$actionOwner = 'unshared_group_by';
290
			$actionUser = 'unshared_by';
291
		}
292
293
		// Members of the new group
294 6
		$group = $this->groupManager->get($shareWith);
295 6
		if (!($group instanceof IGroup)) {
0 ignored issues
show
Bug introduced by
The class OCP\IGroup does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
296 1
			return;
297
		}
298
299
		// User performing the share
300 5
		$this->shareNotificationForSharer($actionSharer, $shareWith, $fileSource, $itemType);
301 5
		$this->shareNotificationForOriginalOwners($this->currentUser, $actionOwner, $shareWith, $fileSource, $itemType);
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\FilesHooks:...tionForOriginalOwners() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
302
303 5
		$offset = 0;
304 5
		$users = $group->searchUsers('', self::USER_BATCH_SIZE, $offset);
305 5
		while (!empty($users)) {
306 4
			$this->addNotificationsForGroupUsers($users, $actionUser, $fileSource, $itemType, $fileTarget, $shareId);
307 4
			$offset += self::USER_BATCH_SIZE;
308 4
			$users = $group->searchUsers('', self::USER_BATCH_SIZE, $offset);
309 4
		}
310 5
	}
311
312
	/**
313
	 * @param IUser[] $usersInGroup
314
	 * @param string $actionUser
315
	 * @param int $fileSource File ID that is being shared
316
	 * @param string $itemType File type that is being shared (file or folder)
317
	 * @param string $fileTarget File path
318
	 * @param int $shareId The Share ID of this share
319
	 */
320 4
	protected function addNotificationsForGroupUsers(array $usersInGroup, $actionUser, $fileSource, $itemType, $fileTarget, $shareId) {
321 4
		$affectedUsers = [];
322
323 4
		foreach ($usersInGroup as $user) {
324 4
			$affectedUsers[$user->getUID()] = $fileTarget;
325 4
		}
326
327
		// Remove the triggering user, we already managed his notifications
328 4
		unset($affectedUsers[$this->currentUser]);
329
330 4
		if (empty($affectedUsers)) {
331 1
			return;
332
		}
333
334 3
		$userIds = array_keys($affectedUsers);
335 3
		$filteredStreamUsersInGroup = $this->userSettings->filterUsersBySetting($userIds, 'stream', Files_Sharing::TYPE_SHARED);
336 3
		$filteredEmailUsersInGroup = $this->userSettings->filterUsersBySetting($userIds, 'email', Files_Sharing::TYPE_SHARED);
337
338 3
		$affectedUsers = $this->fixPathsForShareExceptions($affectedUsers, $shareId);
339 3
		foreach ($affectedUsers as $user => $path) {
340 3
			if (empty($filteredStreamUsersInGroup[$user]) && empty($filteredEmailUsersInGroup[$user])) {
341 2
				continue;
342
			}
343
344 1
			$this->addNotificationsForUser(
345 1
				$user, $actionUser, [[$fileSource => $path], $this->currentUser],
346 1
				$fileSource, $path, ($itemType === 'file'),
347 1
				!empty($filteredStreamUsersInGroup[$user]),
348 1
				!empty($filteredEmailUsersInGroup[$user]) ? $filteredEmailUsersInGroup[$user] : 0
349 1
			);
350 3
		}
351 3
	}
352
353
	/**
354
	 * Check when there was a naming conflict and the target is different
355
	 * for some of the users
356
	 *
357
	 * @param array $affectedUsers
358
	 * @param int $shareId
359
	 * @return mixed
360
	 */
361
	protected function fixPathsForShareExceptions(array $affectedUsers, $shareId) {
362
		$queryBuilder = $this->connection->getQueryBuilder();
363
		$queryBuilder->select(['share_with', 'file_target'])
364
			->from('share')
365
			->where($queryBuilder->expr()->eq('parent', $queryBuilder->createParameter('parent')))
366
			->setParameter('parent', (int) $shareId);
367
		$query = $queryBuilder->execute();
368
369
		while ($row = $query->fetch()) {
370
			$affectedUsers[$row['share_with']] = $row['file_target'];
371
		}
372
373
		return $affectedUsers;
374
	}
375
376
	/**
377
	 * Sharing a file or folder via link/public
378
	 *
379
	 * @param int $fileSource File ID that is being shared
380
	 * @param string $itemType File type that is being shared (file or folder)
381
	 * @param string $linkOwner
382
	 * @param bool $isSharing True if sharing, false if unsharing
383
	 */
384 2
	protected function shareFileOrFolderByLink($fileSource, $itemType, $linkOwner, $isSharing) {
385 2
		if ($isSharing) {
386 2
			$actionSharer = 'shared_link_self';
387 2
			$actionOwner = 'reshared_link_by';
388 2
		} else if ($this->currentUser !== $linkOwner) {
389
			// Link expired
390
			$actionSharer = 'link_expired';
391
			$actionOwner = 'link_by_expired';
392
			$this->currentUser = $linkOwner;
393
			\OC::$server->getUserFolder($linkOwner);
394
		} else {
395
			$actionSharer = 'unshared_link_self';
396
			$actionOwner = 'unshared_link_by';
397
		}
398
399 2
		$this->view->chroot('/' . $this->currentUser . '/files');
400
401
		try {
402 2
			$path = $this->view->getPath($fileSource);
403 2
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
404 1
			return;
405
		}
406
407 1
		$this->shareNotificationForOriginalOwners($this->currentUser, $actionOwner, '', $fileSource, $itemType);
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\FilesHooks:...tionForOriginalOwners() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
408
409 1
		$this->addNotificationsForUser(
410 1
			$this->currentUser, $actionSharer, [[$fileSource => $path]],
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\FilesHooks::addNotificationsForUser() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
411 1
			(int) $fileSource, $path, ($itemType === 'file'),
412 1
			$this->userSettings->getUserSetting($this->currentUser, 'stream', Files_Sharing::TYPE_SHARED),
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\UserSettings::getUserSetting() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
413 1
			$this->userSettings->getUserSetting($this->currentUser, 'email', Files_Sharing::TYPE_SHARED) ? $this->userSettings->getUserSetting($this->currentUser, 'setting', 'batchtime') : 0
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\UserSettings::getUserSetting() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
414 1
		);
415 1
	}
416
417
	/**
418
	 * Add notifications for the user that shares a file/folder
419
	 *
420
	 * @param string $subject
421
	 * @param string $shareWith
422
	 * @param int $fileSource
423
	 * @param string $itemType
424
	 */
425 2
	protected function shareNotificationForSharer($subject, $shareWith, $fileSource, $itemType) {
426 2
		$this->view->chroot('/' . $this->currentUser . '/files');
427
428
		try {
429 2
			$path = $this->view->getPath($fileSource);
430 2
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
431 1
			return;
432
		}
433
434 1
		$this->addNotificationsForUser(
435 1
			$this->currentUser, $subject, [[$fileSource => $path], $shareWith],
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\FilesHooks::addNotificationsForUser() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
436 1
			$fileSource, $path, ($itemType === 'file'),
437 1
			$this->userSettings->getUserSetting($this->currentUser, 'stream', Files_Sharing::TYPE_SHARED),
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\UserSettings::getUserSetting() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
438 1
			$this->userSettings->getUserSetting($this->currentUser, 'email', Files_Sharing::TYPE_SHARED) ? $this->userSettings->getUserSetting($this->currentUser, 'setting', 'batchtime') : 0
0 ignored issues
show
Security Bug introduced by
It seems like $this->currentUser can also be of type false; however, OCA\Activity\UserSettings::getUserSetting() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
439 1
		);
440 1
	}
441
442
	/**
443
	 * Add notifications for the user that shares a file/folder
444
	 *
445
	 * @param string $owner
446
	 * @param string $subject
447
	 * @param string $shareWith
448
	 * @param int $fileSource
449
	 * @param string $itemType
450
	 */
451 2
	protected function reshareNotificationForSharer($owner, $subject, $shareWith, $fileSource, $itemType) {
452 2
		$this->view->chroot('/' . $owner . '/files');
453
454
		try {
455 2
			$path = $this->view->getPath($fileSource);
456 2
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
457 1
			return;
458
		}
459
460 1
		$this->addNotificationsForUser(
461 1
			$owner, $subject, [[$fileSource => $path], $this->currentUser, $shareWith],
462 1
			$fileSource, $path, ($itemType === 'file'),
463 1
			$this->userSettings->getUserSetting($owner, 'stream', Files_Sharing::TYPE_SHARED),
464 1
			$this->userSettings->getUserSetting($owner, 'email', Files_Sharing::TYPE_SHARED) ? $this->userSettings->getUserSetting($owner, 'setting', 'batchtime') : 0
465 1
		);
466 1
	}
467
468
	/**
469
	 * Add notifications for the owners whose files have been reshared
470
	 *
471
	 * @param string $currentOwner
472
	 * @param string $subject
473
	 * @param string $shareWith
474
	 * @param int $fileSource
475
	 * @param string $itemType
476
	 */
477 10
	protected function shareNotificationForOriginalOwners($currentOwner, $subject, $shareWith, $fileSource, $itemType) {
478
		// Get the full path of the current user
479 10
		$this->view->chroot('/' . $currentOwner . '/files');
480
481
		try {
482 10
			$path = $this->view->getPath($fileSource);
483 10
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
484 1
			return;
485
		}
486
487
		/**
488
		 * Get the original owner and his path
489
		 */
490 9
		$owner = $this->view->getOwner($path);
491 9
		if ($owner !== $currentOwner) {
492 7
			$this->reshareNotificationForSharer($owner, $subject, $shareWith, $fileSource, $itemType);
493 7
		}
494
495
		/**
496
		 * Get the sharee who shared the item with the currentUser
497
		 */
498 9
		$this->view->chroot('/' . $currentOwner . '/files');
499 9
		$mount = $this->view->getMount($path);
500 9
		if (!($mount instanceof IMountPoint)) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\Mount\IMountPoint does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
501 1
			return;
502
		}
503
504 8
		$storage = $mount->getStorage();
505 8
		if (!$storage->instanceOfStorage('OC\Files\Storage\Shared')) {
506 1
			return;
507
		}
508
509
		/** @var \OC\Files\Storage\Shared $storage */
510 7
		$shareOwner = $storage->getSharedFrom();
511 7
		if ($shareOwner === '' || $shareOwner === null || $shareOwner === $owner || $shareOwner === $currentOwner) {
512 5
			return;
513
		}
514
515 2
		$this->reshareNotificationForSharer($shareOwner, $subject, $shareWith, $fileSource, $itemType);
516 2
	}
517
518
	/**
519
	 * Adds the activity and email for a user when the settings require it
520
	 *
521
	 * @param string $user
522
	 * @param string $subject
523
	 * @param array $subjectParams
524
	 * @param int $fileId
525
	 * @param string $path
526
	 * @param bool $isFile If the item is a file, we link to the parent directory
527
	 * @param bool $streamSetting
528
	 * @param int $emailSetting
529
	 * @param string $type
530
	 */
531 9
	protected function addNotificationsForUser($user, $subject, $subjectParams, $fileId, $path, $isFile, $streamSetting, $emailSetting, $type = Files_Sharing::TYPE_SHARED) {
532 9
		if (!$streamSetting && !$emailSetting) {
533 1
			return;
534
		}
535
536 8
		$selfAction = $user === $this->currentUser;
537 8
		$app = $type === Files_Sharing::TYPE_SHARED ? 'files_sharing' : 'files';
538 8
		$link = Util::linkToAbsolute('files', 'index.php', array(
539 8
			'dir' => ($isFile) ? dirname($path) : $path,
540 8
		));
541
542 8
		$objectType = ($fileId) ? 'files' : '';
543
544 8
		$event = $this->manager->generateEvent();
545 8
		$event->setApp($app)
546 8
			->setType($type)
547 8
			->setAffectedUser($user)
548 8
			->setAuthor($this->currentUser)
549 8
			->setTimestamp(time())
550 8
			->setSubject($subject, $subjectParams)
551 8
			->setObject($objectType, $fileId, $path)
552 8
			->setLink($link);
553
554
		// Add activity to stream
555 8
		if ($streamSetting && (!$selfAction || $this->userSettings->getUserSetting($this->currentUser, 'setting', 'self'))) {
556 3
			$this->activityData->send($event);
557 3
		}
558
559
		// Add activity to mail queue
560 8
		if ($emailSetting && (!$selfAction || $this->userSettings->getUserSetting($this->currentUser, 'setting', 'selfemail'))) {
561 3
			$latestSend = time() + $emailSetting;
562 3
			$this->activityData->storeMail($event, $latestSend);
563 3
		}
564 8
	}
565
}
566