Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 164
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
CospendProvider
0.00% covered (danger)
0.00%
0 / 164
0.00% covered (danger)
0.00%
0 / 8
1722
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 parse
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 1
182
 setSubjects
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 getIcon
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
42
 parseParamForProject
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 parseParamForBill
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 parseParamForWho
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
132
 cospendUrl
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * @copyright Copyright (c) 2019 Julien Veyssier <eneiluj@posteo.net>
4 *
5 * @author Julien Veyssier <eneiluj@posteo.net>
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
24namespace OCA\Cospend\Activity;
25
26use Exception;
27use InvalidArgumentException;
28
29use OCA\Cospend\AppInfo\Application;
30use OCA\Cospend\Service\ProjectService;
31use OCP\Activity\IEvent;
32use OCP\Activity\IProvider;
33use OCP\IConfig;
34use OCP\IURLGenerator;
35use OCP\IUserManager;
36use OCP\IGroupManager;
37use OCP\IL10N;
38use OCP\App\IAppManager;
39
40class CospendProvider implements IProvider {
41
42    /** @var string */
43    private $userId;
44    /** @var IURLGenerator */
45    private $urlGenerator;
46    /** @var ActivityManager */
47    private $activityManager;
48    /** @var IUserManager */
49    private $userManager;
50    /** @var IL10N */
51    private $l10n;
52    /** @var IConfig */
53    private $config;
54    /**
55     * @var IGroupManager
56     */
57    private $groupManager;
58    /**
59     * @var IAppManager
60     */
61    private $appManager;
62    /**
63     * @var array
64     */
65    private $projectNames;
66
67    public function __construct(IURLGenerator $urlGenerator,
68                                ActivityManager $activityManager,
69                                IUserManager $userManager,
70                                IGroupManager $groupManager,
71                                IAppManager $appManager,
72                                IL10N $l10n,
73                                IConfig $config,
74                                ProjectService $projectService,
75                                ?string $userId) {
76        $this->userId = $userId;
77        $this->urlGenerator = $urlGenerator;
78        $this->activityManager = $activityManager;
79        $this->userManager = $userManager;
80        $this->l10n = $l10n;
81        $this->config = $config;
82        $this->groupManager = $groupManager;
83        $this->appManager = $appManager;
84        $this->projectNames = [];
85        if (!is_null($userId)) {
86            $this->projectNames = $projectService->getProjectNames($userId);
87        }
88    }
89
90    /**
91     * @param string $language The language which should be used for translating, e.g. "en"
92     * @param IEvent $event The current event which should be parsed
93     * @param IEvent|null $previousEvent A potential previous event which you can combine with the current one.
94     *                                   To do so, simply use setChildEvent($previousEvent) after setting the
95     *                                   combined subject on the current event.
96     * @return IEvent
97     * @throws InvalidArgumentException Should be thrown if your provider does not know this event
98     * @since 11.0.0
99     */
100    public function parse($language, IEvent $event, IEvent $previousEvent = null): IEvent {
101        if ($event->getApp() !== 'cospend') {
102            throw new InvalidArgumentException();
103        }
104
105        $event = $this->getIcon($event);
106
107        $subjectIdentifier = $event->getSubject();
108        $subjectParams = $event->getSubjectParameters();
109        $ownActivity = ($event->getAuthor() === $this->userId);
110
111        /**
112         * Map stored parameter objects to rich string types
113         */
114        $params = [];
115
116        $author = $event->getAuthor();
117        // get author if
118        if ($author === '' && array_key_exists('author', $subjectParams)) {
119            $author = $subjectParams['author'];
120            $params = [
121                'user' => [
122                    'type' => 'user',
123                    'id' => 0,
124                    'name' => $subjectParams['author']
125                ],
126            ];
127            unset($subjectParams['author']);
128        }
129        $user = $this->userManager->get($author);
130        if ($user !== null) {
131            $params = [
132                'user' => [
133                    'type' => 'user',
134                    'id' => $author,
135                    'name' => $user->getDisplayName()
136                ],
137            ];
138            $event->setAuthor($author);
139        }
140        if ($event->getObjectType() === ActivityManager::COSPEND_OBJECT_PROJECT) {
141            if (isset($subjectParams['project']) && $event->getObjectName() === '') {
142                $event->setObject($event->getObjectType(), $event->getObjectId(), $subjectParams['project']['name']);
143            }
144            $project = [
145                'type' => 'highlight',
146                'id' => $event->getObjectId(),
147                'name' => $event->getObjectName(),
148                'link' => $this->cospendUrl('/project/' . $event->getObjectId()),
149            ];
150            $params['project'] = $project;
151        }
152
153        if (isset($subjectParams['bill']) && $event->getObjectType() === ActivityManager::COSPEND_OBJECT_BILL) {
154            if ($event->getObjectName() === '') {
155                $event->setObject($event->getObjectType(), $event->getObjectId(), $subjectParams['bill']['name']);
156            }
157            $bill = [
158                'type' => 'highlight',
159                'id' => $event->getObjectId(),
160                'name' => $event->getObjectName(),
161            ];
162
163            if (array_key_exists('project', $subjectParams)) {
164                $bill['link'] = $this->cospendUrl('/project/' . $subjectParams['project']['id']);
165            }
166            $params['bill'] = $bill;
167        }
168
169        $params = $this->parseParamForProject('project', $subjectParams, $params);
170        $params = $this->parseParamForBill('bill', $subjectParams, $params);
171        $params = $this->parseParamForWho($subjectParams, $params);
172
173        $event->setLink($subjectIdentifier);
174
175        try {
176            $subject = $this->activityManager->getActivityFormat($subjectIdentifier, $subjectParams, $ownActivity);
177            $this->setSubjects($event, $subject, $params);
178        } catch (Exception $e) {
179        }
180        return $event;
181    }
182
183    /**
184     * @param IEvent $event
185     * @param string $subject
186     * @param array $parameters
187     */
188    protected function setSubjects(IEvent $event, string $subject, array $parameters) {
189        $placeholders = $replacements = $richParameters = [];
190        foreach ($parameters as $placeholder => $parameter) {
191            $placeholders[] = '{' . $placeholder . '}';
192            if (is_array($parameter) && array_key_exists('name', $parameter)) {
193                $replacements[] = $parameter['name'];
194                $richParameters[$placeholder] = $parameter;
195            } else {
196                $replacements[] = '';
197            }
198        }
199
200        $event->setParsedSubject(str_replace($placeholders, $replacements, $subject))
201            ->setRichSubject($subject, $richParameters);
202        $event->setSubject($subject, $parameters);
203    }
204
205    private function getIcon(IEvent $event): IEvent {
206        $event->setIcon(
207            $this->urlGenerator->getAbsoluteURL(
208                $this->urlGenerator->imagePath('cospend', 'app_black.svg')
209            )
210        );
211        if (strpos($event->getSubject(), '_update') !== false) {
212            $event->setIcon(
213                $this->urlGenerator->getAbsoluteURL(
214                    $this->urlGenerator->imagePath('core', 'actions/rename.svg')
215                )
216            );
217        } elseif (strpos($event->getSubject(), '_create') !== false) {
218            $event->setIcon(
219                $this->urlGenerator->getAbsoluteURL(
220                    $this->urlGenerator->imagePath('files', 'add-color.svg')
221                )
222            );
223        } elseif (strpos($event->getSubject(), '_delete') !== false) {
224            $event->setIcon(
225                $this->urlGenerator->getAbsoluteURL(
226                    $this->urlGenerator->imagePath('files', 'delete-color.svg')
227                )
228            );
229        } elseif ($event->getSubject() === 'project_share' || $event->getSubject() === 'project_unshare') {
230            $event->setIcon(
231                $this->urlGenerator->getAbsoluteURL(
232                    $this->urlGenerator->imagePath('core', 'actions/share.svg')
233                )
234            );
235        }
236        return $event;
237    }
238
239    private function parseParamForProject($paramName, $subjectParams, $params) {
240        if (array_key_exists($paramName, $subjectParams)) {
241            $params[$paramName] = [
242                'type' => 'highlight',
243                'id' => $subjectParams[$paramName]['id'],
244                'name' => $this->projectNames[$subjectParams[$paramName]['id']] ?? $subjectParams[$paramName]['name'],
245                'link' => $this->cospendUrl('?project=' . $subjectParams[$paramName]['id']),
246            ];
247        }
248        return $params;
249    }
250    private function parseParamForBill($paramName, $subjectParams, $params) {
251        if (array_key_exists($paramName, $subjectParams)) {
252            $params[$paramName] = [
253                'type' => 'highlight',
254                'id' => $subjectParams[$paramName]['id'],
255                'name' => $subjectParams[$paramName]['name'].' ('.$subjectParams[$paramName]['amount'].')',
256                'link' => $this->cospendUrl('?project=' . $subjectParams['project']['id']) . '&bill='.$subjectParams[$paramName]['id'],
257            ];
258        }
259        return $params;
260    }
261
262    private function parseParamForWho($subjectParams, $params) {
263        if (array_key_exists('who', $subjectParams)) {
264            if ($subjectParams['type'] === Application::SHARE_TYPES['user']) {
265                $user = $this->userManager->get($subjectParams['who']);
266                if ($user === null) {
267                    throw new InvalidArgumentException();
268                }
269                $params['who'] = [
270                    'type' => 'user',
271                    'id' => $subjectParams['who'],
272                    'name' => $user !== null ? $user->getDisplayName() : $subjectParams['who']
273                ];
274            } elseif ($subjectParams['type'] === Application::SHARE_TYPES['group']) {
275                $group = $this->groupManager->get($subjectParams['who']);
276                if ($group === null) {
277                    throw new InvalidArgumentException();
278                }
279                $params['who'] = [
280                    'type' => 'highlight',
281                    'id' => $subjectParams['who'],
282                    'name' => $group !== null ? $group->getDisplayName() : $subjectParams['who']
283                ];
284            } elseif ($subjectParams['type'] === Application::SHARE_TYPES['circle']) {
285                $displayName = $this->l10n->t('circle %1$s', [$subjectParams['who']]);
286                $circlesEnabled = $this->appManager->isEnabledForUser('circles');
287                if ($circlesEnabled) {
288                    $circlesManager = \OC::$server->get(\OCA\Circles\CirclesManager::class);
289                    $circlesManager->startSuperSession();
290                    try {
291                        $circle = $circlesManager->getCircle($subjectParams['who']);
292                        $circleName = $circle->getDisplayName();
293                        $displayName = $this->l10n->t('circle %1$s', [$circleName]);
294                    } catch (\OCA\Circles\Exceptions\CircleNotFoundException $e) {
295                        throw new InvalidArgumentException();
296                    }
297                    $circlesManager->stopSession();
298                }
299                $params['who'] = [
300                    'type' => 'highlight',
301                    'id' => $subjectParams['who'],
302                    'name' => $displayName,
303                    // 'link' => \OCA\Circles\Api\v1\Circles::generateAbsoluteLink($subjectParams['who'])
304                ];
305            }
306        }
307        return $params;
308    }
309
310    public function cospendUrl($endpoint): string {
311        return $this->urlGenerator->linkToRouteAbsolute('cospend.page.index') . $endpoint;
312    }
313}