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

LibreSign / libresign / 20627540432

31 Dec 2025 09:31PM UTC coverage: 44.647%. First build
20627540432

Pull #6256

github

web-flow
Merge 1d36bae1f into 27812ed76
Pull Request #6256: feat: add dashboard pending signatures widget

0 of 91 new or added lines in 1 file covered. (0.0%)

6618 of 14823 relevant lines covered (44.65%)

5.05 hits per line

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

0.0
/lib/Dashboard/PendingSignaturesWidget.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * SPDX-FileCopyrightText: 2025 LibreSign
7
 * SPDX-License-Identifier: AGPL-3.0-or-later
8
 */
9

10
namespace OCA\Libresign\Dashboard;
11

12
use OCA\Libresign\AppInfo\Application;
13
use OCA\Libresign\Db\SignRequestMapper;
14
use OCA\Libresign\Service\SignFileService;
15
use OCP\Dashboard\IAPIWidget;
16
use OCP\Dashboard\IAPIWidgetV2;
17
use OCP\Dashboard\IButtonWidget;
18
use OCP\Dashboard\IIconWidget;
19
use OCP\Dashboard\Model\WidgetButton;
20
use OCP\Dashboard\Model\WidgetItem;
21
use OCP\Dashboard\Model\WidgetItems;
22
use OCP\IL10N;
23
use OCP\IURLGenerator;
24
use OCP\IUserSession;
25
use Override;
26

27
class PendingSignaturesWidget implements IAPIWidget, IAPIWidgetV2, IButtonWidget, IIconWidget {
28
        public function __construct(
29
                private IL10N $l10n,
30
                private IURLGenerator $urlGenerator,
31
                private SignFileService $signFileService,
32
                private SignRequestMapper $signRequestMapper,
33
                private IUserSession $userSession,
34
        ) {
NEW
35
        }
×
36

37
        #[Override]
38
        public function getId(): string {
NEW
39
                return 'libresign_pending_signatures';
×
40
        }
41

42
        #[Override]
43
        public function getTitle(): string {
NEW
44
                return $this->l10n->t('Pending signatures');
×
45
        }
46

47
        #[Override]
48
        public function getOrder(): int {
NEW
49
                return 10;
×
50
        }
51

52
        #[Override]
53
        public function getIconClass(): string {
NEW
54
                return 'icon-libresign';
×
55
        }
56

57
        #[Override]
58
        public function getIconUrl(): string {
NEW
59
                return $this->urlGenerator->getAbsoluteURL(
×
NEW
60
                        $this->urlGenerator->imagePath(Application::APP_ID, 'app-dark.svg')
×
NEW
61
                );
×
62
        }
63

64
        #[Override]
65
        public function getUrl(): ?string {
NEW
66
                return $this->urlGenerator->linkToRouteAbsolute('libresign.page.index');
×
67
        }
68

69
        #[Override]
70
        public function load(): void {
71
                // No special loading required
NEW
72
        }
×
73

74
        #[Override]
75
        public function getItemsV2(string $userId, ?string $since = null, int $limit = 7): WidgetItems {
76
                try {
NEW
77
                        $user = $this->userSession->getUser();
×
NEW
78
                        if (!$user) {
×
NEW
79
                                return new WidgetItems([], $this->l10n->t('User not found'));
×
80
                        }
81

NEW
82
                        $result = $this->signRequestMapper->getFilesAssociatedFilesWithMe(
×
NEW
83
                                $user,
×
NEW
84
                                ['status' => [\OCA\Libresign\Db\File::STATUS_ABLE_TO_SIGN, \OCA\Libresign\Db\File::STATUS_PARTIAL_SIGNED]],
×
NEW
85
                                1,
×
NEW
86
                                $limit,
×
NEW
87
                                ['sortBy' => 'created_at', 'sortDirection' => 'desc']
×
NEW
88
                        );
×
89

NEW
90
                        $items = [];
×
91

NEW
92
                        foreach ($result['data'] as $fileEntity) {
×
93
                                try {
NEW
94
                                        $signRequest = $this->getSignRequestForUser($fileEntity, $user);
×
95

NEW
96
                                        if (!$signRequest || $signRequest->getSigned()) {
×
NEW
97
                                                continue;
×
98
                                        }
99

NEW
100
                                        $item = new WidgetItem(
×
NEW
101
                                                $this->getDocumentTitle($fileEntity),
×
NEW
102
                                                $this->getSubtitle($signRequest, $fileEntity),
×
NEW
103
                                                $this->urlGenerator->linkToRouteAbsolute('libresign.page.signFPath', ['uuid' => $signRequest->getUuid(), 'path' => 'pdf']),
×
NEW
104
                                                $this->urlGenerator->getAbsoluteURL(
×
NEW
105
                                                        $this->urlGenerator->imagePath('core', 'filetypes/application-pdf.svg')
×
NEW
106
                                                ),
×
NEW
107
                                                $this->getTimestamp($fileEntity)
×
NEW
108
                                        );
×
109

NEW
110
                                        $items[] = $item;
×
NEW
111
                                } catch (\Exception $e) {
×
NEW
112
                                        continue;
×
113
                                }
114
                        }
115

NEW
116
                        return new WidgetItems(
×
NEW
117
                                $items,
×
NEW
118
                                empty($items) ? $this->l10n->t('No pending signatures') : '',
×
NEW
119
                        );
×
NEW
120
                } catch (\Exception $e) {
×
NEW
121
                        return new WidgetItems(
×
NEW
122
                                [],
×
NEW
123
                                $this->l10n->t('Error loading pending signatures'),
×
NEW
124
                        );
×
125
                }
126
        }
127

128
        private function getSignRequestForUser(\OCA\Libresign\Db\File $fileEntity, \OCP\IUser $user): ?\OCA\Libresign\Db\SignRequest {
129
                try {
NEW
130
                        $signRequests = $this->signRequestMapper->getByFileId($fileEntity->getId());
×
131

NEW
132
                        foreach ($signRequests as $signRequest) {
×
NEW
133
                                if ($this->signRequestBelongsToUser($signRequest, $user)) {
×
NEW
134
                                        return $signRequest;
×
135
                                }
136
                        }
NEW
137
                } catch (\Exception $e) {
×
NEW
138
                        return null;
×
139
                }
140

NEW
141
                return null;
×
142
        }
143

144
        private function signRequestBelongsToUser(\OCA\Libresign\Db\SignRequest $signRequest, \OCP\IUser $user): bool {
145
                try {
NEW
146
                        $validSignRequest = $this->signFileService->getSignRequestToSign(
×
NEW
147
                                $this->signFileService->getFile($signRequest->getFileId()),
×
NEW
148
                                $signRequest->getUuid(),
×
NEW
149
                                $user
×
NEW
150
                        );
×
151

NEW
152
                        return $validSignRequest->getId() === $signRequest->getId();
×
NEW
153
                } catch (\Exception $e) {
×
NEW
154
                        return false;
×
155
                }
156
        }
157

158
        private function getDocumentTitle(\OCA\Libresign\Db\File $fileEntity): string {
NEW
159
                if ($fileEntity->getName()) {
×
NEW
160
                        return $fileEntity->getName();
×
161
                }
162

163
                try {
NEW
164
                        $files = $this->signFileService->getNextcloudFiles($fileEntity);
×
NEW
165
                        if (!empty($files)) {
×
NEW
166
                                $file = current($files);
×
NEW
167
                                return $file->getName();
×
168
                        }
NEW
169
                } catch (\Exception $e) {
×
170
                }
171

NEW
172
                return $this->l10n->t('Document');
×
173
        }
174

175
        private function getSubtitle(\OCA\Libresign\Db\SignRequest $signRequest, \OCA\Libresign\Db\File $fileEntity): string {
NEW
176
                $parts = [];
×
177

NEW
178
                $displayName = $signRequest->getDisplayName();
×
NEW
179
                if ($displayName) {
×
NEW
180
                        $parts[] = $this->l10n->t('From: %s', [$displayName]);
×
181
                }
182

NEW
183
                $createdAt = $fileEntity->getCreatedAt();
×
NEW
184
                if ($createdAt instanceof \DateTime) {
×
NEW
185
                        $date = $createdAt->format('d/m/Y');
×
NEW
186
                        $parts[] = $this->l10n->t('Date: %s', [$date]);
×
187
                }
188

NEW
189
                return implode(' • ', $parts);
×
190
        }
191

192
        private function getTimestamp(\OCA\Libresign\Db\File $fileEntity): string {
NEW
193
                $createdAt = $fileEntity->getCreatedAt();
×
NEW
194
                if ($createdAt instanceof \DateTime) {
×
NEW
195
                        return (string)$createdAt->getTimestamp();
×
196
                }
NEW
197
                return '';
×
198
        }
199

200
        #[Override]
201
        public function getItems(string $userId, ?string $since = null, int $limit = 7): array {
NEW
202
                $widgetItems = $this->getItemsV2($userId, $since, $limit);
×
NEW
203
                return $widgetItems->getItems();
×
204
        }
205

206
        #[Override]
207
        public function getWidgetButtons(string $userId): array {
NEW
208
                return [
×
NEW
209
                        new WidgetButton(
×
NEW
210
                                WidgetButton::TYPE_MORE,
×
NEW
211
                                $this->urlGenerator->linkToRouteAbsolute('libresign.page.index'),
×
NEW
212
                                $this->l10n->t('View all documents')
×
NEW
213
                        ),
×
NEW
214
                ];
×
215
        }
216
}
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