Passed
Push — master ( 2ce0fe...eb92c5 )
by Julius
17:52 queued 13s
created

ViewController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 14
c 0
b 0
f 0
nc 1
nop 13
dl 0
loc 28
rs 9.7998

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 fnuesse <[email protected]>
8
 * @author fnuesse <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author John Molakvoæ <[email protected]>
11
 * @author Julius Härtl <[email protected]>
12
 * @author Lukas Reschke <[email protected]>
13
 * @author Max Kovalenko <[email protected]>
14
 * @author Morris Jobke <[email protected]>
15
 * @author Nina Pypchenko <[email protected]>
16
 * @author Robin Appelman <[email protected]>
17
 * @author Roeland Jago Douma <[email protected]>
18
 * @author Thomas Müller <[email protected]>
19
 * @author Vincent Petry <[email protected]>
20
 *
21
 * @license AGPL-3.0
22
 *
23
 * This code is free software: you can redistribute it and/or modify
24
 * it under the terms of the GNU Affero General Public License, version 3,
25
 * as published by the Free Software Foundation.
26
 *
27
 * This program is distributed in the hope that it will be useful,
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30
 * GNU Affero General Public License for more details.
31
 *
32
 * You should have received a copy of the GNU Affero General Public License, version 3,
33
 * along with this program. If not, see <http://www.gnu.org/licenses/>
34
 *
35
 */
36
namespace OCA\Files\Controller;
37
38
use OCA\Files\Activity\Helper;
39
use OCA\Files\Event\LoadAdditionalScriptsEvent;
40
use OCA\Files\Event\LoadSidebar;
41
use OCA\Viewer\Event\LoadViewer;
0 ignored issues
show
Bug introduced by
The type OCA\Viewer\Event\LoadViewer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
42
use OCP\App\IAppManager;
43
use OCP\AppFramework\Controller;
44
use OCP\AppFramework\Http\ContentSecurityPolicy;
45
use OCP\AppFramework\Http\RedirectResponse;
46
use OCP\AppFramework\Http\Response;
47
use OCP\AppFramework\Http\TemplateResponse;
48
use OCP\AppFramework\Services\IInitialState;
49
use OCP\EventDispatcher\IEventDispatcher;
50
use OCP\Files\Folder;
51
use OCP\Files\IRootFolder;
52
use OCP\Files\NotFoundException;
53
use OCP\Files\Template\ITemplateManager;
54
use OCP\IConfig;
55
use OCP\IL10N;
56
use OCP\IRequest;
57
use OCP\IURLGenerator;
58
use OCP\IUserSession;
59
use OCP\Share\IManager;
60
61
/**
62
 * Class ViewController
63
 *
64
 * @package OCA\Files\Controller
65
 */
66
class ViewController extends Controller {
67
	/** @var string */
68
	protected $appName;
69
	/** @var IRequest */
70
	protected $request;
71
	/** @var IURLGenerator */
72
	protected $urlGenerator;
73
	/** @var IL10N */
74
	protected $l10n;
75
	/** @var IConfig */
76
	protected $config;
77
	/** @var IEventDispatcher */
78
	protected $eventDispatcher;
79
	/** @var IUserSession */
80
	protected $userSession;
81
	/** @var IAppManager */
82
	protected $appManager;
83
	/** @var IRootFolder */
84
	protected $rootFolder;
85
	/** @var Helper */
86
	protected $activityHelper;
87
	/** @var IInitialState */
88
	private $initialState;
89
	/** @var ITemplateManager */
90
	private $templateManager;
91
	/** @var IManager */
92
	private $shareManager;
93
94
	public function __construct(string $appName,
95
		IRequest $request,
96
		IURLGenerator $urlGenerator,
97
		IL10N $l10n,
98
		IConfig $config,
99
		IEventDispatcher $eventDispatcher,
100
		IUserSession $userSession,
101
		IAppManager $appManager,
102
		IRootFolder $rootFolder,
103
		Helper $activityHelper,
104
		IInitialState $initialState,
105
		ITemplateManager $templateManager,
106
		IManager $shareManager
107
	) {
108
		parent::__construct($appName, $request);
109
		$this->appName = $appName;
110
		$this->request = $request;
111
		$this->urlGenerator = $urlGenerator;
112
		$this->l10n = $l10n;
113
		$this->config = $config;
114
		$this->eventDispatcher = $eventDispatcher;
115
		$this->userSession = $userSession;
116
		$this->appManager = $appManager;
117
		$this->rootFolder = $rootFolder;
118
		$this->activityHelper = $activityHelper;
119
		$this->initialState = $initialState;
120
		$this->templateManager = $templateManager;
121
		$this->shareManager = $shareManager;
122
	}
123
124
	/**
125
	 * @param string $appName
126
	 * @param string $scriptName
127
	 * @return string
128
	 */
129
	protected function renderScript($appName, $scriptName) {
130
		$content = '';
131
		$appPath = \OC_App::getAppPath($appName);
132
		$scriptPath = $appPath . '/' . $scriptName;
0 ignored issues
show
Bug introduced by
Are you sure $appPath of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

132
		$scriptPath = /** @scrutinizer ignore-type */ $appPath . '/' . $scriptName;
Loading history...
133
		if (file_exists($scriptPath)) {
134
			// TODO: sanitize path / script name ?
135
			ob_start();
136
			include $scriptPath;
137
			$content = ob_get_contents();
138
			@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ob_end_clean(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

138
			/** @scrutinizer ignore-unhandled */ @ob_end_clean();

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
139
		}
140
141
		return $content;
142
	}
143
144
	/**
145
	 * FIXME: Replace with non static code
146
	 *
147
	 * @return array
148
	 * @throws \OCP\Files\NotFoundException
149
	 */
150
	protected function getStorageInfo() {
151
		\OC_Util::setupFS();
152
		$dirInfo = \OC\Files\Filesystem::getFileInfo('/', false);
153
154
		return \OC_Helper::getStorageInfo('/', $dirInfo);
155
	}
156
157
	/**
158
	 * @NoCSRFRequired
159
	 * @NoAdminRequired
160
	 *
161
	 * @param string $fileid
162
	 * @return TemplateResponse|RedirectResponse
163
	 * @throws NotFoundException
164
	 */
165
	public function showFile(string $fileid = null): Response {
166
		// This is the entry point from the `/f/{fileid}` URL which is hardcoded in the server.
167
		try {
168
			return $this->redirectToFile($fileid);
169
		} catch (NotFoundException $e) {
170
			return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', ['fileNotFound' => true]));
171
		}
172
	}
173
174
	/**
175
	 * @NoCSRFRequired
176
	 * @NoAdminRequired
177
	 *
178
	 * @param string $dir
179
	 * @param string $view
180
	 * @param string $fileid
181
	 * @param bool $fileNotFound
182
	 * @param string $openfile
183
	 * @return TemplateResponse|RedirectResponse
184
	 * @throws NotFoundException
185
	 */
186
	public function index($dir = '', $view = '', $fileid = null, $fileNotFound = false, $openfile = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $view is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

186
	public function index($dir = '', /** @scrutinizer ignore-unused */ $view = '', $fileid = null, $fileNotFound = false, $openfile = null) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
187
		if ($fileid !== null) {
188
			try {
189
				return $this->redirectToFile($fileid);
190
			} catch (NotFoundException $e) {
191
				return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', ['fileNotFound' => true]));
192
			}
193
		}
194
195
		$nav = new \OCP\Template('files', 'appnavigation', '');
196
197
		// Load the files we need
198
		\OCP\Util::addStyle('files', 'merged');
199
		\OCP\Util::addScript('files', 'merged-index');
200
		\OCP\Util::addScript('files', 'dist/templates');
201
202
		// mostly for the home storage's free space
203
		// FIXME: Make non static
204
		$storageInfo = $this->getStorageInfo();
205
206
		$user = $this->userSession->getUser()->getUID();
207
208
		// Get all the user favorites to create a submenu
209
		try {
210
			$favElements = $this->activityHelper->getFavoriteFilePaths($this->userSession->getUser()->getUID());
211
		} catch (\RuntimeException $e) {
212
			$favElements['folders'] = [];
213
		}
214
215
		$collapseClasses = '';
216
		if (count($favElements['folders']) > 0) {
217
			$collapseClasses = 'collapsible';
218
		}
219
220
		$favoritesSublistArray = [];
221
222
		$navBarPositionPosition = 6;
223
		$currentCount = 0;
224
		foreach ($favElements['folders'] as $dir) {
225
			$link = $this->urlGenerator->linkToRoute('files.view.index', ['dir' => $dir, 'view' => 'files']);
226
			$sortingValue = ++$currentCount;
227
			$element = [
228
				'id' => str_replace('/', '-', $dir),
229
				'view' => 'files',
230
				'href' => $link,
231
				'dir' => $dir,
232
				'order' => $navBarPositionPosition,
233
				'folderPosition' => $sortingValue,
234
				'name' => basename($dir),
235
				'icon' => 'files',
236
				'quickaccesselement' => 'true'
237
			];
238
239
			array_push($favoritesSublistArray, $element);
240
			$navBarPositionPosition++;
241
		}
242
243
		$navItems = \OCA\Files\App::getNavigationManager()->getAll();
244
245
		// add the favorites entry in menu
246
		$navItems['favorites']['sublist'] = $favoritesSublistArray;
247
		$navItems['favorites']['classes'] = $collapseClasses;
248
249
		// parse every menu and add the expandedState user value
250
		foreach ($navItems as $key => $item) {
251
			if (isset($item['expandedState'])) {
252
				$navItems[$key]['defaultExpandedState'] = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', $item['expandedState'], '0') === '1';
253
			}
254
		}
255
256
		$nav->assign('navigationItems', $navItems);
257
258
		$nav->assign('usage', \OC_Helper::humanFileSize($storageInfo['used']));
259
		if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
260
			$totalSpace = $this->l10n->t('Unlimited');
261
		} else {
262
			$totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
263
		}
264
		$nav->assign('total_space', $totalSpace);
265
		$nav->assign('quota', $storageInfo['quota']);
266
		$nav->assign('usage_relative', $storageInfo['relative']);
267
268
		$nav->assign('webdav_url', \OCP\Util::linkToRemote('dav/files/' . $user));
269
270
		$contentItems = [];
271
272
		// render the container content for every navigation item
273
		foreach ($navItems as $item) {
274
			$content = '';
275
			if (isset($item['script'])) {
276
				$content = $this->renderScript($item['appname'], $item['script']);
277
			}
278
			// parse submenus
279
			if (isset($item['sublist'])) {
280
				foreach ($item['sublist'] as $subitem) {
281
					$subcontent = '';
282
					if (isset($subitem['script'])) {
283
						$subcontent = $this->renderScript($subitem['appname'], $subitem['script']);
284
					}
285
					$contentItems[$subitem['id']] = [
286
						'id' => $subitem['id'],
287
						'content' => $subcontent
288
					];
289
				}
290
			}
291
			$contentItems[$item['id']] = [
292
				'id' => $item['id'],
293
				'content' => $content
294
			];
295
		}
296
297
		$event = new LoadAdditionalScriptsEvent();
298
		$this->eventDispatcher->dispatchTyped($event);
299
		$this->eventDispatcher->dispatchTyped(new LoadSidebar());
300
		// Load Viewer scripts
301
		if (class_exists(LoadViewer::class)) {
302
			$this->eventDispatcher->dispatchTyped(new LoadViewer());
303
		}
304
		$this->initialState->provideInitialState('templates_path', $this->templateManager->hasTemplateDirectory() ? $this->templateManager->getTemplatePath() : false);
305
		$this->initialState->provideInitialState('templates', $this->templateManager->listCreators());
306
307
		$params = [];
308
		$params['usedSpacePercent'] = (int) $storageInfo['relative'];
309
		$params['owner'] = $storageInfo['owner'] ?? '';
310
		$params['ownerDisplayName'] = $storageInfo['ownerDisplayName'] ?? '';
311
		$params['isPublic'] = false;
312
		$params['allowShareWithLink'] = $this->shareManager->shareApiAllowLinks() ? 'yes' : 'no';
313
		$params['defaultFileSorting'] = $this->config->getUserValue($user, 'files', 'file_sorting', 'name');
314
		$params['defaultFileSortingDirection'] = $this->config->getUserValue($user, 'files', 'file_sorting_direction', 'asc');
315
		$params['showgridview'] = $this->config->getUserValue($user, 'files', 'show_grid', false);
316
		$params['isIE'] = \OC_Util::isIe();
317
		$showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
318
		$params['showHiddenFiles'] = $showHidden ? 1 : 0;
319
		$cropImagePreviews = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', true);
320
		$params['cropImagePreviews'] = $cropImagePreviews ? 1 : 0;
321
		$params['fileNotFound'] = $fileNotFound ? 1 : 0;
322
		$params['appNavigation'] = $nav;
323
		$params['appContents'] = $contentItems;
324
		$params['hiddenFields'] = $event->getHiddenFields();
325
326
		$response = new TemplateResponse(
327
			$this->appName,
328
			'index',
329
			$params
330
		);
331
		$policy = new ContentSecurityPolicy();
332
		$policy->addAllowedFrameDomain('\'self\'');
333
		$response->setContentSecurityPolicy($policy);
334
335
		$this->provideInitialState($dir, $openfile);
336
337
		return $response;
338
	}
339
340
	/**
341
	 * Add openFileInfo in initialState if $openfile is set.
342
	 * @param string $dir - the ?dir= URL param
343
	 * @param string $openfile - the ?openfile= URL param
344
	 * @return void
345
	 */
346
	private function provideInitialState(string $dir, ?string $openfile): void {
347
		if ($openfile === null) {
348
			return;
349
		}
350
351
		$user = $this->userSession->getUser();
352
353
		if ($user === null) {
354
			return;
355
		}
356
357
		$uid = $user->getUID();
358
		$userFolder = $this->rootFolder->getUserFolder($uid);
359
		$nodes = $userFolder->getById((int) $openfile);
360
		$node = array_shift($nodes);
361
362
		if ($node === null) {
363
			return;
364
		}
365
366
		// properly format full path and make sure
367
		// we're relative to the user home folder
368
		$isRoot = $node === $userFolder;
369
		$path = $userFolder->getRelativePath($node->getPath());
370
		$directory = $userFolder->getRelativePath($node->getParent()->getPath());
371
372
		// Prevent opening a file from another folder.
373
		if ($dir !== $directory) {
374
			return;
375
		}
376
377
		$this->initialState->provideInitialState(
378
			'openFileInfo', [
379
				'id' => $node->getId(),
380
				'name' => $isRoot ? '' : $node->getName(),
381
				'path' => $path,
382
				'directory' => $directory,
383
				'mime' => $node->getMimetype(),
384
				'type' => $node->getType(),
385
				'permissions' => $node->getPermissions(),
386
			]
387
		);
388
	}
389
390
	/**
391
	 * Redirects to the file list and highlight the given file id
392
	 *
393
	 * @param string $fileId file id to show
394
	 * @return RedirectResponse redirect response or not found response
395
	 * @throws \OCP\Files\NotFoundException
396
	 */
397
	private function redirectToFile($fileId) {
398
		$uid = $this->userSession->getUser()->getUID();
399
		$baseFolder = $this->rootFolder->getUserFolder($uid);
400
		$files = $baseFolder->getById($fileId);
0 ignored issues
show
Bug introduced by
$fileId of type string is incompatible with the type integer expected by parameter $id of OCP\Files\Folder::getById(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

400
		$files = $baseFolder->getById(/** @scrutinizer ignore-type */ $fileId);
Loading history...
401
		$params = [];
402
403
		if (empty($files) && $this->appManager->isEnabledForUser('files_trashbin')) {
404
			$baseFolder = $this->rootFolder->get($uid . '/files_trashbin/files/');
405
			$files = $baseFolder->getById($fileId);
0 ignored issues
show
Bug introduced by
The method getById() does not exist on OCP\Files\Node. Did you maybe mean getId()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

405
			/** @scrutinizer ignore-call */ 
406
   $files = $baseFolder->getById($fileId);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
406
			$params['view'] = 'trashbin';
407
		}
408
409
		if (!empty($files)) {
410
			$file = current($files);
411
			if ($file instanceof Folder) {
412
				// set the full path to enter the folder
413
				$params['dir'] = $baseFolder->getRelativePath($file->getPath());
0 ignored issues
show
Bug introduced by
The method getRelativePath() does not exist on OCP\Files\Node. It seems like you code against a sub-type of OCP\Files\Node such as OCP\Files\Folder or OC\Files\Node\Folder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

413
				/** @scrutinizer ignore-call */ 
414
    $params['dir'] = $baseFolder->getRelativePath($file->getPath());
Loading history...
414
			} else {
415
				// set parent path as dir
416
				$params['dir'] = $baseFolder->getRelativePath($file->getParent()->getPath());
417
				// and scroll to the entry
418
				$params['scrollto'] = $file->getName();
419
			}
420
421
			return new RedirectResponse($this->urlGenerator->linkToRoute('files.view.index', $params));
422
		}
423
		throw new \OCP\Files\NotFoundException();
424
	}
425
}
426