Passed
Push — master ( 9b1b62...011405 )
by Julius
02:56 queued 10s
created

lib/Activity/DeckProvider.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @copyright Copyright (c) 2018 Julius Härtl <[email protected]>
4
 *
5
 * @author Julius Härtl <[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\Deck\Activity;
25
26
27
use cogpowered\FineDiff\Diff;
28
use OCA\Deck\Db\Acl;
29
use OCP\Activity\IEvent;
30
use OCP\Activity\IProvider;
31
use OCP\Comments\IComment;
32
use OCP\Comments\ICommentsManager;
33
use OCP\Comments\NotFoundException;
34
use OCP\IConfig;
35
use OCP\IURLGenerator;
36
use OCP\IUserManager;
37
use OCP\L10N\IFactory;
38
39
class DeckProvider implements IProvider {
40
41
	/** @var string */
42
	private $userId;
43
	/** @var IURLGenerator */
44
	private $urlGenerator;
45
	/** @var ActivityManager */
46
	private $activityManager;
47
	/** @var IUserManager */
48
	private $userManager;
49
	/** @var ICommentsManager */
50
	private $commentsManager;
51
	/** @var IFactory */
52
	private $l10nFactory;
53
	/** @var IConfig */
54
	private $config;
55
56
	public function __construct(IURLGenerator $urlGenerator, ActivityManager $activityManager, IUserManager $userManager, ICommentsManager $commentsManager, IFactory $l10n, IConfig $config, $userId) {
57
		$this->userId = $userId;
58
		$this->urlGenerator = $urlGenerator;
59
		$this->activityManager = $activityManager;
60
		$this->commentsManager = $commentsManager;
61
		$this->userManager = $userManager;
62
		$this->l10nFactory = $l10n;
63
		$this->config = $config;
64
	}
65
66
	/**
67
	 * @param string $language The language which should be used for translating, e.g. "en"
68
	 * @param IEvent $event The current event which should be parsed
69
	 * @param IEvent|null $previousEvent A potential previous event which you can combine with the current one.
70
	 *                                   To do so, simply use setChildEvent($previousEvent) after setting the
71
	 *                                   combined subject on the current event.
72
	 * @return IEvent
73
	 * @throws \InvalidArgumentException Should be thrown if your provider does not know this event
74
	 * @since 11.0.0
75
	 */
76
	public function parse($language, IEvent $event, IEvent $previousEvent = null) {
77
		if ($event->getApp() !== 'deck') {
78
			throw new \InvalidArgumentException();
79
		}
80
81
		$event = $this->getIcon($event);
82
83
		$subjectIdentifier = $event->getSubject();
84
		$subjectParams = $event->getSubjectParameters();
85
		$ownActivity = ($event->getAuthor() === $this->userId);
86
87
		/**
88
		 * Map stored parameter objects to rich string types
89
		 */
90
91
		$author = $event->getAuthor();
92
		// get author if
93
		if (($author === '' || $author === ActivityManager::DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED) && array_key_exists('author', $subjectParams)) {
94
			$author = $subjectParams['author'];
95
			unset($subjectParams['author']);
96
		}
97
		$user = $this->userManager->get($author);
98
		if ($user !== null) {
99
			$params = [
100
				'user' => [
101
					'type' => 'user',
102
					'id' => $author,
103
					'name' => $user !== null ? $user->getDisplayName() : $author
104
				],
105
			];
106
			$event->setAuthor($author);
107
		}
108
		if ($event->getObjectType() === ActivityManager::DECK_OBJECT_BOARD) {
109 View Code Duplication
			if (isset($subjectParams['board']) && $event->getObjectName() === '') {
110
				$event->setObject($event->getObjectType(), $event->getObjectId(), $subjectParams['board']['title']);
111
			}
112
			$board = [
113
				'type' => 'highlight',
114
				'id' => $event->getObjectId(),
115
				'name' => $event->getObjectName(),
116
				'link' => $this->deckUrl('/board/' . $event->getObjectId()),
117
			];
118
			$params['board'] = $board;
0 ignored issues
show
The variable $params does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
119
		}
120
121
		if (isset($subjectParams['card']) && $event->getObjectType() === ActivityManager::DECK_OBJECT_CARD) {
122 View Code Duplication
			if ($event->getObjectName() === '') {
123
				$event->setObject($event->getObjectType(), $event->getObjectId(), $subjectParams['card']['title']);
124
			}
125
			$card = [
126
				'type' => 'highlight',
127
				'id' => $event->getObjectId(),
128
				'name' => $event->getObjectName(),
129
			];
130
131
			if (array_key_exists('board', $subjectParams)) {
132
				$archivedParam = $subjectParams['card']['archived'] ? 'archived' : '';
133
				$card['link'] = $this->deckUrl('/board/' . $subjectParams['board']['id'] . '/' . $archivedParam . '/card/' . $event->getObjectId());
134
			}
135
			$params['card'] = $card;
136
		}
137
138
		$params = $this->parseParamForBoard('board', $subjectParams, $params);
139
		$params = $this->parseParamForStack('stack', $subjectParams, $params);
140
		$params = $this->parseParamForStack('stackBefore', $subjectParams, $params);
141
		$params = $this->parseParamForAttachment('attachment', $subjectParams, $params);
142
		$params = $this->parseParamForLabel($subjectParams, $params);
143
		$params = $this->parseParamForAssignedUser($subjectParams, $params);
144
		$params = $this->parseParamForAcl($subjectParams, $params);
145
		$params = $this->parseParamForChanges($subjectParams, $params, $event);
146
		$params = $this->parseParamForComment($subjectParams, $params, $event);
147
		$params = $this->parseParamForDuedate($subjectParams, $params, $event);
148
149
		try {
150
			$subject = $this->activityManager->getActivityFormat($subjectIdentifier, $subjectParams, $ownActivity);
151
			$this->setSubjects($event, $subject, $params);
152
		} catch (\Exception $e) {
153
		}
154
		return $event;
155
	}
156
157
	/**
158
	 * @param IEvent $event
159
	 * @param string $subject
160
	 * @param array $parameters
161
	 */
162
	protected function setSubjects(IEvent $event, $subject, array $parameters) {
163
		$placeholders = $replacements = $richParameters = [];
164
		foreach ($parameters as $placeholder => $parameter) {
165
			$placeholders[] = '{' . $placeholder . '}';
166
			if (is_array($parameter) && array_key_exists('name', $parameter)) {
167
				$replacements[] = $parameter['name'];
168
				$richParameters[$placeholder] = $parameter;
169
			} else {
170
				$replacements[] = '';
171
			}
172
		}
173
174
		$event->setParsedSubject(str_replace($placeholders, $replacements, $subject))
175
			->setRichSubject($subject, $richParameters);
176
		$event->setSubject($subject, $parameters);
177
	}
178
179
	private function getIcon(IEvent $event) {
180
		$event->setIcon($this->urlGenerator->imagePath('deck', 'deck-dark.svg'));
181 View Code Duplication
		if (strpos($event->getSubject(), '_update') !== false) {
182
			$event->setIcon($this->urlGenerator->imagePath('files', 'change.svg'));
183
		}
184 View Code Duplication
		if (strpos($event->getSubject(), '_create') !== false) {
185
			$event->setIcon($this->urlGenerator->imagePath('files', 'add-color.svg'));
186
		}
187 View Code Duplication
		if (strpos($event->getSubject(), '_delete') !== false) {
188
			$event->setIcon($this->urlGenerator->imagePath('files', 'delete-color.svg'));
189
		}
190 View Code Duplication
		if (strpos($event->getSubject(), 'archive') !== false) {
191
			$event->setIcon($this->urlGenerator->imagePath('deck', 'archive.svg'));
192
		}
193 View Code Duplication
		if (strpos($event->getSubject(), '_restore') !== false) {
194
			$event->setIcon($this->urlGenerator->imagePath('core', 'actions/history.svg'));
195
		}
196 View Code Duplication
		if (strpos($event->getSubject(), 'attachment_') !== false) {
197
			$event->setIcon($this->urlGenerator->imagePath('core', 'places/files.svg'));
198
		}
199 View Code Duplication
		if (strpos($event->getSubject(), 'comment_') !== false) {
200
			$event->setIcon($this->urlGenerator->imagePath('core', 'actions/comment.svg'));
201
		}
202
		return $event;
203
	}
204
205
	private function parseParamForBoard($paramName, $subjectParams, $params) {
206
		if (array_key_exists($paramName, $subjectParams)) {
207
			$params[$paramName] = [
208
				'type' => 'highlight',
209
				'id' => $subjectParams[$paramName]['id'],
210
				'name' => $subjectParams[$paramName]['title'],
211
				'link' => $this->deckUrl('/board/' . $subjectParams[$paramName]['id'] . '/'),
212
			];
213
		}
214
		return $params;
215
	}
216
	private function parseParamForStack($paramName, $subjectParams, $params) {
217
		if (array_key_exists($paramName, $subjectParams)) {
218
			$params[$paramName] = [
219
				'type' => 'highlight',
220
				'id' => $subjectParams[$paramName]['id'],
221
				'name' => $subjectParams[$paramName]['title'],
222
			];
223
		}
224
		return $params;
225
	}
226
227
	private function parseParamForAttachment($paramName, $subjectParams, $params) {
228
		if (array_key_exists($paramName, $subjectParams)) {
229
			$params[$paramName] = [
230
				'type' => 'highlight',
231
				'id' => $subjectParams[$paramName]['id'],
232
				'name' => $subjectParams[$paramName]['data'],
233
				'link' => $this->urlGenerator->linkToRoute('deck.attachment.display', ['cardId' => $subjectParams['card']['id'], 'attachmentId' => $subjectParams['attachment']['id']]),
234
			];
235
		}
236
		return $params;
237
	}
238
239
	private function parseParamForAssignedUser($subjectParams, $params) {
240
		if (array_key_exists('assigneduser', $subjectParams)) {
241
			$user = $this->userManager->get($subjectParams['assigneduser']);
242
			$params['assigneduser'] = [
243
				'type' => 'user',
244
				'id' => $subjectParams['assigneduser'],
245
				'name' => $user !== null ? $user->getDisplayName() : $subjectParams['assigneduser']
246
			];
247
		}
248
		return $params;
249
	}
250
251
	private function parseParamForLabel($subjectParams, $params) {
252 View Code Duplication
		if (array_key_exists('label', $subjectParams)) {
253
			$params['label'] = [
254
				'type' => 'highlight',
255
				'id' => $subjectParams['label']['id'],
256
				'name' => $subjectParams['label']['title']
257
			];
258
		}
259
		return $params;
260
	}
261
262
	private function parseParamForAcl($subjectParams, $params) {
263
		if (array_key_exists('acl', $subjectParams)) {
264
			if ($subjectParams['acl']['type'] === Acl::PERMISSION_TYPE_USER) {
265
				$user = $this->userManager->get($subjectParams['acl']['participant']);
266
				$params['acl'] = [
267
					'type' => 'user',
268
					'id' => $subjectParams['acl']['participant'],
269
					'name' => $user !== null ? $user->getDisplayName() : $subjectParams['acl']['participant']
270
				];
271 View Code Duplication
			} else {
272
				$params['acl'] = [
273
					'type' => 'highlight',
274
					'id' => $subjectParams['acl']['participant'],
275
					'name' => $subjectParams['acl']['participant']
276
				];
277
			}
278
		}
279
		return $params;
280
	}
281
282
	private function parseParamForComment($subjectParams, $params, IEvent $event) {
283
		if (array_key_exists('comment', $subjectParams)) {
284
			/** @var IComment $comment */
285
			try {
286
				$comment = $this->commentsManager->get((int)$subjectParams['comment']);
287
				$event->setParsedMessage($comment->getMessage());
288
				$params['comment'] =[
289
					'type' => 'highlight',
290
					'id' => $subjectParams['comment'],
291
					'name' => $comment->getMessage()
292
				];
293
			} catch (NotFoundException $e) {
294
			}
295
		}
296
		return $params;
297
	}
298
299
	private function parseParamForDuedate($subjectParams, $params, IEvent $event) {
300
		if (array_key_exists('after', $subjectParams) && $event->getSubject() === ActivityManager::SUBJECT_CARD_UPDATE_DUEDATE) {
301
			$userLanguage = $this->config->getUserValue($event->getAuthor(), 'core', 'lang', $this->l10nFactory->findLanguage());
302
			$userLocale = $this->config->getUserValue($event->getAuthor(), 'core', 'locale', $this->l10nFactory->findLocale());
303
			$l10n = $this->l10nFactory->get('deck', $userLanguage, $userLocale);
304
			$date = new \DateTime($subjectParams['after']);
305
			$date->setTimezone(new \DateTimeZone(\date_default_timezone_get()));
306
			$params['after'] = [
307
				'type' => 'highlight',
308
				'id' => 'dt:' . $subjectParams['after'],
309
				'name' => $l10n->l('datetime', $date)
310
			];
311
		}
312
		return $params;
313
	}
314
315
	/**
316
	 * Add diff to message if the subject parameter 'diff' is set, otherwise
317
	 * the changed values are added to before/after
318
	 *
319
	 * @param $subjectParams
320
	 * @param $params
321
	 * @return mixed
322
	 */
323
	private function parseParamForChanges($subjectParams, $params, $event) {
324
		if (array_key_exists('diff', $subjectParams) && $subjectParams['diff']) {
325
			$diff = new Diff();
326
			// Don't add diff as message since we are limited to 255 chars here
327
			//$event->setMessage($subjectParams['after']);
328
			$event->setParsedMessage('<pre class="visualdiff">' . $diff->render($subjectParams['before'], $subjectParams['after']) . '</pre>');
329
			return $params;
330
		}
331 View Code Duplication
		if (array_key_exists('before', $subjectParams)) {
332
			$params['before'] = [
333
				'type' => 'highlight',
334
				'id' => $subjectParams['before'],
335
				'name' => $subjectParams['before']
336
			];
337
		}
338 View Code Duplication
		if (array_key_exists('after', $subjectParams)) {
339
			$params['after'] = [
340
				'type' => 'highlight',
341
				'id' => $subjectParams['after'],
342
				'name' => $subjectParams['after']
343
			];
344
		}
345
		return $params;
346
	}
347
348
	public function deckUrl($endpoint) {
349
		return $this->urlGenerator->linkToRouteAbsolute('deck.page.index') . '#!' . $endpoint;
350
	}
351
}
352