Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 190
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Notifier
0.00% covered (danger)
0.00%
0 / 190
0.00% covered (danger)
0.00%
0 / 7
462
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getID
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 prepare
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 parseSignRequest
0.00% covered (danger)
0.00%
0 / 64
0.00% covered (danger)
0.00%
0 / 1
42
 parseSigned
0.00% covered (danger)
0.00%
0 / 62
0.00% covered (danger)
0.00%
0 / 1
30
 parseCanceled
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\Notification;
10
11use OCA\Libresign\AppInfo\Application;
12use OCA\Libresign\Db\FileMapper;
13use OCA\Libresign\Db\SignRequestMapper;
14use OCP\IL10N;
15use OCP\IURLGenerator;
16use OCP\L10N\IFactory;
17use OCP\Notification\IAction;
18use OCP\Notification\INotification;
19use OCP\Notification\INotifier;
20use OCP\Notification\UnknownNotificationException;
21use OCP\RichObjectStrings\Definitions;
22
23class Notifier implements INotifier {
24    public function __construct(
25        private IFactory $factory,
26        private IURLGenerator $url,
27        private Definitions $definitions,
28        private FileMapper $fileMapper,
29        private SignRequestMapper $signRequestMapper,
30    ) {
31    }
32
33    #[\Override]
34    public function getID(): string {
35        return Application::APP_ID;
36    }
37
38    #[\Override]
39    public function getName(): string {
40        // TRANSLATORS Notification app category label shown in Nextcloud notification settings.
41        return $this->factory->get(Application::APP_ID)->t('File sharing');
42    }
43
44    #[\Override]
45    public function prepare(INotification $notification, string $languageCode): INotification {
46        if ($notification->getApp() !== Application::APP_ID) {
47            throw new UnknownNotificationException();
48        }
49
50        $l = $this->factory->get(Application::APP_ID, $languageCode);
51
52        return match ($notification->getSubject()) {
53            'new_sign_request' => $this->parseSignRequest($notification, $l, false),
54            'update_sign_request' => $this->parseSignRequest($notification, $l, true),
55            'file_signed' => $this->parseSigned($notification, $l),
56            'sign_request_canceled' => $this->parseCanceled($notification, $l),
57            default => throw new UnknownNotificationException(),
58        };
59    }
60
61    private function parseSignRequest(
62        INotification $notification,
63        IL10N $l,
64        bool $update,
65    ): INotification {
66
67        $this->definitions->definitions['sign-request'] = [
68            'author' => 'LibreSign',
69            'since' => '28.0.0',
70            'parameters' => [
71                'id' => [
72                    'since' => '28.0.0',
73                    'required' => true,
74                    'description' => 'The id of SignRequest object',
75                    'example' => '12345',
76                ],
77                'name' => [
78                    'since' => '28.0.0',
79                    'required' => true,
80                    'description' => 'The display name of signer',
81                    'example' => 'John Doe',
82                ],
83            ],
84        ];
85
86        $parameters = $notification->getSubjectParameters();
87        $notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath(Application::APP_ID, 'app-dark.svg')));
88        if (isset($parameters['file'])) {
89            $notification->setLink($parameters['file']['link']);
90            $signAction = $notification->createAction()
91                // TRANSLATORS Action button opening the related file from a LibreSign notification.
92                ->setParsedLabel($l->t('View'))
93                ->setPrimary(true)
94                ->setLink(
95                    $parameters['file']['link'],
96                    IAction::TYPE_WEB
97                );
98            $notification->addParsedAction($signAction);
99            if (isset($parameters['from'])) {
100                // TRANSLATORS Notification subject. {from} is the user who requested a signature, {file} is the document name.
101                $subject = $l->t('{from} requested your signature on {file}');
102                $notification->setParsedSubject(
103                    str_replace(
104                        ['{from}', '{file}'],
105                        [
106                            $parameters['from']['name'],
107                            $parameters['file']['name'],
108                        ],
109                        $subject
110                    ))
111                    ->setRichSubject($subject, $parameters);
112            }
113        }
114        if ($update) {
115            // TRANSLATORS Notification message informing the signer that a pending document changed and should be reviewed again.
116            $notification->setParsedMessage($l->t('Changes were made to a document you need to sign.'));
117        }
118
119        if (isset($parameters['signRequest']) && isset($parameters['signRequest']['id'])) {
120            $dismissAction = $notification->createAction()
121                // TRANSLATORS Action button that dismisses this notification from the notification list.
122                ->setParsedLabel($l->t('Dismiss notification'))
123                ->setLink(
124                    $this->url->linkToOCSRouteAbsolute(
125                        'libresign.notify.notificationDismiss',
126                        [
127                            'apiVersion' => 'v1',
128                            'timestamp' => $notification->getDateTime()->getTimestamp(),
129                            'objectType' => 'signRequest',
130                            'objectId' => $parameters['signRequest']['id'],
131                            'subject' => 'new_sign_request',
132                        ],
133                    ),
134                    IAction::TYPE_DELETE
135                );
136            $notification->addParsedAction($dismissAction);
137        }
138
139        return $notification;
140    }
141
142    private function parseSigned(
143        INotification $notification,
144        IL10N $l,
145    ): INotification {
146
147        $this->definitions->definitions['signer'] = [
148            'author' => 'LibreSign',
149            'since' => '30.0.0',
150            'parameters' => [
151                'id' => [
152                    'since' => '30.0.0',
153                    'required' => true,
154                    'description' => 'The identify method id',
155                    'example' => '12345',
156                ],
157                'name' => [
158                    'since' => '30.0.0',
159                    'required' => true,
160                    'description' => 'The display name of signer',
161                    'example' => 'John Doe',
162                ],
163            ],
164        ];
165
166        $parameters = $notification->getSubjectParameters();
167        $notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath(Application::APP_ID, 'app-dark.svg')));
168        if (isset($parameters['file'])) {
169            $notification->setLink($parameters['file']['link']);
170            $signAction = $notification->createAction()
171                // TRANSLATORS Action button opening the signed file from a notification.
172                ->setParsedLabel($l->t('View'))
173                ->setPrimary(true)
174                ->setLink(
175                    $parameters['file']['link'],
176                    IAction::TYPE_WEB
177                );
178            $notification->addParsedAction($signAction);
179            if (isset($parameters['from'])) {
180                // TRANSLATORS Notification subject. {from} is the signer name and {file} is the document name that was signed.
181                $subject = $l->t('{from} signed {file}');
182                $notification->setParsedSubject(
183                    str_replace(
184                        ['{from}', '{file}'],
185                        [
186                            $parameters['from']['name'],
187                            $parameters['file']['name'],
188                        ],
189                        $subject
190                    ))
191                    ->setRichSubject($subject, $parameters);
192            }
193        }
194
195        if (isset($parameters['signedFile']) && isset($parameters['signedFile']['id'])) {
196            $dismissAction = $notification->createAction()
197                // TRANSLATORS Action button that dismisses this notification from the notification list.
198                ->setParsedLabel($l->t('Dismiss notification'))
199                ->setLink(
200                    $this->url->linkToOCSRouteAbsolute(
201                        'libresign.notify.notificationDismiss',
202                        [
203                            'apiVersion' => 'v1',
204                            'timestamp' => $notification->getDateTime()->getTimestamp(),
205                            'objectType' => 'signedFile',
206                            'objectId' => $parameters['signedFile']['id'],
207                            'subject' => 'file_signed',
208                        ],
209                    ),
210                    IAction::TYPE_DELETE
211                );
212            $notification->addParsedAction($dismissAction);
213        }
214
215        return $notification;
216    }
217
218    private function parseCanceled(
219        INotification $notification,
220        IL10N $l,
221    ): INotification {
222
223        $this->definitions->definitions['sign-request'] = [
224            'author' => 'LibreSign',
225            'since' => '28.0.0',
226            'parameters' => [
227                'id' => [
228                    'since' => '28.0.0',
229                    'required' => true,
230                    'description' => 'The id of SignRequest object',
231                    'example' => '12345',
232                ],
233                'name' => [
234                    'since' => '28.0.0',
235                    'required' => true,
236                    'description' => 'The display name of signer',
237                    'example' => 'John Doe',
238                ],
239            ],
240        ];
241
242        $parameters = $notification->getSubjectParameters();
243        $notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath(Application::APP_ID, 'app-dark.svg')));
244
245        if (isset($parameters['from']) && isset($parameters['file'])) {
246            // TRANSLATORS Notification subject. {from} is the actor who canceled, {file} is the document name whose signature request was canceled.
247            $subject = $l->t('{from} canceled the signature request for {file}');
248            $notification->setParsedSubject(
249                str_replace(
250                    ['{from}', '{file}'],
251                    [
252                        $parameters['from']['name'],
253                        $parameters['file']['name'],
254                    ],
255                    $subject
256                ))
257                ->setRichSubject($subject, $parameters);
258        }
259
260        if (isset($parameters['signRequest']) && isset($parameters['signRequest']['id'])) {
261            $dismissAction = $notification->createAction()
262                // TRANSLATORS Action button that dismisses this cancellation notification.
263                ->setParsedLabel($l->t('Dismiss notification'))
264                ->setLink(
265                    $this->url->linkToOCSRouteAbsolute(
266                        'libresign.notify.notificationDismiss',
267                        [
268                            'apiVersion' => 'v1',
269                            'timestamp' => $notification->getDateTime()->getTimestamp(),
270                            'objectType' => 'signRequest',
271                            'objectId' => $parameters['signRequest']['id'],
272                            'subject' => 'sign_request_canceled',
273                        ],
274                    ),
275                    IAction::TYPE_DELETE
276                );
277            $notification->addParsedAction($dismissAction);
278        }
279
280        return $notification;
281    }
282}