Completed
Pull Request — master (#5628)
by Joas
17:04
created

Provider   C

Complexity

Total Complexity 71

Size/Duplication

Total Lines 365
Duplicated Lines 34.52 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 126
loc 365
rs 5.5904
c 0
b 0
f 0
wmc 71
lcom 1
cbo 8

9 Methods

Rating   Name   Duplication   Size   Complexity  
A parse() 0 18 4
A __construct() 7 7 1
C parseShortVersion() 37 53 13
D parseLongVersion() 37 104 27
A setSubjects() 14 14 3
D getParameters() 0 48 16
A getFile() 20 20 3
A getUser() 11 11 2
A getDisplayName() 0 8 2

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

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Joas Schilling <[email protected]>
4
 *
5
 * @license GNU AGPL version 3 or any later version
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as
9
 * published by the Free Software Foundation, either version 3 of the
10
 * License, or (at your option) any later version.
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
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
namespace OCA\Files\Activity;
23
24
use OCP\Activity\IEvent;
25
use OCP\Activity\IEventMerger;
26
use OCP\Activity\IManager;
27
use OCP\Activity\IProvider;
28
use OCP\IL10N;
29
use OCP\IURLGenerator;
30
use OCP\IUser;
31
use OCP\IUserManager;
32
use OCP\L10N\IFactory;
33
34
class Provider implements IProvider {
35
36
	/** @var IFactory */
37
	protected $languageFactory;
38
39
	/** @var IL10N */
40
	protected $l;
41
	/** @var IL10N */
42
	protected $activityLang;
43
44
	/** @var IURLGenerator */
45
	protected $url;
46
47
	/** @var IManager */
48
	protected $activityManager;
49
50
	/** @var IUserManager */
51
	protected $userManager;
52
53
	/** @var IEventMerger */
54
	protected $eventMerger;
55
56
	/** @var string[] cached displayNames - key is the UID and value the displayname */
57
	protected $displayNames = [];
58
59
	/**
60
	 * @param IFactory $languageFactory
61
	 * @param IURLGenerator $url
62
	 * @param IManager $activityManager
63
	 * @param IUserManager $userManager
64
	 * @param IEventMerger $eventMerger
65
	 */
66 View Code Duplication
	public function __construct(IFactory $languageFactory, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IEventMerger $eventMerger) {
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...
67
		$this->languageFactory = $languageFactory;
68
		$this->url = $url;
69
		$this->activityManager = $activityManager;
70
		$this->userManager = $userManager;
71
		$this->eventMerger = $eventMerger;
72
	}
73
74
	/**
75
	 * @param string $language
76
	 * @param IEvent $event
77
	 * @param IEvent|null $previousEvent
78
	 * @return IEvent
79
	 * @throws \InvalidArgumentException
80
	 * @since 11.0.0
81
	 */
82
	public function parse($language, IEvent $event, IEvent $previousEvent = null) {
83
		if ($event->getApp() !== 'files') {
84
			throw new \InvalidArgumentException();
85
		}
86
87
		$this->l = $this->languageFactory->get('files', $language);
88
		$this->activityLang = $this->languageFactory->get('activity', $language);
89
90
		if ($this->activityManager->isFormattingFilteredObject()) {
91
			try {
92
				return $this->parseShortVersion($event, $previousEvent);
93
			} catch (\InvalidArgumentException $e) {
94
				// Ignore and simply use the long version...
95
			}
96
		}
97
98
		return $this->parseLongVersion($event, $previousEvent);
99
	}
100
101
	/**
102
	 * @param IEvent $event
103
	 * @param IEvent|null $previousEvent
104
	 * @return IEvent
105
	 * @throws \InvalidArgumentException
106
	 * @since 11.0.0
107
	 */
108
	public function parseShortVersion(IEvent $event, IEvent $previousEvent = null) {
109
		$parsedParameters = $this->getParameters($event);
110
111
		if ($event->getSubject() === 'created_by') {
112
			$subject = $this->l->t('Created by {user}');
113
			if ($this->activityManager->getRequirePNG()) {
114
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
115
			} else {
116
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
117
			}
118 View Code Duplication
		} else if ($event->getSubject() === 'changed_by') {
119
			$subject = $this->l->t('Changed by {user}');
120
			if ($this->activityManager->getRequirePNG()) {
121
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
122
			} else {
123
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
124
			}
125
		} else if ($event->getSubject() === 'deleted_by') {
126
			$subject = $this->l->t('Deleted by {user}');
127
			if ($this->activityManager->getRequirePNG()) {
128
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.png')));
129
			} else {
130
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.svg')));
131
			}
132
		} else if ($event->getSubject() === 'restored_by') {
133
			$subject = $this->l->t('Restored by {user}');
134
		} else if ($event->getSubject() === 'renamed_by') {
135
			$subject = $this->l->t('Renamed by {user}');
136
			if ($this->activityManager->getRequirePNG()) {
137
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
138
			} else {
139
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
140
			}
141
		} else if ($event->getSubject() === 'moved_by') {
142
			$subject = $this->l->t('Moved by {user}');
143
			if ($this->activityManager->getRequirePNG()) {
144
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
145
			} else {
146
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
147
			}
148
		} else {
149
			throw new \InvalidArgumentException();
150
		}
151
152 View Code Duplication
		if (!isset($parsedParameters['user'])) {
153
			// External user via public link share
154
			$subject = str_replace('{user}', $this->activityLang->t('"remote user"'), $subject);
155
		}
156
157
		$this->setSubjects($event, $subject, $parsedParameters);
158
159
		return $this->eventMerger->mergeEvents('user', $event, $previousEvent);
160
	}
161
162
	/**
163
	 * @param IEvent $event
164
	 * @param IEvent|null $previousEvent
165
	 * @return IEvent
166
	 * @throws \InvalidArgumentException
167
	 * @since 11.0.0
168
	 */
169
	public function parseLongVersion(IEvent $event, IEvent $previousEvent = null) {
170
		$parsedParameters = $this->getParameters($event);
171
172
		if ($event->getSubject() === 'created_self') {
173
			$subject = $this->l->t('You created {file}');
174
			if ($this->activityManager->getRequirePNG()) {
175
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
176
			} else {
177
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
178
			}
179
		} else if ($event->getSubject() === 'created_by') {
180
			$subject = $this->l->t('{user} created {file}');
181
			if ($this->activityManager->getRequirePNG()) {
182
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
183
			} else {
184
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
185
			}
186
		} else if ($event->getSubject() === 'created_public') {
187
			$subject = $this->l->t('{file} was created in a public folder');
188
			if ($this->activityManager->getRequirePNG()) {
189
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
190
			} else {
191
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
192
			}
193
		} else if ($event->getSubject() === 'changed_self') {
194
			$subject = $this->l->t('You changed {file}');
195
			if ($this->activityManager->getRequirePNG()) {
196
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
197
			} else {
198
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
199
			}
200
		} else if ($event->getSubject() === 'changed_by') {
201
			$subject = $this->l->t('{user} changed {file}');
202
			if ($this->activityManager->getRequirePNG()) {
203
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
204
			} else {
205
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
206
			}
207
		} else if ($event->getSubject() === 'deleted_self') {
208
			$subject = $this->l->t('You deleted {file}');
209
			if ($this->activityManager->getRequirePNG()) {
210
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.png')));
211
			} else {
212
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.svg')));
213
			}
214
		} else if ($event->getSubject() === 'deleted_by') {
215
			$subject = $this->l->t('{user} deleted {file}');
216
			if ($this->activityManager->getRequirePNG()) {
217
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.png')));
218
			} else {
219
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.svg')));
220
			}
221
		} else if ($event->getSubject() === 'restored_self') {
222
			$subject = $this->l->t('You restored {file}');
223 View Code Duplication
		} else if ($event->getSubject() === 'restored_by') {
224
			$subject = $this->l->t('{user} restored {file}');
225
		} else if ($event->getSubject() === 'renamed_self') {
226
			$subject = $this->l->t('You renamed {oldfile} to {newfile}');
227
			if ($this->activityManager->getRequirePNG()) {
228
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
229
			} else {
230
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
231
			}
232
		} else if ($event->getSubject() === 'renamed_by') {
233
			$subject = $this->l->t('{user} renamed {oldfile} to {newfile}');
234
			if ($this->activityManager->getRequirePNG()) {
235
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
236
			} else {
237
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
238
			}
239
		} else if ($event->getSubject() === 'moved_self') {
240
			$subject = $this->l->t('You moved {oldfile} to {newfile}');
241
			if ($this->activityManager->getRequirePNG()) {
242
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
243
			} else {
244
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
245
			}
246
		} else if ($event->getSubject() === 'moved_by') {
247
			$subject = $this->l->t('{user} moved {oldfile} to {newfile}');
248
			if ($this->activityManager->getRequirePNG()) {
249
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
250
			} else {
251
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
252
			}
253
		} else {
254
			throw new \InvalidArgumentException();
255
		}
256
257 View Code Duplication
		if (!isset($parsedParameters['user'])) {
258
			// External user via public link share
259
			$subject = str_replace('{user}', $this->activityLang->t('"remote user"'), $subject);
260
		}
261
262
		$this->setSubjects($event, $subject, $parsedParameters);
263
264
		$event = $this->eventMerger->mergeEvents('file', $event, $previousEvent);
265
266
		if ($event->getChildEvent() === null) {
267
			// Couldn't group by file, maybe we can group by user
268
			$event = $this->eventMerger->mergeEvents('user', $event, $previousEvent);
269
		}
270
271
		return $event;
272
	}
273
274 View Code Duplication
	protected function setSubjects(IEvent $event, $subject, array $parameters) {
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...
275
		$placeholders = $replacements = [];
276
		foreach ($parameters as $placeholder => $parameter) {
277
			$placeholders[] = '{' . $placeholder . '}';
278
			if ($parameter['type'] === 'file') {
279
				$replacements[] = $parameter['path'];
280
			} else {
281
				$replacements[] = $parameter['name'];
282
			}
283
		}
284
285
		$event->setParsedSubject(str_replace($placeholders, $replacements, $subject))
286
			->setRichSubject($subject, $parameters);
287
	}
288
289
	/**
290
	 * @param IEvent $event
291
	 * @return array
292
	 * @throws \InvalidArgumentException
293
	 */
294
	protected function getParameters(IEvent $event) {
295
		$parameters = $event->getSubjectParameters();
296
		switch ($event->getSubject()) {
297
			case 'created_self':
298
			case 'created_public':
299
			case 'changed_self':
300
			case 'deleted_self':
301
			case 'restored_self':
302
				return [
303
					'file' => $this->getFile($parameters[0], $event),
304
				];
305
			case 'created_by':
306
			case 'changed_by':
307
			case 'deleted_by':
308
			case 'restored_by':
309
				if ($parameters[1] === '') {
310
					// External user via public link share
311
					return [
312
						'file' => $this->getFile($parameters[0], $event),
313
					];
314
				}
315
				return [
316
					'file' => $this->getFile($parameters[0], $event),
317
					'user' => $this->getUser($parameters[1]),
318
				];
319
			case 'renamed_self':
320
			case 'moved_self':
321
				return [
322
					'newfile' => $this->getFile($parameters[0]),
323
					'oldfile' => $this->getFile($parameters[1]),
324
				];
325
			case 'renamed_by':
326
			case 'moved_by':
327
				if ($parameters[1] === '') {
328
					// External user via public link share
329
					return [
330
						'newfile' => $this->getFile($parameters[0]),
331
						'oldfile' => $this->getFile($parameters[2]),
332
					];
333
				}
334
				return [
335
					'newfile' => $this->getFile($parameters[0]),
336
					'user' => $this->getUser($parameters[1]),
337
					'oldfile' => $this->getFile($parameters[2]),
338
				];
339
		}
340
		return [];
341
	}
342
343
	/**
344
	 * @param array|string $parameter
345
	 * @param IEvent|null $event
346
	 * @return array
347
	 * @throws \InvalidArgumentException
348
	 */
349 View Code Duplication
	protected function getFile($parameter, IEvent $event = null) {
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...
350
		if (is_array($parameter)) {
351
			$path = reset($parameter);
352
			$id = (string) key($parameter);
353
		} else if ($event !== null) {
354
			// Legacy from before ownCloud 8.2
355
			$path = $parameter;
356
			$id = $event->getObjectId();
357
		} else {
358
			throw new \InvalidArgumentException('Could not generate file parameter');
359
		}
360
361
		return [
362
			'type' => 'file',
363
			'id' => $id,
364
			'name' => basename($path),
365
			'path' => trim($path, '/'),
366
			'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $id]),
367
		];
368
	}
369
370
	/**
371
	 * @param string $uid
372
	 * @return array
373
	 */
374 View Code Duplication
	protected function getUser($uid) {
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...
375
		if (!isset($this->displayNames[$uid])) {
376
			$this->displayNames[$uid] = $this->getDisplayName($uid);
377
		}
378
379
		return [
380
			'type' => 'user',
381
			'id' => $uid,
382
			'name' => $this->displayNames[$uid],
383
		];
384
	}
385
386
	/**
387
	 * @param string $uid
388
	 * @return string
389
	 */
390
	protected function getDisplayName($uid) {
391
		$user = $this->userManager->get($uid);
392
		if ($user instanceof IUser) {
393
			return $user->getDisplayName();
394
		} else {
395
			return $uid;
396
		}
397
	}
398
}
399