Passed
Push — master ( 6f3c4f...d83ea2 )
by Blizzz
16:41 queued 12s
created

DefaultPublicShareTemplateProvider::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
c 1
b 0
f 0
nc 1
nop 10
dl 0
loc 22
rs 9.9332

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
declare(strict_types=1);
4
/**
5
 * @copyright Copyright (c) 2023 Louis Chemineau <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Files_Sharing;
25
26
use OCA\FederatedFileSharing\FederatedShareProvider;
27
use OCA\Files_Sharing\AppInfo\Application;
28
use OCA\Files_Sharing\Event\BeforeTemplateRenderedEvent;
29
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...
30
use OCP\Accounts\IAccountManager;
31
use OCP\AppFramework\Http\ContentSecurityPolicy;
32
use OCP\AppFramework\Http\Template\ExternalShareMenuAction;
33
use OCP\AppFramework\Http\Template\LinkMenuAction;
34
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
35
use OCP\AppFramework\Http\Template\SimpleMenuAction;
36
use OCP\AppFramework\Http\TemplateResponse;
37
use OCP\Constants;
38
use OCP\Defaults;
39
use OCP\EventDispatcher\IEventDispatcher;
40
use OCP\Files\FileInfo;
41
use OCP\Files\Folder;
42
use OCP\Files\NotFoundException;
43
use OCP\IConfig;
44
use OCP\IL10N;
45
use OCP\IPreview;
46
use OCP\IRequest;
47
use OCP\IURLGenerator;
48
use OCP\IUser;
49
use OCP\IUserManager;
50
use OCP\Share\IShare;
51
use OCP\Share\IPublicShareTemplateProvider;
52
use OCP\Template;
53
use OCP\Util;
54
55
class DefaultPublicShareTemplateProvider implements IPublicShareTemplateProvider {
56
	private IUserManager $userManager;
57
	private IAccountManager $accountManager;
58
	private IPreview $previewManager;
59
	protected FederatedShareProvider $federatedShareProvider;
60
	private IURLGenerator $urlGenerator;
61
	private IEventDispatcher $eventDispatcher;
62
	private IL10N $l10n;
63
	private Defaults $defaults;
64
	private IConfig $config;
65
	private IRequest $request;
66
67
	public function __construct(
68
		IUserManager $userManager,
69
		IAccountManager $accountManager,
70
		IPreview $previewManager,
71
		FederatedShareProvider $federatedShareProvider,
72
		IUrlGenerator $urlGenerator,
73
		IEventDispatcher $eventDispatcher,
74
		IL10N $l10n,
75
		Defaults $defaults,
76
		IConfig $config,
77
		IRequest $request
78
	) {
79
		$this->userManager = $userManager;
80
		$this->accountManager = $accountManager;
81
		$this->previewManager = $previewManager;
82
		$this->federatedShareProvider = $federatedShareProvider;
83
		$this->urlGenerator = $urlGenerator;
84
		$this->eventDispatcher = $eventDispatcher;
85
		$this->l10n = $l10n;
86
		$this->defaults = $defaults;
87
		$this->config = $config;
88
		$this->request = $request;
89
	}
90
91
	public function shouldRespond(IShare $share): bool {
92
		return true;
93
	}
94
95
	public function renderPage(IShare $share, string $token, string $path): TemplateResponse {
96
		$shareNode = $share->getNode();
97
98
		$shareTmpl = [];
99
		$shareTmpl['owner'] = '';
100
		$shareTmpl['shareOwner'] = '';
101
102
		$owner = $this->userManager->get($share->getShareOwner());
103
		if ($owner instanceof IUser) {
104
			$ownerAccount = $this->accountManager->getAccount($owner);
105
106
			$ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
107
			if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
108
				$shareTmpl['owner'] = $owner->getUID();
109
				$shareTmpl['shareOwner'] = $owner->getDisplayName();
110
			}
111
		}
112
113
		$shareTmpl['filename'] = $shareNode->getName();
114
		$shareTmpl['directory_path'] = $share->getTarget();
115
		$shareTmpl['note'] = $share->getNote();
116
		$shareTmpl['mimetype'] = $shareNode->getMimetype();
117
		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
118
		$shareTmpl['dirToken'] = $token;
119
		$shareTmpl['sharingToken'] = $token;
120
		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
121
		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
0 ignored issues
show
introduced by
The condition $share->getPassword() !== null is always true.
Loading history...
122
		$shareTmpl['dir'] = '';
123
		$shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
124
		$shareTmpl['fileSize'] = Util::humanFileSize($shareNode->getSize());
125
		$shareTmpl['hideDownload'] = $share->getHideDownload();
126
127
		$hideFileList = false;
128
129
		if ($shareNode instanceof Folder) {
130
			$shareIsFolder = true;
131
132
			$folderNode = $shareNode->get($path);
133
			$shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
134
135
			/*
136
			 * The OC_Util methods require a view. This just uses the node API
137
			 */
138
			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
139
			if ($freeSpace < FileInfo::SPACE_UNLIMITED) {
140
				$freeSpace = (int)max($freeSpace, 0);
141
			} else {
142
				$freeSpace = (int)((INF > 0) ? INF: PHP_INT_MAX); // work around https://bugs.php.net/bug.php?id=69188
143
			}
144
145
			$hideFileList = !($share->getPermissions() & Constants::PERMISSION_READ);
146
			$maxUploadFilesize = $freeSpace;
147
148
			$folder = new Template('files', 'list', '');
149
150
			$folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
151
			$folder->assign('dirToken', $token);
152
			$folder->assign('permissions', Constants::PERMISSION_READ);
153
			$folder->assign('isPublic', true);
154
			$folder->assign('hideFileList', $hideFileList);
155
			$folder->assign('publicUploadEnabled', 'no');
156
			// default to list view
157
			$folder->assign('showgridview', false);
158
			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
159
			$folder->assign('uploadMaxHumanFilesize', Util::humanFileSize($maxUploadFilesize));
160
			$folder->assign('freeSpace', $freeSpace);
161
			$folder->assign('usedSpacePercent', 0);
162
			$folder->assign('trash', false);
163
			$shareTmpl['folder'] = $folder->fetchPage();
164
		} else {
165
			$shareIsFolder = false;
166
		}
167
168
		// default to list view
169
		$shareTmpl['showgridview'] = false;
170
171
		$shareTmpl['hideFileList'] = $hideFileList;
172
		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
173
			'token' => $token,
174
			'filename' => $shareIsFolder ? null : $shareNode->getName()
175
		]);
176
		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $token]);
177
		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
178
		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
179
		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
180
		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
181
		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', '');
182
		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
183
184
		if ($shareTmpl['previewSupported']) {
185
			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
186
				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
187
			$ogPreview = $shareTmpl['previewImage'];
188
189
			// We just have direct previews for image files
190
			if ($shareNode->getMimePart() === 'image') {
191
				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $token]);
192
193
				$ogPreview = $shareTmpl['previewURL'];
194
195
				//Whatapp is kind of picky about their size requirements
196
				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
197
					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
198
						'token' => $token,
199
						'x' => 256,
200
						'y' => 256,
201
						'a' => true,
202
					]);
203
				}
204
			}
205
		} else {
206
			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
207
			$ogPreview = $shareTmpl['previewImage'];
208
		}
209
210
		// Load files we need
211
		Util::addScript('files', 'semaphore');
212
		Util::addScript('files', 'file-upload');
213
		Util::addStyle('files_sharing', 'publicView');
214
		Util::addScript('files_sharing', 'public');
215
		Util::addScript('files_sharing', 'templates');
216
		Util::addScript('files', 'fileactions');
217
		Util::addScript('files', 'fileactionsmenu');
218
		Util::addScript('files', 'jquery.fileupload');
219
		Util::addScript('files_sharing', 'files_drop');
220
221
		if (isset($shareTmpl['folder'])) {
222
			// JS required for folders
223
			Util::addStyle('files', 'merged');
224
			Util::addScript('files', 'filesummary');
225
			Util::addScript('files', 'templates');
226
			Util::addScript('files', 'breadcrumb');
227
			Util::addScript('files', 'fileinfomodel');
228
			Util::addScript('files', 'newfilemenu');
229
			Util::addScript('files', 'files');
230
			Util::addScript('files', 'filemultiselectmenu');
231
			Util::addScript('files', 'filelist');
232
			Util::addScript('files', 'keyboardshortcuts');
233
			Util::addScript('files', 'operationprogressbar');
234
		}
235
236
		// Load Viewer scripts
237
		if (class_exists(LoadViewer::class)) {
238
			$this->eventDispatcher->dispatchTyped(new LoadViewer());
239
		}
240
		// OpenGraph Support: http://ogp.me/
241
		Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
242
		Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
243
		Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
244
		Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
245
		Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
246
		Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
247
248
		$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));
249
250
		$csp = new ContentSecurityPolicy();
251
		$csp->addAllowedFrameDomain('\'self\'');
252
253
		$response = new PublicTemplateResponse(Application::APP_ID, 'public', $shareTmpl);
254
		$response->setHeaderTitle($shareTmpl['filename']);
255
		if ($shareTmpl['shareOwner'] !== '') {
256
			$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
257
		}
258
259
		$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== Constants::PERMISSION_CREATE;
260
261
		if ($isNoneFileDropFolder && !$share->getHideDownload()) {
262
			Util::addScript('files_sharing', 'public_note');
263
264
			$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
265
			$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
266
			$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
267
			$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
268
			$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
269
			// TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
270
			$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your %s', [$this->defaults->getProductName()]), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
271
272
			$responseComposer = [];
273
274
			if ($shareIsFolder) {
275
				$responseComposer[] = $downloadAllWhite;
276
				$responseComposer[] = $downloadAll;
277
			} else {
278
				$responseComposer[] = $downloadWhite;
279
				$responseComposer[] = $download;
280
			}
281
			$responseComposer[] = $directLink;
282
			if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
283
				$responseComposer[] = $externalShare;
284
			}
285
286
			$response->setHeaderActions($responseComposer);
287
		}
288
289
		$response->setContentSecurityPolicy($csp);
290
		return $response;
291
	}
292
}
293