Passed
Push — master ( 36b6a7...e235c6 )
by John
16:03 queued 12s
created

ApiController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
c 0
b 0
f 0
nc 1
nop 9
dl 0
loc 17
rs 10

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 Christoph Wurst <[email protected]>
6
 * @author Daniel Kesselberg <[email protected]>
7
 * @author Felix Nüsse <[email protected]>
8
 * @author fnuesse <[email protected]>
9
 * @author fnuesse <[email protected]>
10
 * @author Joas Schilling <[email protected]>
11
 * @author John Molakvoæ <[email protected]>
12
 * @author Julius Härtl <[email protected]>
13
 * @author Lukas Reschke <[email protected]>
14
 * @author Max Kovalenko <[email protected]>
15
 * @author Morris Jobke <[email protected]>
16
 * @author Nina Pypchenko <[email protected]>
17
 * @author Richard Steinmetz <[email protected]>
18
 * @author Robin Appelman <[email protected]>
19
 * @author Roeland Jago Douma <[email protected]>
20
 * @author Tobias Kaminsky <[email protected]>
21
 * @author Vincent Petry <[email protected]>
22
 *
23
 * @license AGPL-3.0
24
 *
25
 * This code is free software: you can redistribute it and/or modify
26
 * it under the terms of the GNU Affero General Public License, version 3,
27
 * as published by the Free Software Foundation.
28
 *
29
 * This program is distributed in the hope that it will be useful,
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32
 * GNU Affero General Public License for more details.
33
 *
34
 * You should have received a copy of the GNU Affero General Public License, version 3,
35
 * along with this program. If not, see <http://www.gnu.org/licenses/>
36
 *
37
 */
38
namespace OCA\Files\Controller;
39
40
use OC\Files\Node\Node;
41
use OCA\Files\Service\TagService;
42
use OCA\Files\Service\UserConfig;
43
use OCP\AppFramework\Controller;
44
use OCP\AppFramework\Http;
45
use OCP\AppFramework\Http\DataResponse;
46
use OCP\AppFramework\Http\FileDisplayResponse;
47
use OCP\AppFramework\Http\JSONResponse;
48
use OCP\AppFramework\Http\Response;
49
use OCP\Files\File;
50
use OCP\Files\Folder;
51
use OCP\Files\NotFoundException;
52
use OCP\IConfig;
53
use OCP\IPreview;
54
use OCP\IRequest;
55
use OCP\IUserSession;
56
use OCP\Share\IManager;
57
use OCP\Share\IShare;
58
59
/**
60
 * Class ApiController
61
 *
62
 * @package OCA\Files\Controller
63
 */
64
class ApiController extends Controller {
65
	private TagService $tagService;
66
	private IManager $shareManager;
67
	private IPreview $previewManager;
68
	private IUserSession $userSession;
69
	private IConfig $config;
70
	private Folder $userFolder;
71
	private UserConfig $userConfig;
72
73
	/**
74
	 * @param string $appName
75
	 * @param IRequest $request
76
	 * @param IUserSession $userSession
77
	 * @param TagService $tagService
78
	 * @param IPreview $previewManager
79
	 * @param IManager $shareManager
80
	 * @param IConfig $config
81
	 * @param Folder $userFolder
82
	 */
83
	public function __construct($appName,
84
								IRequest $request,
85
								IUserSession $userSession,
86
								TagService $tagService,
87
								IPreview $previewManager,
88
								IManager $shareManager,
89
								IConfig $config,
90
								Folder $userFolder,
91
								UserConfig $userConfig) {
92
		parent::__construct($appName, $request);
93
		$this->userSession = $userSession;
94
		$this->tagService = $tagService;
95
		$this->previewManager = $previewManager;
96
		$this->shareManager = $shareManager;
97
		$this->config = $config;
98
		$this->userFolder = $userFolder;
99
		$this->userConfig = $userConfig;
100
	}
101
102
	/**
103
	 * Gets a thumbnail of the specified file
104
	 *
105
	 * @since API version 1.0
106
	 *
107
	 * @NoAdminRequired
108
	 * @NoCSRFRequired
109
	 * @StrictCookieRequired
110
	 *
111
	 * @param int $x
112
	 * @param int $y
113
	 * @param string $file URL-encoded filename
114
	 * @return DataResponse|FileDisplayResponse
115
	 */
116
	public function getThumbnail($x, $y, $file) {
117
		if ($x < 1 || $y < 1) {
118
			return new DataResponse(['message' => 'Requested size must be numeric and a positive value.'], Http::STATUS_BAD_REQUEST);
119
		}
120
121
		try {
122
			$file = $this->userFolder->get($file);
123
			if ($file instanceof Folder) {
124
				throw new NotFoundException();
125
			}
126
127
			/** @var File $file */
128
			$preview = $this->previewManager->getPreview($file, $x, $y, true);
129
130
			return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]);
131
		} catch (NotFoundException $e) {
132
			return new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND);
133
		} catch (\Exception $e) {
134
			return new DataResponse([], Http::STATUS_BAD_REQUEST);
135
		}
136
	}
137
138
	/**
139
	 * Updates the info of the specified file path
140
	 * The passed tags are absolute, which means they will
141
	 * replace the actual tag selection.
142
	 *
143
	 * @NoAdminRequired
144
	 *
145
	 * @param string $path path
146
	 * @param array|string $tags array of tags
147
	 * @return DataResponse
148
	 */
149
	public function updateFileTags($path, $tags = null) {
150
		$result = [];
151
		// if tags specified or empty array, update tags
152
		if (!is_null($tags)) {
153
			try {
154
				$this->tagService->updateFileTags($path, $tags);
155
			} catch (\OCP\Files\NotFoundException $e) {
156
				return new DataResponse([
157
					'message' => $e->getMessage()
158
				], Http::STATUS_NOT_FOUND);
159
			} catch (\OCP\Files\StorageNotAvailableException $e) {
160
				return new DataResponse([
161
					'message' => $e->getMessage()
162
				], Http::STATUS_SERVICE_UNAVAILABLE);
163
			} catch (\Exception $e) {
164
				return new DataResponse([
165
					'message' => $e->getMessage()
166
				], Http::STATUS_NOT_FOUND);
167
			}
168
			$result['tags'] = $tags;
169
		}
170
		return new DataResponse($result);
171
	}
172
173
	/**
174
	 * @param \OCP\Files\Node[] $nodes
175
	 * @return array
176
	 */
177
	private function formatNodes(array $nodes) {
178
		$shareTypesForNodes = $this->getShareTypesForNodes($nodes);
179
		return array_values(array_map(function (Node $node) use ($shareTypesForNodes) {
180
			$shareTypes = $shareTypesForNodes[$node->getId()] ?? [];
181
			$file = \OCA\Files\Helper::formatFileInfo($node->getFileInfo());
182
			$file['hasPreview'] = $this->previewManager->isAvailable($node);
183
			$parts = explode('/', dirname($node->getPath()), 4);
184
			if (isset($parts[3])) {
185
				$file['path'] = '/' . $parts[3];
186
			} else {
187
				$file['path'] = '/';
188
			}
189
			if (!empty($shareTypes)) {
190
				$file['shareTypes'] = $shareTypes;
191
			}
192
			return $file;
193
		}, $nodes));
194
	}
195
196
	/**
197
	 * Get the share types for each node
198
	 *
199
	 * @param \OCP\Files\Node[] $nodes
200
	 * @return array<int, int[]> list of share types for each fileid
201
	 */
202
	private function getShareTypesForNodes(array $nodes): array {
203
		$userId = $this->userSession->getUser()->getUID();
204
		$requestedShareTypes = [
205
			IShare::TYPE_USER,
206
			IShare::TYPE_GROUP,
207
			IShare::TYPE_LINK,
208
			IShare::TYPE_REMOTE,
209
			IShare::TYPE_EMAIL,
210
			IShare::TYPE_ROOM,
211
			IShare::TYPE_DECK,
212
		];
213
		$shareTypes = [];
214
215
		$nodeIds = array_map(function (Node $node) {
216
			return $node->getId();
217
		}, $nodes);
218
219
		foreach ($requestedShareTypes as $shareType) {
220
			$nodesLeft = array_combine($nodeIds, array_fill(0, count($nodeIds), true));
221
			$offset = 0;
222
223
			// fetch shares until we've either found shares for all nodes or there are no more shares left
224
			while (count($nodesLeft) > 0) {
225
				$shares = $this->shareManager->getSharesBy($userId, $shareType, null, false, 100, $offset);
226
				foreach ($shares as $share) {
227
					$fileId = $share->getNodeId();
228
					if (isset($nodesLeft[$fileId])) {
229
						if (!isset($shareTypes[$fileId])) {
230
							$shareTypes[$fileId] = [];
231
						}
232
						$shareTypes[$fileId][] = $shareType;
233
						unset($nodesLeft[$fileId]);
234
					}
235
				}
236
237
				if (count($shares) < 100) {
238
					break;
239
				} else {
240
					$offset += count($shares);
241
				}
242
			}
243
		}
244
		return $shareTypes;
245
	}
246
247
	/**
248
	 * Returns a list of recently modified files.
249
	 *
250
	 * @NoAdminRequired
251
	 *
252
	 * @return DataResponse
253
	 */
254
	public function getRecentFiles() {
255
		$nodes = $this->userFolder->getRecent(100);
256
		$files = $this->formatNodes($nodes);
257
		return new DataResponse(['files' => $files]);
258
	}
259
260
	/**
261
	 * Change the default sort mode
262
	 *
263
	 * @NoAdminRequired
264
	 *
265
	 * @param string $mode
266
	 * @param string $direction
267
	 * @return Response
268
	 * @throws \OCP\PreConditionNotMetException
269
	 */
270
	public function updateFileSorting($mode, $direction) {
271
		$allowedMode = ['name', 'size', 'mtime'];
272
		$allowedDirection = ['asc', 'desc'];
273
		if (!in_array($mode, $allowedMode) || !in_array($direction, $allowedDirection)) {
274
			$response = new Response();
275
			$response->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY);
276
			return $response;
277
		}
278
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting', $mode);
279
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting_direction', $direction);
280
		return new Response();
281
	}
282
283
	/**
284
	 * Toggle default files user config
285
	 *
286
	 * @NoAdminRequired
287
	 *
288
	 * @param string $key
289
	 * @param string|bool $value
290
	 * @return JSONResponse
291
	 */
292
	public function setConfig(string $key, $value): JSONResponse {
293
		try {
294
			$this->userConfig->setConfig($key, (string)$value);
295
		} catch (\InvalidArgumentException $e) {
296
			return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
297
		}
298
299
		return new JSONResponse(['message' => 'ok', 'data' => ['key' => $key, 'value' => $value]]);
300
	}
301
302
303
	/**
304
	 * Get the user config
305
	 *
306
	 * @NoAdminRequired
307
	 *
308
	 * @return JSONResponse
309
	 */
310
	public function getConfigs(): JSONResponse {
311
		return new JSONResponse(['message' => 'ok', 'data' => $this->userConfig->getConfigs()]);
312
	}
313
314
	/**
315
	 * Toggle default for showing/hiding hidden files
316
	 *
317
	 * @NoAdminRequired
318
	 *
319
	 * @param bool $value
320
	 * @return Response
321
	 * @throws \OCP\PreConditionNotMetException
322
	 */
323
	public function showHiddenFiles(bool $value): Response {
324
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', $value ? '1' : '0');
325
		return new Response();
326
	}
327
328
	/**
329
	 * Toggle default for cropping preview images
330
	 *
331
	 * @NoAdminRequired
332
	 *
333
	 * @param bool $value
334
	 * @return Response
335
	 * @throws \OCP\PreConditionNotMetException
336
	 */
337
	public function cropImagePreviews(bool $value): Response {
338
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', $value ? '1' : '0');
339
		return new Response();
340
	}
341
342
	/**
343
	 * Toggle default for files grid view
344
	 *
345
	 * @NoAdminRequired
346
	 *
347
	 * @param bool $show
348
	 * @return Response
349
	 * @throws \OCP\PreConditionNotMetException
350
	 */
351
	public function showGridView(bool $show): Response {
352
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', $show ? '1' : '0');
353
		return new Response();
354
	}
355
356
	/**
357
	 * Get default settings for the grid view
358
	 *
359
	 * @NoAdminRequired
360
	 */
361
	public function getGridView() {
362
		$status = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', '0') === '1';
363
		return new JSONResponse(['gridview' => $status]);
364
	}
365
366
	/**
367
	 * Toggle default for showing/hiding xxx folder
368
	 *
369
	 * @NoAdminRequired
370
	 *
371
	 * @param int $show
372
	 * @param string $key the key of the folder
373
	 *
374
	 * @return Response
375
	 * @throws \OCP\PreConditionNotMetException
376
	 */
377
	public function toggleShowFolder(int $show, string $key): Response {
378
		if ($show !== 0 && $show !== 1) {
379
			return new DataResponse([
380
				'message' => 'Invalid show value. Only 0 and 1 are allowed.'
381
			], Http::STATUS_BAD_REQUEST);
382
		}
383
384
		$userId = $this->userSession->getUser()->getUID();
385
386
		// Set the new value and return it
387
		// Using a prefix prevents the user from setting arbitrary keys
388
		$this->config->setUserValue($userId, 'files', 'show_' . $key, (string)$show);
389
		return new JSONResponse([$key => $show]);
390
	}
391
392
	/**
393
	 * Get sorting-order for custom sorting
394
	 *
395
	 * @NoAdminRequired
396
	 *
397
	 * @param string $folderpath
398
	 * @return string
399
	 * @throws \OCP\Files\NotFoundException
400
	 */
401
	public function getNodeType($folderpath) {
402
		$node = $this->userFolder->get($folderpath);
403
		return $node->getType();
404
	}
405
}
406