• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LibreSign / libresign / 20284436755

16 Dec 2025 10:14PM UTC coverage: 43.738%. First build
20284436755

Pull #6216

github

web-flow
Merge 263a8cf56 into db13f2cda
Pull Request #6216: feat: custom message for signers

5 of 67 new or added lines in 6 files covered. (7.46%)

5926 of 13549 relevant lines covered (43.74%)

5.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.49
/lib/Listener/NotificationListener.php
1
<?php
2

3
declare(strict_types=1);
4
/**
5
 * SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8

9
namespace OCA\Libresign\Listener;
10

11
use OCA\Libresign\AppInfo\Application as AppInfoApplication;
12
use OCA\Libresign\Db\File as FileEntity;
13
use OCA\Libresign\Db\SignRequest;
14
use OCA\Libresign\Db\SignRequestMapper;
15
use OCA\Libresign\Events\SendSignNotificationEvent;
16
use OCA\Libresign\Events\SignedEvent;
17
use OCA\Libresign\Events\SignRequestCanceledEvent;
18
use OCA\Libresign\Service\IdentifyMethod\IIdentifyMethod;
19
use OCP\AppFramework\Utility\ITimeFactory;
20
use OCP\EventDispatcher\Event;
21
use OCP\EventDispatcher\IEventListener;
22
use OCP\IURLGenerator;
23
use OCP\IUser;
24
use OCP\IUserSession;
25
use OCP\Notification\IManager;
26

27
/**
28
 * @template-implements IEventListener<Event>
29
 */
30
class NotificationListener implements IEventListener {
31
        public function __construct(
32
                private IManager $notificationManager,
33
                protected IUserSession $userSession,
34
                private ITimeFactory $timeFactory,
35
                protected IURLGenerator $url,
36
                private SignRequestMapper $signRequestMapper,
37
        ) {
38
        }
13✔
39

40
        #[\Override]
41
        public function handle(Event $event): void {
42
                if ($event instanceof SendSignNotificationEvent) {
13✔
43
                        $this->sendSignNotification(
13✔
44
                                $event->getSignRequest(),
13✔
45
                                $event->getLibreSignFile(),
13✔
46
                                $event->getIdentifyMethod(),
13✔
47
                        );
13✔
48
                } elseif ($event instanceof SignedEvent) {
2✔
49
                        $this->sendSignedNotification(
×
50
                                $event->getSignRequest(),
×
51
                                $event->getLibreSignFile(),
×
52
                                $event->getIdentifyMethod(),
×
53
                        );
×
54
                } elseif ($event instanceof SignRequestCanceledEvent) {
2✔
55
                        $this->sendCanceledNotification(
2✔
56
                                $event->getSignRequest(),
2✔
57
                                $event->getLibreSignFile(),
2✔
58
                                $event->getIdentifyMethod(),
2✔
59
                        );
2✔
60
                }
61
        }
62

63
        private function sendSignNotification(
64
                SignRequest $signRequest,
65
                FileEntity $libreSignFile,
66
                IIdentifyMethod $identifyMethod,
67
        ): void {
68
                $actor = $this->userSession->getUser();
13✔
69
                if (!$actor instanceof IUser) {
13✔
70
                        return;
12✔
71
                }
72
                if ($identifyMethod->getEntity()->isDeletedAccount()) {
3✔
73
                        return;
×
74
                }
75
                $notificationDisabled = $this->isNotificationDisabledAtActivity(
3✔
76
                        $identifyMethod->getEntity()->getIdentifierValue(),
3✔
77
                        SendSignNotificationEvent::FILE_TO_SIGN,
3✔
78
                );
3✔
79
                if ($notificationDisabled) {
3✔
80
                        return;
×
81
                }
82
                $notification = $this->notificationManager->createNotification();
3✔
83
                $notification
3✔
84
                        ->setApp(AppInfoApplication::APP_ID)
3✔
85
                        ->setObject('signRequest', (string)$signRequest->getId())
3✔
86
                        ->setDateTime((new \DateTime())->setTimestamp($this->timeFactory->now()->getTimestamp()))
3✔
87
                        ->setUser($identifyMethod->getEntity()->getIdentifierValue());
3✔
88
                $isFirstNotification = $this->signRequestMapper->incrementNotificationCounter($signRequest, 'notify');
3✔
89
                if ($isFirstNotification) {
3✔
90
                        $subject = 'new_sign_request';
3✔
91
                } else {
92
                        $subject = 'update_sign_request';
×
93
                }
94
                $notification->setSubject($subject, [
3✔
95
                        'from' => $this->getUserParameter(
3✔
96
                                $actor->getUID(),
3✔
97
                                $actor->getDisplayName(),
3✔
98
                        ),
3✔
99
                        'file' => $this->getFileParameter($signRequest, $libreSignFile),
3✔
100
                        'signRequest' => [
3✔
101
                                'type' => 'sign-request',
3✔
102
                                'id' => (string)$signRequest->getId(),
3✔
103
                                'name' => $actor->getDisplayName(),
3✔
104
                        ],
3✔
105
                ]);
3✔
106
                $this->notificationManager->notify($notification);
3✔
107
        }
108

109
        private function sendSignedNotification(
110
                SignRequest $signRequest,
111
                FileEntity $libreSignFile,
112
                IIdentifyMethod $identifyMethod,
113
        ): void {
114

115
                $actorId = $libreSignFile->getUserId();
×
116

117
                if ($identifyMethod->getEntity()->isDeletedAccount()) {
×
118
                        return;
×
119
                }
120
                $notificationDisabled = $this->isNotificationDisabledAtActivity(
×
121
                        $libreSignFile->getUserId(),
×
122
                        SignedEvent::FILE_SIGNED,
×
123
                );
×
124
                if ($notificationDisabled) {
×
125
                        return;
×
126
                }
127

128
                $notification = $this->notificationManager->createNotification();
×
129
                $notification
×
130
                        ->setApp(AppInfoApplication::APP_ID)
×
131
                        ->setObject('signedFile', (string)$signRequest->getId())
×
132
                        ->setDateTime((new \DateTime())->setTimestamp($this->timeFactory->now()->getTimestamp())->setTimezone(new \DateTimeZone('UTC')))
×
133
                        ->setUser($actorId)
×
134
                        ->setSubject('file_signed', [
×
135
                                'from' => $this->getFromSignedParameter(
×
136
                                        $identifyMethod->getEntity()->getIdentifierKey(),
×
137
                                        $identifyMethod->getEntity()->getIdentifierValue(),
×
138
                                        $signRequest->getDisplayName(),
×
139
                                        $identifyMethod->getEntity()->getId(),
×
140
                                ),
×
141
                                'file' => [
×
142
                                        'type' => 'file',
×
143
                                        'id' => (string)$libreSignFile->getNodeId(),
×
144
                                        'name' => $libreSignFile->getName(),
×
145
                                        'path' => $libreSignFile->getName(),
×
146
                                        'link' => $this->url->linkToRouteAbsolute('libresign.page.indexFPath', [
×
147
                                                'path' => 'validation/' . $libreSignFile->getUuid(),
×
148
                                        ]),
×
149
                                ],
×
150
                                'signedFile' => [
×
151
                                        'type' => 'signer',
×
152
                                        'id' => (string)$signRequest->getId(),
×
153
                                        'name' => $signRequest->getDisplayName(),
×
154
                                ],
×
155
                        ]);
×
156

157
                $this->notificationManager->notify($notification);
×
158
        }
159

160
        private function sendCanceledNotification(
161
                SignRequest $signRequest,
162
                FileEntity $libreSignFile,
163
                IIdentifyMethod $identifyMethod,
164
        ): void {
165
                $actor = $this->userSession->getUser();
2✔
166
                if (!$actor instanceof IUser) {
2✔
167
                        return;
×
168
                }
169
                if ($identifyMethod->getEntity()->isDeletedAccount()) {
2✔
170
                        return;
×
171
                }
172
                $notificationDisabled = $this->isNotificationDisabledAtActivity(
2✔
173
                        $identifyMethod->getEntity()->getIdentifierValue(),
2✔
174
                        SignRequestCanceledEvent::SIGN_REQUEST_CANCELED,
2✔
175
                );
2✔
176
                if ($notificationDisabled) {
2✔
177
                        return;
×
178
                }
179

180
                $notification = $this->notificationManager->createNotification();
2✔
181
                $notification
2✔
182
                        ->setApp(AppInfoApplication::APP_ID)
2✔
183
                        ->setObject('signRequest', (string)$signRequest->getId())
2✔
184
                        ->setDateTime((new \DateTime())->setTimestamp($this->timeFactory->now()->getTimestamp()))
2✔
185
                        ->setUser($identifyMethod->getEntity()->getIdentifierValue())
2✔
186
                        ->setSubject('sign_request_canceled', [
2✔
187
                                'from' => $this->getUserParameter(
2✔
188
                                        $actor->getUID(),
2✔
189
                                        $actor->getDisplayName(),
2✔
190
                                ),
2✔
191
                                'file' => [
2✔
192
                                        'type' => 'file',
2✔
193
                                        'id' => (string)$libreSignFile->getNodeId(),
2✔
194
                                        'name' => $libreSignFile->getName(),
2✔
195
                                        'path' => $libreSignFile->getName(),
2✔
196
                                ],
2✔
197
                                'signRequest' => [
2✔
198
                                        'type' => 'sign-request',
2✔
199
                                        'id' => (string)$signRequest->getId(),
2✔
200
                                        'name' => $actor->getDisplayName(),
2✔
201
                                ],
2✔
202
                        ]);
2✔
203

204
                $this->notificationManager->notify($notification);
2✔
205
        }
206

207
        private function isNotificationDisabledAtActivity(string $userId, string $type): bool {
208
                if (!class_exists(\OCA\Activity\UserSettings::class)) {
4✔
209
                        return false;
4✔
210
                }
211
                $activityUserSettings = \OCP\Server::get(\OCA\Activity\UserSettings::class);
×
212
                if ($activityUserSettings) {
×
NEW
213
                        $manager = \OCP\Server::get(\OCP\Activity\IManager::class);
×
214
                        try {
NEW
215
                                $manager->getSettingById($type);
×
NEW
216
                        } catch (\Exception $e) {
×
NEW
217
                                return false;
×
218
                        }
219

NEW
220
                        $adminSetting = $activityUserSettings->getAdminSetting('notification', $type);
×
NEW
221
                        if (!$adminSetting) {
×
NEW
222
                                return true;
×
223
                        }
224

225
                        $notificationSetting = $activityUserSettings->getUserSetting(
×
226
                                $userId,
×
227
                                'notification',
×
228
                                $type
×
229
                        );
×
230
                        if ($notificationSetting === false) {
×
231
                                return true;
×
232
                        }
233
                }
234
                return false;
×
235
        }
236

237
        /**
238
         * @psalm-return array{type: 'file', id: string, name: string, path: string, link: string}
239
         */
240
        protected function getFileParameter(SignRequest $signRequest, FileEntity $libreSignFile): array {
241
                return [
3✔
242
                        'type' => 'file',
3✔
243
                        'id' => (string)$libreSignFile->getNodeId(),
3✔
244
                        'name' => $libreSignFile->getName(),
3✔
245
                        'path' => $libreSignFile->getName(),
3✔
246
                        'link' => $this->url->linkToRouteAbsolute('libresign.page.signFPath', ['uuid' => $signRequest->getUuid(), 'path' => 'pdf']),
3✔
247
                ];
3✔
248
        }
249

250
        protected function getUserParameter(
251
                string $userId,
252
                string $displayName,
253
        ): array {
254
                return [
4✔
255
                        'type' => 'user',
4✔
256
                        'id' => $userId,
4✔
257
                        'name' => $displayName,
4✔
258
                ];
4✔
259
        }
260

261
        protected function getFromSignedParameter(
262
                string $type,
263
                string $identifier,
264
                string $displayName,
265
                int $identifyMethodId,
266
        ): array {
267

268
                if ($type === 'account') {
×
269
                        return $this->getUserParameter(
×
270
                                $identifier,
×
271
                                $displayName
×
272
                        );
×
273
                }
274

275
                return [
×
276
                        'type' => 'signer',
×
277
                        'id' => (string)$identifyMethodId,
×
278
                        'name' => $displayName,
×
279
                ];
×
280
        }
281
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc