Completed
Push — master ( af6e20...df6ab2 )
by Morris
01:57
created

APIv2::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
ccs 13
cts 13
cp 1
rs 8.9713
cc 1
eloc 23
nc 1
nop 12
crap 1

How to fix   Many Parameters   

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
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 *
7
 * @license AGPL-3.0
8
 *
9
 * This code is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License, version 3,
11
 * as published by the Free Software Foundation.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License, version 3,
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
20
 *
21
 */
22
23
namespace OCA\Activity\Controller;
24
25
26
use OC\Files\View;
27
use OCA\Activity\Data;
28
use OCA\Activity\Exception\InvalidFilterException;
29
use OCA\Activity\GroupHelper;
30
use OCA\Activity\UserSettings;
31
use OCA\Activity\ViewInfoCache;
32
use OCP\Activity\IManager;
33
use OCP\AppFramework\Http;
34
use OCP\AppFramework\Http\DataResponse;
35
use OCP\AppFramework\OCSController;
36
use OCP\Files\FileInfo;
37
use OCP\Files\IMimeTypeDetector;
38
use OCP\IPreview;
39
use OCP\IRequest;
40
use OCP\IURLGenerator;
41
use OCP\IUser;
42
use OCP\IUserSession;
43
44
class APIv2 extends OCSController {
45
46
	/** @var string */
47
	protected $filter;
48
49
	/** @var int */
50
	protected $since;
51
52
	/** @var int */
53
	protected $limit;
54
55
	/** @var string */
56
	protected $sort;
57
58
	/** @var string */
59
	protected $objectType;
60
61
	/** @var int */
62
	protected $objectId;
63
64
	/** @var string */
65
	protected $user;
66
67
	/** @var bool */
68
	protected $loadPreviews;
69
70
71
	/** @var IManager */
72
	protected $activityManager;
73
74
	/** @var Data */
75
	protected $data;
76
77
	/** @var GroupHelper */
78
	protected $helper;
79
80
	/** @var UserSettings */
81
	protected $settings;
82
83
	/** @var IURLGenerator */
84
	protected $urlGenerator;
85
86
	/** @var IUserSession */
87
	protected $userSession;
88
89
	/** @var IPreview */
90
	protected $preview;
91
92
	/** @var IMimeTypeDetector */
93
	protected $mimeTypeDetector;
94
95
	/** @var View */
96
	protected $view;
97
98
	/** @var ViewInfoCache */
99
	protected $infoCache;
100
101
	/**
102
	 * OCSEndPoint constructor.
103
	 *
104
	 * @param string $appName
105
	 * @param IRequest $request
106
	 * @param IManager $activityManager
107
	 * @param Data $data
108
	 * @param GroupHelper $helper
109
	 * @param UserSettings $settings
110
	 * @param IURLGenerator $urlGenerator
111
	 * @param IUserSession $userSession
112
	 * @param IPreview $preview
113
	 * @param IMimeTypeDetector $mimeTypeDetector
114
	 * @param View $view
115
	 * @param ViewInfoCache $infoCache
116
	 */
117 65
	public function __construct($appName,
118
								IRequest $request,
119
								IManager $activityManager,
120
								Data $data,
121
								GroupHelper $helper,
122
								UserSettings $settings,
123
								IURLGenerator $urlGenerator,
124
								IUserSession $userSession,
125
								IPreview $preview,
126
								IMimeTypeDetector $mimeTypeDetector,
127
								View $view,
128
								ViewInfoCache $infoCache) {
129 65
		parent::__construct($appName, $request);
130 65
		$this->activityManager = $activityManager;
131 65
		$this->data = $data;
132 65
		$this->helper = $helper;
133 65
		$this->settings = $settings;
134 65
		$this->urlGenerator = $urlGenerator;
135 65
		$this->userSession = $userSession;
136 65
		$this->preview = $preview;
137 65
		$this->mimeTypeDetector = $mimeTypeDetector;
138 65
		$this->view = $view;
139 65
		$this->infoCache = $infoCache;
140 65
	}
141
142
	/**
143
	 * @param string $filter
144
	 * @param int $since
145
	 * @param int $limit
146
	 * @param bool $previews
147
	 * @param string $objectType
148
	 * @param int $objectId
149
	 * @param string $sort
150
	 * @throws InvalidFilterException when the filter is invalid
151
	 * @throws \OutOfBoundsException when no user is given
152
	 */
153 22
	protected function validateParameters($filter, $since, $limit, $previews, $objectType, $objectId, $sort) {
154 22
		$this->filter = is_string($filter) ? $filter : 'all';
155 22
		if ($this->filter !== $this->data->validateFilter($this->filter)) {
156 2
			throw new InvalidFilterException();
157
		}
158 20
		$this->since = (int) $since;
159 20
		$this->limit = (int) $limit;
160 20
		$this->loadPreviews = (bool) $previews;
161 20
		$this->objectType = (string) $objectType;
162 20
		$this->objectId = (int) $objectId;
163 20
		$this->sort = in_array($sort, ['asc', 'desc'], true) ? $sort : 'desc';
164
165 20
		if (($this->objectType !== '' && $this->objectId === 0) || ($this->objectType === '' && $this->objectId !== 0)) {
166
			// Only allowed together
167 2
			$this->objectType = '';
168 2
			$this->objectId = 0;
169
		}
170
171 20
		$user = $this->userSession->getUser();
172 20
		if ($user instanceof IUser) {
0 ignored issues
show
Bug introduced by
The class OCP\IUser 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...
173 19
			$this->user = $user->getUID();
174
		} else {
175
			// No user logged in
176 1
			throw new \OutOfBoundsException();
177
		}
178 19
	}
179
180
	/**
181
	 * @NoAdminRequired
182
	 *
183
	 * @param int $since
184
	 * @param int $limit
185
	 * @param bool $previews
186
	 * @param string $object_type
187
	 * @param int $object_id
188
	 * @param string $sort
189
	 * @return DataResponse
190
	 */
191 2
	public function getDefault($since = 0, $limit = 50, $previews = false, $object_type = '', $object_id = 0, $sort = 'desc') {
192 2
		return $this->get('all', $since, $limit, $previews, $object_type, $object_id, $sort);
193
	}
194
195
	/**
196
	 * @NoAdminRequired
197
	 *
198
	 * @param string $filter
199
	 * @param int $since
200
	 * @param int $limit
201
	 * @param bool $previews
202
	 * @param string $object_type
203
	 * @param int $object_id
204
	 * @param string $sort
205
	 * @return DataResponse
206
	 */
207 2
	public function getFilter($filter, $since = 0, $limit = 50, $previews = false, $object_type = '', $object_id = 0, $sort = 'desc') {
208 2
		return $this->get($filter, $since, $limit, $previews, $object_type, $object_id, $sort);
209
	}
210
211
	/**
212
	 * @param string $filter
213
	 * @param int $since
214
	 * @param int $limit
215
	 * @param bool $previews
216
	 * @param string $filterObjectType
217
	 * @param int $filterObjectId
218
	 * @param string $sort
219
	 * @return DataResponse
220
	 */
221 11
	protected function get($filter, $since, $limit, $previews, $filterObjectType, $filterObjectId, $sort) {
222
		try {
223 11
			$this->validateParameters($filter, $since, $limit, $previews, $filterObjectType, $filterObjectId, $sort);
224 2
		} catch (InvalidFilterException $e) {
225 1
			return new DataResponse(null, Http::STATUS_NOT_FOUND);
226 1
		} catch (\OutOfBoundsException $e) {
227 1
			return new DataResponse(null, Http::STATUS_FORBIDDEN);
228
		}
229
230 9
		$this->activityManager->setRequirePNG($this->request->isUserAgent([IRequest::USER_AGENT_CLIENT_IOS]));
231
		try {
232 9
			$response = $this->data->get(
233 9
				$this->helper,
234 9
				$this->settings,
235 9
				$this->user,
236
237 9
				$this->since,
238 9
				$this->limit,
239 9
				$this->sort,
240
241 9
				$this->filter,
242 9
				$this->objectType,
243 9
				$this->objectId
244
			);
245 2
		} catch (\OutOfBoundsException $e) {
246
			// Invalid since argument
247 1
			return new DataResponse(null, Http::STATUS_FORBIDDEN);
248 1
		} catch (\BadMethodCallException $e) {
249
			// No activity settings enabled
250 1
			return new DataResponse(null, Http::STATUS_NO_CONTENT);
251
		}
252 7
		$this->activityManager->setRequirePNG(false);
253
254 7
		$headers = $this->generateHeaders($response['headers'], $response['has_more'], $response['data']);
255 7
		if (empty($response['data']) || $this->request->getHeader('If-None-Match') === $headers['ETag']) {
256 3
			return new DataResponse([], Http::STATUS_NOT_MODIFIED, $headers);
257
		}
258
259 4
		$preparedActivities = [];
260 4
		foreach ($response['data'] as $activity) {
261 4
			$activity['datetime'] = date(\DateTime::ATOM, $activity['timestamp']);
262 4
			unset($activity['timestamp']);
263
264 4
			if ($this->loadPreviews) {
265 3
				$activity['previews'] = [];
266 3
				if ($activity['object_type'] === 'files') {
267 2
					if (!empty($activity['objects']) && is_array($activity['objects'])) {
268 1
						foreach ($activity['objects'] as $objectId => $objectName) {
269 1
							if (((int) $objectId) === 0 || $objectName === '') {
270
								// No file, no preview
271 1
								continue;
272
							}
273
274 1
							$activity['previews'][] = $this->getPreview($activity['affecteduser'], (int) $objectId, $objectName);
275
						}
276 1
					} else if ($activity['object_id']) {
277 1
						$activity['previews'][] = $this->getPreview($activity['affecteduser'], (int) $activity['object_id'], $activity['object_name']);
278
					}
279
				}
280
			}
281
282 4
			unset($activity['affecteduser']);
283 4
			$preparedActivities[] = $activity;
284
		}
285
286 4
		return new DataResponse($preparedActivities, Http::STATUS_OK, $headers);
287
	}
288
289
	/**
290
	 * @param array $headers
291
	 * @param bool $hasMoreActivities
292
	 * @param array $data
293
	 * @return array
294
	 */
295 6
	protected function generateHeaders(array $headers, $hasMoreActivities, array $data) {
296 6
		if ($hasMoreActivities && isset($headers['X-Activity-Last-Given'])) {
297
			// Set the "Link" header for the next page
298
			$nextPageParameters = [
299 3
				'since' => $headers['X-Activity-Last-Given'],
300 3
				'limit' => $this->limit,
301 3
				'sort' => $this->sort,
302
			];
303 3
			if ($this->objectType && $this->objectId) {
304 1
				$nextPageParameters['object_type'] = $this->objectType;
305 1
				$nextPageParameters['object_id'] = $this->objectId;
306
			}
307 3
			if ($this->request->getParam('format') !== null) {
308 1
				$nextPageParameters['format'] = $this->request->getParam('format');
309
			}
310
311 3
			$nextPage = $this->request->getServerProtocol(); # http
312 3
			$nextPage .= '://' . $this->request->getServerHost(); # localhost
313 3
			$nextPage .= $this->request->getScriptName(); # /ocs/v2.php
314 3
			$nextPage .= $this->request->getPathInfo(); # /apps/activity/api/v2/activity
315 3
			$nextPage .= '?' . http_build_query($nextPageParameters);
316 3
			$headers['Link'] = '<' . $nextPage . '>; rel="next"';
317
		}
318
319 6
		$ids = [];
320 6
		foreach ($data as $activity) {
321 2
			$ids[] = $activity['activity_id'];
322
		}
323 6
		$headers['ETag'] = md5(json_encode($ids));
324
325 6
		return $headers;
326
	}
327
328
	/**
329
	 * @param string $owner
330
	 * @param int $fileId
331
	 * @param string $filePath
332
	 * @return array
333
	 */
334 7
	protected function getPreview($owner, $fileId, $filePath) {
335 7
		$info = $this->infoCache->getInfoById($owner, $fileId, $filePath);
336
337 7
		if (!$info['exists'] || $info['view'] !== '') {
338 3
			return $this->getPreviewFromPath($filePath, $info);
339
		}
340
341
		$preview = [
342 4
			'link'			=> $this->getPreviewLink($info['path'], $info['is_dir'], $info['view']),
343 4
			'source'		=> '',
344
			'isMimeTypeIcon' => true,
345
		];
346
347
		// show a preview image if the file still exists
348 4
		if ($info['is_dir']) {
349 1
			$preview['source'] = $this->getPreviewPathFromMimeType('dir');
350
		} else {
351 3
			$this->view->chroot('/' . $owner . '/files');
352 3
			$fileInfo = $this->view->getFileInfo($info['path']);
353 3
			if (!($fileInfo instanceof FileInfo)) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\FileInfo 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...
354 1
				$pathPreview = $this->getPreviewFromPath($filePath, $info);
355 1
				$preview['source'] = $pathPreview['source'];
356 2
			} else if ($this->preview->isAvailable($fileInfo)) {
357 1
				$preview['isMimeTypeIcon'] = false;
358 1
				$preview['source'] = $this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreview', [
359 1
					'file' => $info['path'],
360 1
					'c' => $this->view->getETag($info['path']),
361 1
					'x' => 150,
362 1
					'y' => 150,
363
				]);
364
			} else {
365 1
				$preview['source'] = $this->getPreviewPathFromMimeType($fileInfo->getMimetype());
366
			}
367
		}
368
369 4
		return $preview;
370
	}
371
372
	/**
373
	 * @param string $filePath
374
	 * @param array $info
375
	 * @return array
376
	 */
377 3
	protected function getPreviewFromPath($filePath, $info) {
378 3
		$mimeType = $this->mimeTypeDetector->detectPath($filePath);
379
		$preview = [
380 3
			'link'			=> $this->getPreviewLink($info['path'], $info['is_dir'], $info['view']),
381 3
			'source'		=> $this->getPreviewPathFromMimeType($mimeType),
382
			'isMimeTypeIcon' => true,
383
		];
384
385 3
		return $preview;
386
	}
387
388
	/**
389
	 * @param string $mimeType
390
	 * @return string
391
	 */
392 3
	protected function getPreviewPathFromMimeType($mimeType) {
393 3
		$mimeTypeIcon = $this->mimeTypeDetector->mimeTypeIcon($mimeType);
394 3
		if (substr($mimeTypeIcon, -4) === '.png') {
395 1
			$mimeTypeIcon = substr($mimeTypeIcon, 0, -4) . '.svg';
396
		}
397
398 3
		return $this->urlGenerator->getAbsoluteURL($mimeTypeIcon);
399
	}
400
401
	/**
402
	 * @param string $path
403
	 * @param bool $isDir
404
	 * @param string $view
405
	 * @return string
406
	 */
407 6
	protected function getPreviewLink($path, $isDir, $view) {
408
		$params = [
409 6
			'dir' => $path,
410
		];
411 6
		if (!$isDir) {
412 3
			$params['dir'] = (substr_count($path, '/') === 1) ? '/' : dirname($path);
413 3
			$params['scrollto'] = basename($path);
414
		}
415 6
		if ($view !== '') {
416 2
			$params['view'] = $view;
417
		}
418 6
		return $this->urlGenerator->linkToRouteAbsolute('files.view.index', $params);
419
	}
420
}
421