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

LibreSign / libresign / 20882165631

10 Jan 2026 05:56PM UTC coverage: 44.646%. First build
20882165631

Pull #6433

github

web-flow
Merge eead2e4b3 into ecd36974e
Pull Request #6433: refactor: move all constants to FileStatus enum

31 of 56 new or added lines in 16 files covered. (55.36%)

6742 of 15101 relevant lines covered (44.65%)

5.01 hits per line

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

44.0
/lib/Db/IdDocsMapper.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\Db;
10

11
use OCA\Libresign\Enum\FileStatus;
12
use OCA\Libresign\Helper\Pagination;
13
use OCP\AppFramework\Db\QBMapper;
14
use OCP\DB\QueryBuilder\IQueryBuilder;
15
use OCP\DB\Types;
16
use OCP\IDBConnection;
17
use OCP\IL10N;
18
use OCP\IURLGenerator;
19

20
/**
21
 * Class FileMapper
22
 *
23
 * @package OCA\Libresign\DB
24
 * @template-extends QBMapper<IdDocs>
25
 */
26
class IdDocsMapper extends QBMapper {
27
        public function __construct(
28
                IDBConnection $db,
29
                private IURLGenerator $urlGenerator,
30
                private FileMapper $fileMapper,
31
                private SignRequestMapper $signRequestMapper,
32
                private FileTypeMapper $fileTypeMapper,
33
                private IL10N $l10n,
34
        ) {
35
                parent::__construct($db, 'libresign_id_docs');
47✔
36
        }
37

38
        public function save(int $fileId, ?int $signRequestId, ?string $userId, string $fileType): IdDocs {
39
                $idDocs = new IdDocs();
1✔
40
                $idDocs->setFileId($fileId);
1✔
41
                $idDocs->setSignRequestId($signRequestId);
1✔
42
                $idDocs->setUserId($userId);
1✔
43
                $idDocs->setFileType($fileType);
1✔
44
                return $this->insert($idDocs);
1✔
45
        }
46

47
        public function getByUserIdAndFileId(string $userId, int $fileId): IdDocs {
48
                $qb = $this->db->getQueryBuilder();
×
49
                $qb->select('*')
×
50
                        ->from($this->getTableName())
×
51
                        ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
×
52
                        ->andWhere($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
×
53
                return $this->findEntity($qb);
×
54
        }
55

56
        /**
57
         * @return IdDocs[]
58
         */
59
        public function getByUserId(string $userId): array {
60
                $qb = $this->db->getQueryBuilder();
×
61
                $qb->select('*')
×
62
                        ->from($this->getTableName())
×
63
                        ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
×
64
                return $this->findEntities($qb);
×
65
        }
66

67
        public function getByUserIdAndNodeId(string $userId, int $nodeId): IdDocs {
68
                $qb = $this->db->getQueryBuilder();
×
69
                $qb->select('id.*')
×
70
                        ->from($this->getTableName(), 'id')
×
71
                        ->join('id', 'libresign_file', 'f', 'f.id = id.file_id')
×
72
                        ->where($qb->expr()->eq('id.user_id', $qb->createNamedParameter($userId)))
×
73
                        ->andWhere($qb->expr()->eq('f.node_id', $qb->createNamedParameter($nodeId, IQueryBuilder::PARAM_INT)));
×
74
                return $this->findEntity($qb);
×
75
        }
76

77
        public function getByFileId(int $fileId): IdDocs {
78
                $qb = $this->db->getQueryBuilder();
×
79
                $qb->select('*')
×
80
                        ->from($this->getTableName())
×
81
                        ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
×
82
                return $this->findEntity($qb);
×
83
        }
84

85
        public function deleteByFileId(int $fileId): void {
86
                $qb = $this->db->getQueryBuilder();
×
87
                $qb->delete($this->getTableName())
×
88
                        ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
×
89
                $qb->executeStatement();
×
90
        }
91

92
        public function getByUserAndType(string $userId, string $fileType): ?IdDocs {
93
                $qb = $this->db->getQueryBuilder();
1✔
94
                $qb->select('*')
1✔
95
                        ->from($this->getTableName())
1✔
96
                        ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
1✔
97
                        ->andWhere($qb->expr()->eq('file_type', $qb->createNamedParameter($fileType)));
1✔
98
                try {
99
                        return $this->findEntity($qb);
1✔
100
                } catch (\Throwable) {
1✔
101
                        return null;
1✔
102
                }
103
        }
104

105
        public function list(array $filter, ?int $page = null, ?int $length = null, array $sort = []): array {
106
                $filter['length'] = $length;
1✔
107
                $filter['page'] = $page;
1✔
108
                $filter['sort'] = $sort;
1✔
109
                $pagination = $this->getDocs($filter);
1✔
110
                $pagination->setMaxPerPage($length);
1✔
111
                $pagination->setCurrentPage($page);
1✔
112
                $currentPageResults = $pagination->getCurrentPageResults();
1✔
113

114
                $url = $this->urlGenerator->linkToRoute('libresign.page.getPdf', ['uuid' => '_replace_']);
1✔
115
                $url = str_replace('_replace_', '', $url);
1✔
116

117
                $data = [];
1✔
118
                $fileIds = [];
1✔
119

120
                foreach ($currentPageResults as $row) {
1✔
121
                        $fileIds[] = $row['id'];
×
122
                        $data[] = $this->formatListRow($row, $url);
×
123
                }
124
                $signers = $this->signRequestMapper->getByMultipleFileId($fileIds);
1✔
125
                $return['data'] = $this->assocFileToSignRequestAndFormat($data, $signers);
1✔
126
                $return['pagination'] = $pagination;
1✔
127
                return $return;
1✔
128
        }
129

130
        private function getQueryBuilder(array $filter = [], bool $count = false): IQueryBuilder {
131
                $qb = $this->db->getQueryBuilder();
1✔
132
                if ($count) {
1✔
133
                        $qb->select($qb->func()->count())
1✔
134
                                ->setFirstResult(0)
1✔
135
                                ->setMaxResults(null);
1✔
136
                } else {
137
                        $qb
1✔
138
                                ->select(
1✔
139
                                        'f.id',
1✔
140
                                        'f.uuid',
1✔
141
                                        'f.name',
1✔
142
                                        'f.callback',
1✔
143
                                        'f.status',
1✔
144
                                        'f.node_id',
1✔
145
                                        'id.file_type',
1✔
146
                                        'f.created_at',
1✔
147
                                )
1✔
148
                                ->groupBy(
1✔
149
                                        'f.id',
1✔
150
                                        'f.uuid',
1✔
151
                                        'f.name',
1✔
152
                                        'f.callback',
1✔
153
                                        'f.status',
1✔
154
                                        'f.node_id',
1✔
155
                                        'f.created_at',
1✔
156
                                        'id.file_type',
1✔
157
                                );
1✔
158
                        if (isset($filter['length']) && isset($filter['page'])) {
1✔
159
                                $qb->setFirstResult($filter['length'] * ($filter['page'] - 1));
1✔
160
                                $qb->setMaxResults($filter['length']);
1✔
161
                        }
162

163
                        if (!empty($filter['sort'])) {
1✔
164
                                $allowedSortFields = [
×
165
                                        'owner' => 'u.displayname',
×
166
                                        'file_type' => 'id.file_type',
×
167
                                        'status' => 'f.status',
×
168
                                        'created_at' => 'f.created_at',
×
169
                                ];
×
170

171
                                foreach ($filter['sort'] as $field => $direction) {
×
172
                                        if (!isset($allowedSortFields[$field])) {
×
173
                                                continue;
×
174
                                        }
175
                                        $direction = strtoupper($direction) === 'ASC' ? 'ASC' : 'DESC';
×
176
                                        $qb->addOrderBy($allowedSortFields[$field], $direction);
×
177
                                }
178
                        } else {
179
                                $qb->orderBy('f.created_at', 'DESC');
1✔
180
                        }
181
                }
182
                $qb
1✔
183
                        ->from($this->getTableName(), 'id')
1✔
184
                        ->join('id', 'libresign_file', 'f', 'f.id = id.file_id');
1✔
185

186
                $needsUserJoin = !$count || !empty($filter['userId']) || (!empty($filter['sort']) && isset($filter['sort']['owner']));
1✔
187

188
                if ($needsUserJoin) {
1✔
189
                        if (!$count) {
1✔
190
                                $qb->selectAlias('u.uid_lower', 'account_uid')
1✔
191
                                        ->selectAlias('u.displayname', 'account_displayname')
1✔
192
                                        ->addGroupBy('u.uid_lower')
1✔
193
                                        ->addGroupBy('u.displayname');
1✔
194
                        }
195
                        $joinType = !empty($filter['userId']) ? 'join' : 'leftJoin';
1✔
196
                        $qb->$joinType('id', 'users', 'u', 'id.user_id = u.uid');
1✔
197
                }
198

199
                if (!empty($filter['userId'])) {
1✔
200
                        $qb->where(
×
201
                                $qb->expr()->eq('id.user_id', $qb->createNamedParameter($filter['userId'])),
×
202
                        );
×
203
                }
204
                if (!empty($filter['approved'])) {
1✔
205
                        if ($filter['approved'] === 'yes') {
×
206
                                $qb->andWhere(
×
NEW
207
                                        $qb->expr()->eq('f.status', $qb->createNamedParameter(FileStatus::SIGNED->value, Types::INTEGER)),
×
208
                                );
×
209
                        }
210
                }
211
                return $qb;
1✔
212
        }
213

214
        private function getDocs(array $filter = []): Pagination {
215
                $qb = $this->getQueryBuilder(
1✔
216
                        filter: $filter,
1✔
217
                );
1✔
218
                $countQb = $this->getQueryBuilder(
1✔
219
                        filter: $filter,
1✔
220
                        count: true,
1✔
221
                );
1✔
222

223
                $pagination = new Pagination($qb, $this->urlGenerator, $countQb);
1✔
224
                return $pagination;
1✔
225
        }
226

227
        private function formatListRow(array $row, string $url): array {
228
                $row['nodeId'] = (int)$row['node_id'];
×
229
                $row['status'] = (int)$row['status'];
×
230
                $row['statusText'] = $this->getIdDocStatusText((int)$row['status']);
×
231
                $row['account'] = [
×
232
                        'uid' => $row['account_uid'],
×
233
                        'displayName' => $row['account_displayname']
×
234
                ];
×
235
                $row['file_type'] = [
×
236
                        'type' => $row['file_type'],
×
237
                        'name' => $this->fileTypeMapper->getNameOfType($row['file_type']),
×
238
                        'description' => $this->fileTypeMapper->getDescriptionOfType($row['file_type']),
×
239
                        'key' => $row['file_type'],
×
240
                ];
×
241
                $row['created_at'] = (new \DateTime())
×
242
                        ->setTimestamp((int)$row['created_at'])
×
243
                        ->format('Y-m-d H:i:s');
×
244
                $row['file'] = [
×
245
                        'name' => $row['name'],
×
246
                        'status' => $row['status'],
×
247
                        'statusText' => $this->getIdDocStatusText((int)$row['status']),
×
248
                        'created_at' => $row['created_at'],
×
249
                        'file' => [
×
250
                                'type' => 'pdf',
×
251
                                'nodeId' => (int)$row['node_id'],
×
252
                                'url' => $url . $row['uuid'],
×
253
                        ],
×
254
                        'callback' => $row['callback'],
×
255
                        'uuid' => $row['uuid'],
×
256
                ];
×
257
                unset(
×
258
                        $row['node_id'],
×
259
                        $row['name'],
×
260
                        $row['account_displayname'],
×
261
                        $row['account_uid'],
×
262
                        $row['callback'],
×
263
                        $row['uuid'],
×
264
                        $row['account_uid'],
×
265
                );
×
266
                return $row;
×
267
        }
268

269
        /**
270
         * @param array $files
271
         * @param SignRequest[] $signers
272
         */
273
        private function assocFileToSignRequestAndFormat(array $files, array $signers): array {
274
                foreach ($files as $key => $file) {
1✔
275
                        $totalSigned = 0;
×
276
                        $files[$key]['file']['signers'] = [];
×
277
                        foreach ($signers as $signerKey => $signer) {
×
278
                                if ($signer->getFileId() === $file['id']) {
×
279
                                        $data = [
×
280
                                                'description' => $signer->getDescription(),
×
281
                                                'displayName' => $signer->getDisplayName(),
×
282
                                                'request_sign_date' => (new \DateTime())
×
283
                                                        ->setTimestamp($signer->getCreatedAt()->getTimestamp())
×
284
                                                        ->format('Y-m-d H:i:s'),
×
285
                                                'sign_date' => null,
×
286
                                                'signRequestId' => $signer->getId(),
×
287
                                                'status' => $signer->getStatus(),
×
288
                                                'statusText' => $this->signRequestMapper->getTextOfSignerStatus($signer->getStatus()),
×
289
                                        ];
×
290
                                        if ($signer->getSigned()) {
×
291
                                                $data['sign_date'] = (new \DateTime())
×
292
                                                        ->setTimestamp($signer->getSigned()->getTimestamp())
×
293
                                                        ->format('Y-m-d H:i:s');
×
294
                                                $totalSigned++;
×
295
                                        }
296
                                        $files[$key]['file']['signers'][] = $data;
×
297
                                        unset($signers[$signerKey]);
×
298
                                }
299
                        }
300
                        unset($files[$key]['id']);
×
301
                }
302
                return $files;
1✔
303
        }
304

305
        private function getIdDocStatusText(int $status): string {
306
                return match ($status) {
NEW
307
                        FileStatus::ABLE_TO_SIGN->value => $this->l10n->t('waiting for approval'),
×
NEW
308
                        FileStatus::SIGNED->value => $this->l10n->t('approved'),
×
309
                        default => $this->fileMapper->getTextOfStatus($status),
×
310
                };
311
        }
312
}
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