Passed
Push — master ( 795881...c80e00 )
by Julius
12:34 queued 10s
created

ApiController::formatNodes()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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