Passed
Push — master ( 7d7f7a...71065f )
by Joas
16:42 queued 13s
created

Provider::getDisplayName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Joas Schilling <[email protected]>
4
 *
5
 * @author Christoph Wurst <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Morris Jobke <[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 OCA\Comments\Activity;
26
27
use OCP\Activity\IEvent;
28
use OCP\Activity\IManager;
29
use OCP\Activity\IProvider;
30
use OCP\Comments\ICommentsManager;
31
use OCP\Comments\NotFoundException;
32
use OCP\IL10N;
33
use OCP\IURLGenerator;
34
use OCP\IUser;
35
use OCP\IUserManager;
36
use OCP\L10N\IFactory;
37
38
class Provider implements IProvider {
39
40
	protected IFactory $languageFactory;
41
	protected ?IL10N $l = null;
42
	protected IUrlGenerator $url;
43
	protected ICommentsManager $commentsManager;
44
	protected IUserManager $userManager;
45
	protected IManager $activityManager;
46
47
	public function __construct(IFactory $languageFactory, IURLGenerator $url, ICommentsManager $commentsManager, IUserManager $userManager, IManager $activityManager) {
48
		$this->languageFactory = $languageFactory;
49
		$this->url = $url;
50
		$this->commentsManager = $commentsManager;
51
		$this->userManager = $userManager;
52
		$this->activityManager = $activityManager;
53
	}
54
55
	/**
56
	 * @param string $language
57
	 * @param IEvent $event
58
	 * @param IEvent|null $previousEvent
59
	 * @return IEvent
60
	 * @throws \InvalidArgumentException
61
	 * @since 11.0.0
62
	 */
63
	public function parse($language, IEvent $event, IEvent $previousEvent = null) {
64
		if ($event->getApp() !== 'comments') {
65
			throw new \InvalidArgumentException();
66
		}
67
68
		$this->l = $this->languageFactory->get('comments', $language);
69
70
		if ($event->getSubject() === 'add_comment_subject') {
71
			$this->parseMessage($event);
72
			if ($this->activityManager->getRequirePNG()) {
73
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/comment.png')));
74
			} else {
75
				$event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/comment.svg')));
76
			}
77
78
			if ($this->activityManager->isFormattingFilteredObject()) {
79
				try {
80
					return $this->parseShortVersion($event);
81
				} catch (\InvalidArgumentException $e) {
82
					// Ignore and simply use the long version...
83
				}
84
			}
85
86
			return $this->parseLongVersion($event);
87
		} else {
88
			throw new \InvalidArgumentException();
89
		}
90
	}
91
92
	/**
93
	 * @throws \InvalidArgumentException
94
	 */
95
	protected function parseShortVersion(IEvent $event): IEvent {
96
		$subjectParameters = $this->getSubjectParameters($event);
97
98
		if ($event->getSubject() === 'add_comment_subject') {
99
			if ($subjectParameters['actor'] === $this->activityManager->getCurrentUserId()) {
100
				$event->setParsedSubject($this->l->t('You commented'))
0 ignored issues
show
Bug introduced by
The method t() does not exist on null. ( Ignorable by Annotation )

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

100
				$event->setParsedSubject($this->l->/** @scrutinizer ignore-call */ t('You commented'))

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...
101
					->setRichSubject($this->l->t('You commented'), []);
102
			} else {
103
				$author = $this->generateUserParameter($subjectParameters['actor']);
104
				$event->setParsedSubject($this->l->t('%1$s commented', [$author['name']]))
105
					->setRichSubject($this->l->t('{author} commented'), [
106
						'author' => $author,
107
					]);
108
			}
109
		} else {
110
			throw new \InvalidArgumentException();
111
		}
112
113
		return $event;
114
	}
115
116
	/**
117
	 * @throws \InvalidArgumentException
118
	 */
119
	protected function parseLongVersion(IEvent $event): IEvent {
120
		$subjectParameters = $this->getSubjectParameters($event);
121
122
		if ($event->getSubject() === 'add_comment_subject') {
123
			if ($subjectParameters['actor'] === $this->activityManager->getCurrentUserId()) {
124
				$event->setParsedSubject($this->l->t('You commented on %1$s', [
125
					$subjectParameters['filePath'],
126
				]))
127
					->setRichSubject($this->l->t('You commented on {file}'), [
128
						'file' => $this->generateFileParameter($subjectParameters['fileId'], $subjectParameters['filePath']),
129
					]);
130
			} else {
131
				$author = $this->generateUserParameter($subjectParameters['actor']);
132
				$event->setParsedSubject($this->l->t('%1$s commented on %2$s', [
133
					$author['name'],
134
					$subjectParameters['filePath'],
135
				]))
136
					->setRichSubject($this->l->t('{author} commented on {file}'), [
137
						'author' => $author,
138
						'file' => $this->generateFileParameter($subjectParameters['fileId'], $subjectParameters['filePath']),
139
					]);
140
			}
141
		} else {
142
			throw new \InvalidArgumentException();
143
		}
144
145
		return $event;
146
	}
147
148
	protected function getSubjectParameters(IEvent $event): array {
149
		$subjectParameters = $event->getSubjectParameters();
150
		if (isset($subjectParameters['fileId'])) {
151
			return $subjectParameters;
152
		}
153
154
		// Fix subjects from 12.0.3 and older
155
		//
156
		// Do NOT Remove unless necessary
157
		// Removing this will break parsing of activities that were created on
158
		// Nextcloud 12, so we should keep this as long as it's acceptable.
159
		// Otherwise if people upgrade over multiple releases in a short period,
160
		// they will get the dead entries in their stream.
161
		return [
162
			'actor' => $subjectParameters[0],
163
			'fileId' => $event->getObjectId(),
164
			'filePath' => trim($subjectParameters[1], '/'),
165
		];
166
	}
167
168
	protected function parseMessage(IEvent $event): void {
169
		$messageParameters = $event->getMessageParameters();
170
		if (empty($messageParameters)) {
171
			// Email
172
			return;
173
		}
174
175
		$commentId = isset($messageParameters['commentId']) ? $messageParameters['commentId'] : $messageParameters[0];
176
177
		try {
178
			$comment = $this->commentsManager->get((string) $commentId);
179
			$message = $comment->getMessage();
180
181
			$mentionCount = 1;
182
			$mentions = [];
183
			foreach ($comment->getMentions() as $mention) {
184
				if ($mention['type'] !== 'user') {
185
					continue;
186
				}
187
188
				$message = str_replace('@"' . $mention['id'] . '"', '{mention' . $mentionCount . '}', $message);
189
				if (strpos($mention['id'], ' ') === false && strpos($mention['id'], 'guest/') !== 0) {
190
					$message = str_replace('@' . $mention['id'], '{mention' . $mentionCount . '}', $message);
191
				}
192
193
				$mentions['mention' . $mentionCount] = $this->generateUserParameter($mention['id']);
194
				$mentionCount++;
195
			}
196
197
			$event->setParsedMessage($comment->getMessage())
198
				->setRichMessage($message, $mentions);
199
		} catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
200
		}
201
	}
202
203
	protected function generateFileParameter(int $id, string $path): array {
204
		return [
205
			'type' => 'file',
206
			'id' => $id,
207
			'name' => basename($path),
208
			'path' => $path,
209
			'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $id]),
210
		];
211
	}
212
213
	protected function generateUserParameter(string $uid): array {
214
		return [
215
			'type' => 'user',
216
			'id' => $uid,
217
			'name' => $this->userManager->getDisplayName($uid) ?? $uid,
218
		];
219
	}
220
}
221