Passed
Push — master ( 634f5a...1a0f9b )
by John
14:30 queued 13s
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
	/**
262
	 * Returns the current logged-in user's storage stats.
263
	 *
264
	 * @NoAdminRequired
265
	 *
266
	 * @param ?string $dir the directory to get the storage stats from
267
	 * @return JSONResponse
268
	 */
269
	public function getStorageStats($dir = '/'): JSONResponse {
270
		$storageInfo = \OC_Helper::getStorageInfo($dir ?: '/');
271
		return new JSONResponse(['message' => 'ok', 'data' => $storageInfo]);
272
	}
273
274
	/**
275
	 * Change the default sort mode
276
	 *
277
	 * @NoAdminRequired
278
	 *
279
	 * @param string $mode
280
	 * @param string $direction
281
	 * @return Response
282
	 * @throws \OCP\PreConditionNotMetException
283
	 */
284
	public function updateFileSorting($mode, $direction) {
285
		$allowedMode = ['name', 'size', 'mtime'];
286
		$allowedDirection = ['asc', 'desc'];
287
		if (!in_array($mode, $allowedMode) || !in_array($direction, $allowedDirection)) {
288
			$response = new Response();
289
			$response->setStatus(Http::STATUS_UNPROCESSABLE_ENTITY);
290
			return $response;
291
		}
292
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting', $mode);
293
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'file_sorting_direction', $direction);
294
		return new Response();
295
	}
296
297
	/**
298
	 * Toggle default files user config
299
	 *
300
	 * @NoAdminRequired
301
	 *
302
	 * @param string $key
303
	 * @param string|bool $value
304
	 * @return JSONResponse
305
	 */
306
	public function setConfig(string $key, $value): JSONResponse {
307
		try {
308
			$this->userConfig->setConfig($key, (string)$value);
309
		} catch (\InvalidArgumentException $e) {
310
			return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
311
		}
312
313
		return new JSONResponse(['message' => 'ok', 'data' => ['key' => $key, 'value' => $value]]);
314
	}
315
316
317
	/**
318
	 * Get the user config
319
	 *
320
	 * @NoAdminRequired
321
	 *
322
	 * @return JSONResponse
323
	 */
324
	public function getConfigs(): JSONResponse {
325
		return new JSONResponse(['message' => 'ok', 'data' => $this->userConfig->getConfigs()]);
326
	}
327
328
	/**
329
	 * Toggle default for showing/hiding hidden files
330
	 *
331
	 * @NoAdminRequired
332
	 *
333
	 * @param bool $value
334
	 * @return Response
335
	 * @throws \OCP\PreConditionNotMetException
336
	 */
337
	public function showHiddenFiles(bool $value): Response {
338
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', $value ? '1' : '0');
339
		return new Response();
340
	}
341
342
	/**
343
	 * Toggle default for cropping preview images
344
	 *
345
	 * @NoAdminRequired
346
	 *
347
	 * @param bool $value
348
	 * @return Response
349
	 * @throws \OCP\PreConditionNotMetException
350
	 */
351
	public function cropImagePreviews(bool $value): Response {
352
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', $value ? '1' : '0');
353
		return new Response();
354
	}
355
356
	/**
357
	 * Toggle default for files grid view
358
	 *
359
	 * @NoAdminRequired
360
	 *
361
	 * @param bool $show
362
	 * @return Response
363
	 * @throws \OCP\PreConditionNotMetException
364
	 */
365
	public function showGridView(bool $show): Response {
366
		$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', $show ? '1' : '0');
367
		return new Response();
368
	}
369
370
	/**
371
	 * Get default settings for the grid view
372
	 *
373
	 * @NoAdminRequired
374
	 */
375
	public function getGridView() {
376
		$status = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', '0') === '1';
377
		return new JSONResponse(['gridview' => $status]);
378
	}
379
380
	/**
381
	 * Toggle default for showing/hiding xxx folder
382
	 *
383
	 * @NoAdminRequired
384
	 *
385
	 * @param int $show
386
	 * @param string $key the key of the folder
387
	 *
388
	 * @return Response
389
	 * @throws \OCP\PreConditionNotMetException
390
	 */
391
	public function toggleShowFolder(int $show, string $key): Response {
392
		if ($show !== 0 && $show !== 1) {
393
			return new DataResponse([
394
				'message' => 'Invalid show value. Only 0 and 1 are allowed.'
395
			], Http::STATUS_BAD_REQUEST);
396
		}
397
398
		$userId = $this->userSession->getUser()->getUID();
399
400
		// Set the new value and return it
401
		// Using a prefix prevents the user from setting arbitrary keys
402
		$this->config->setUserValue($userId, 'files', 'show_' . $key, (string)$show);
403
		return new JSONResponse([$key => $show]);
404
	}
405
406
	/**
407
	 * Get sorting-order for custom sorting
408
	 *
409
	 * @NoAdminRequired
410
	 *
411
	 * @param string $folderpath
412
	 * @return string
413
	 * @throws \OCP\Files\NotFoundException
414
	 */
415
	public function getNodeType($folderpath) {
416
		$node = $this->userFolder->get($folderpath);
417
		return $node->getType();
418
	}
419
}
420