Passed
Push — master ( b6d8fc...c76be6 )
by Julius
23:41 queued 14s
created

FileReferenceProvider::getId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * @copyright Copyright (c) 2022 Julius Härtl <[email protected]>
6
 *
7
 * @author Julius Härtl <[email protected]>
8
 *
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace OC\Collaboration\Reference\File;
26
27
use OC\User\NoUserException;
28
use OCP\Collaboration\Reference\ADiscoverableReferenceProvider;
29
use OCP\Collaboration\Reference\IReference;
30
use OCP\Collaboration\Reference\Reference;
31
use OCP\Files\IMimeTypeDetector;
32
use OCP\Files\InvalidPathException;
33
use OCP\Files\IRootFolder;
34
use OCP\Files\Node;
35
use OCP\Files\NotFoundException;
36
use OCP\Files\NotPermittedException;
37
use OCP\IL10N;
38
use OCP\IPreview;
39
use OCP\IURLGenerator;
40
use OCP\IUserSession;
41
use OCP\L10N\IFactory;
42
43
class FileReferenceProvider extends ADiscoverableReferenceProvider {
44
	private IURLGenerator $urlGenerator;
45
	private IRootFolder $rootFolder;
46
	private ?string $userId;
47
	private IPreview $previewManager;
48
	private IMimeTypeDetector $mimeTypeDetector;
49
	private IL10N $l10n;
50
51
	public function __construct(
52
		IURLGenerator $urlGenerator,
53
		IRootFolder $rootFolder,
54
		IUserSession $userSession,
55
		IMimeTypeDetector $mimeTypeDetector,
56
		IPreview $previewManager,
57
		IFactory $l10n
58
	) {
59
		$this->urlGenerator = $urlGenerator;
60
		$this->rootFolder = $rootFolder;
61
		$this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null;
62
		$this->previewManager = $previewManager;
63
		$this->mimeTypeDetector = $mimeTypeDetector;
64
		$this->l10n = $l10n->get('files');
65
	}
66
67
	public function matchReference(string $referenceText): bool {
68
		return $this->getFilesAppLinkId($referenceText) !== null;
69
	}
70
71
	private function getFilesAppLinkId(string $referenceText): ?int {
72
		$start = $this->urlGenerator->getAbsoluteURL('/apps/files/');
73
		$startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/files/');
74
75
		$fileId = null;
76
77
		if (mb_strpos($referenceText, $start) === 0) {
78
			$parts = parse_url($referenceText);
79
			parse_str($parts['query'] ?? '', $query);
80
			$fileId = isset($query['fileid']) ? (int)$query['fileid'] : $fileId;
81
			$fileId = isset($query['openfile']) ? (int)$query['openfile'] : $fileId;
82
		}
83
84
		if (mb_strpos($referenceText, $startIndex) === 0) {
85
			$parts = parse_url($referenceText);
86
			parse_str($parts['query'] ?? '', $query);
87
			$fileId = isset($query['fileid']) ? (int)$query['fileid'] : $fileId;
88
			$fileId = isset($query['openfile']) ? (int)$query['openfile'] : $fileId;
89
		}
90
91
		if (mb_strpos($referenceText, $this->urlGenerator->getAbsoluteURL('/index.php/f/')) === 0) {
92
			$fileId = str_replace($this->urlGenerator->getAbsoluteURL('/index.php/f/'), '', $referenceText);
93
		}
94
95
		if (mb_strpos($referenceText, $this->urlGenerator->getAbsoluteURL('/f/')) === 0) {
96
			$fileId = str_replace($this->urlGenerator->getAbsoluteURL('/f/'), '', $referenceText);
97
		}
98
99
		return $fileId !== null ? (int)$fileId : null;
100
	}
101
102
	public function resolveReference(string $referenceText): ?IReference {
103
		if ($this->matchReference($referenceText)) {
104
			$reference = new Reference($referenceText);
105
			try {
106
				$this->fetchReference($reference);
107
			} catch (NotFoundException $e) {
108
				$reference->setRichObject('file', null);
109
				$reference->setAccessible(false);
110
			}
111
			return $reference;
112
		}
113
114
		return null;
115
	}
116
117
	/**
118
	 * @throws NotFoundException
119
	 */
120
	private function fetchReference(Reference $reference): void {
121
		if ($this->userId === null) {
122
			throw new NotFoundException();
123
		}
124
125
		$fileId = $this->getFilesAppLinkId($reference->getId());
126
		if ($fileId === null) {
127
			throw new NotFoundException();
128
		}
129
130
		try {
131
			$userFolder = $this->rootFolder->getUserFolder($this->userId);
132
			$files = $userFolder->getById($fileId);
133
134
			if (empty($files)) {
135
				throw new NotFoundException();
136
			}
137
138
			/** @var Node $file */
139
			$file = array_shift($files);
140
141
			$reference->setTitle($file->getName());
142
			$reference->setDescription($file->getMimetype());
143
			$reference->setUrl($this->urlGenerator->getAbsoluteURL('/index.php/f/' . $fileId));
144
			if ($this->previewManager->isMimeSupported($file->getMimeType())) {
145
				$reference->setImageUrl($this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreviewByFileId', ['x' => 1600, 'y' => 630, 'fileId' => $fileId]));
146
			} else {
147
				$fileTypeIconUrl = $this->mimeTypeDetector->mimeTypeIcon($file->getMimeType());
148
				$reference->setImageUrl($fileTypeIconUrl);
149
			}
150
151
			$reference->setRichObject('file', [
152
				'id' => $file->getId(),
153
				'name' => $file->getName(),
154
				'size' => $file->getSize(),
155
				'path' => $userFolder->getRelativePath($file->getPath()),
156
				'link' => $reference->getUrl(),
157
				'mimetype' => $file->getMimetype(),
158
				'mtime' => $file->getMTime(),
159
				'preview-available' => $this->previewManager->isAvailable($file)
160
			]);
161
		} catch (InvalidPathException|NotFoundException|NotPermittedException|NoUserException $e) {
162
			throw new NotFoundException();
163
		}
164
	}
165
166
	public function getCachePrefix(string $referenceId): string {
167
		return (string)$this->getFilesAppLinkId($referenceId);
168
	}
169
170
	public function getCacheKey(string $referenceId): ?string {
171
		return $this->userId ?? '';
172
	}
173
174
	public function getId(): string {
175
		return 'files';
176
	}
177
178
	public function getTitle(): string {
179
		return $this->l10n->t('Files');
180
	}
181
182
	public function getOrder(): int {
183
		return 0;
184
	}
185
186
	public function getIconUrl(): string {
187
		return $this->urlGenerator->imagePath('files', 'folder.svg');
188
	}
189
}
190