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

LibreSign / libresign / 20626396441

31 Dec 2025 08:10PM UTC coverage: 44.647%. First build
20626396441

Pull #6256

github

web-flow
Merge ba17304b2 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\Db\SignRequestMapper;
13
use OCA\Libresign\Service\SignFileService;
14
use OCA\Libresign\AppInfo\Application;
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 OCP\Util;
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
        /**
38
         * @inheritDoc
39
         */
40
        public function getId(): string {
NEW
41
                return 'libresign_pending_signatures';
×
42
        }
43

44
        /**
45
         * @inheritDoc
46
         */
47
        public function getTitle(): string {
NEW
48
                return $this->l10n->t('Pending signatures');
×
49
        }
50

51
        /**
52
         * @inheritDoc
53
         */
54
        public function getOrder(): int {
NEW
55
                return 10;
×
56
        }
57

58
        /**
59
         * @inheritDoc
60
         */
61
        public function getIconClass(): string {
NEW
62
                return 'icon-libresign';
×
63
        }
64

65
        /**
66
         * @inheritDoc
67
         */
68
        public function getIconUrl(): string {
NEW
69
                return $this->urlGenerator->getAbsoluteURL(
×
NEW
70
                        $this->urlGenerator->imagePath(Application::APP_ID, 'app-dark.svg')
×
NEW
71
                );
×
72
        }
73

74
        /**
75
         * @inheritDoc
76
         */
77
        public function getUrl(): ?string {
NEW
78
                return $this->urlGenerator->linkToRouteAbsolute('libresign.page.index');
×
79
        }
80

81
        /**
82
         * @inheritDoc
83
         */
84
        public function load(): void {
85

NEW
86
        }
×
87

88
        /**
89
         * @inheritDoc
90
         */
91
        public function getItemsV2(string $userId, ?string $since = null, int $limit = 7): WidgetItems {
92
                try {
NEW
93
                        $user = $this->userSession->getUser();
×
NEW
94
                        if (!$user) {
×
NEW
95
                                return new WidgetItems([], $this->l10n->t('User not found'));
×
96
                        }
97

NEW
98
                        $result = $this->signRequestMapper->getFilesAssociatedFilesWithMe(
×
NEW
99
                                $user,
×
NEW
100
                                ['status' => [\OCA\Libresign\Db\File::STATUS_ABLE_TO_SIGN, \OCA\Libresign\Db\File::STATUS_PARTIAL_SIGNED]],
×
NEW
101
                                1,
×
NEW
102
                                $limit,
×
NEW
103
                                ['sortBy' => 'created_at', 'sortDirection' => 'desc']
×
NEW
104
                        );
×
105

NEW
106
                        $items = [];
×
107

NEW
108
                        foreach ($result['data'] as $fileEntity) {
×
109
                                try {
NEW
110
                                        $signRequest = $this->getSignRequestForUser($fileEntity, $user);
×
111

NEW
112
                                        if (!$signRequest || $signRequest->getSigned()) {
×
NEW
113
                                                continue;
×
114
                                        }
115

NEW
116
                                        $item = new WidgetItem(
×
NEW
117
                                                $this->getDocumentTitle($fileEntity),
×
NEW
118
                                                $this->getSubtitle($signRequest, $fileEntity),
×
NEW
119
                                                $this->urlGenerator->linkToRouteAbsolute('libresign.page.signFPath', ['uuid' => $signRequest->getUuid(), 'path' => 'pdf']),
×
NEW
120
                                                $this->urlGenerator->getAbsoluteURL(
×
NEW
121
                                                        $this->urlGenerator->imagePath('core', 'filetypes/application-pdf.svg')
×
NEW
122
                                                ),
×
NEW
123
                                                $this->getTimestamp($fileEntity)
×
NEW
124
                                        );
×
125

NEW
126
                                        $items[] = $item;
×
NEW
127
                                } catch (\Exception $e) {
×
NEW
128
                                        continue;
×
129
                                }
130
                        }
131

NEW
132
                        return new WidgetItems(
×
NEW
133
                                $items,
×
NEW
134
                                empty($items) ? $this->l10n->t('No pending signatures') : '',
×
NEW
135
                        );
×
NEW
136
                } catch (\Exception $e) {
×
NEW
137
                        return new WidgetItems(
×
NEW
138
                                [],
×
NEW
139
                                $this->l10n->t('Error loading pending signatures'),
×
NEW
140
                        );
×
141
                }
142
        }
143

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

NEW
148
                        foreach ($signRequests as $signRequest) {
×
NEW
149
                                if ($this->signRequestBelongsToUser($signRequest, $user)) {
×
NEW
150
                                        return $signRequest;
×
151
                                }
152
                        }
NEW
153
                } catch (\Exception $e) {
×
NEW
154
                        return null;
×
155
                }
156

NEW
157
                return null;
×
158
        }
159

160
        private function signRequestBelongsToUser(\OCA\Libresign\Db\SignRequest $signRequest, \OCP\IUser $user): bool {
161
                try {
NEW
162
                        $validSignRequest = $this->signFileService->getSignRequestToSign(
×
NEW
163
                                $this->signFileService->getFile($signRequest->getFileId()),
×
NEW
164
                                $signRequest->getUuid(),
×
NEW
165
                                $user
×
NEW
166
                        );
×
167

NEW
168
                        return $validSignRequest->getId() === $signRequest->getId();
×
NEW
169
                } catch (\Exception $e) {
×
NEW
170
                        return false;
×
171
                }
172
        }
173

174
        private function getDocumentTitle(\OCA\Libresign\Db\File $fileEntity): string {
NEW
175
                if ($fileEntity->getName()) {
×
NEW
176
                        return $fileEntity->getName();
×
177
                }
178

179
                try {
NEW
180
                        $files = $this->signFileService->getNextcloudFiles($fileEntity);
×
NEW
181
                        if (!empty($files)) {
×
NEW
182
                                $file = current($files);
×
NEW
183
                                return $file->getName();
×
184
                        }
NEW
185
                } catch (\Exception $e) {
×
186
                }
187

NEW
188
                return $this->l10n->t('Document');
×
189
        }
190

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

NEW
194
                $displayName = $signRequest->getDisplayName();
×
NEW
195
                if ($displayName) {
×
NEW
196
                        $parts[] = $this->l10n->t('From: %s', [$displayName]);
×
197
                }
198

NEW
199
                $createdAt = $fileEntity->getCreatedAt();
×
NEW
200
                if ($createdAt instanceof \DateTime) {
×
NEW
201
                        $date = $createdAt->format('d/m/Y');
×
NEW
202
                        $parts[] = $this->l10n->t('Date: %s', [$date]);
×
203
                }
204

NEW
205
                return implode(' • ', $parts);
×
206
        }
207

208
        private function getTimestamp(\OCA\Libresign\Db\File $fileEntity): string {
NEW
209
                $createdAt = $fileEntity->getCreatedAt();
×
NEW
210
                if ($createdAt instanceof \DateTime) {
×
NEW
211
                        return (string)$createdAt->getTimestamp();
×
212
                }
NEW
213
                return '';
×
214
        }
215

216
        /**
217
         * @inheritDoc
218
         * @deprecated Use getItemsV2 instead
219
         */
220
        public function getItems(string $userId, ?string $since = null, int $limit = 7): array {
NEW
221
                $widgetItems = $this->getItemsV2($userId, $since, $limit);
×
NEW
222
                return $widgetItems->getItems();
×
223
        }
224

225
        /**
226
         * @inheritDoc
227
         */
228
        public function getWidgetButtons(string $userId): array {
NEW
229
                return [
×
NEW
230
                        new WidgetButton(
×
NEW
231
                                WidgetButton::TYPE_MORE,
×
NEW
232
                                $this->urlGenerator->linkToRouteAbsolute('libresign.page.index'),
×
NEW
233
                                $this->l10n->t('View all documents')
×
NEW
234
                        ),
×
NEW
235
                ];
×
236
        }
237
}
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