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

LibreSign / libresign / 20621591205

31 Dec 2025 03:04PM UTC coverage: 44.647%. First build
20621591205

Pull #6256

github

web-flow
Merge 67205cd47 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\UserStatus\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\Model\WidgetButton;
19
use OCP\Dashboard\Model\WidgetItem;
20
use OCP\Dashboard\Model\WidgetItems;
21
use OCP\IL10N;
22
use OCP\IURLGenerator;
23
use OCP\IUserSession;
24
use OCP\Util;
25

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

36
        /**
37
         * @inheritDoc
38
         */
39
        public function getId(): string {
NEW
40
                return 'libresign_pending_signatures';
×
41
        }
42

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

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

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

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

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

80
        /**
81
         * @inheritDoc
82
         */
83
        public function load(): void {
84
                //Util::addScript('libresign', 'libresign-dashboard');
NEW
85
        }
×
86

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

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

NEW
105
                        $items = [];
×
106

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

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

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

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

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

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

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

NEW
156
                return null;
×
157
        }
158

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

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

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

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

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

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

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

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

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

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

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

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