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

LibreSign / libresign / 19878831952

03 Dec 2025 01:08AM UTC coverage: 41.576%. First build
19878831952

Pull #4464

github

web-flow
Merge a843e05d5 into da0973853
Pull Request #4464: refactor: attach document

117 of 302 new or added lines in 16 files covered. (38.74%)

5123 of 12322 relevant lines covered (41.58%)

4.17 hits per line

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

45.41
/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\Helper\Pagination;
12
use OCP\AppFramework\Db\QBMapper;
13
use OCP\DB\QueryBuilder\IQueryBuilder;
14
use OCP\DB\Types;
15
use OCP\IDBConnection;
16
use OCP\IL10N;
17
use OCP\IURLGenerator;
18

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

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

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

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

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

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

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

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

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

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

115
                $data = [];
1✔
116
                $fileIds = [];
1✔
117

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

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

165
                if (!$count || !empty($filter['userId'])) {
1✔
166
                        if (!$count) {
1✔
167
                                $qb->selectAlias('u.uid_lower', 'account_uid')
1✔
168
                                        ->selectAlias('u.displayname', 'account_displayname')
1✔
169
                                        ->addGroupBy('u.uid_lower')
1✔
170
                                        ->addGroupBy('u.displayname');
1✔
171
                        }
172
                        $joinType = !empty($filter['userId']) ? 'join' : 'leftJoin';
1✔
173
                        $qb->$joinType('id', 'users', 'u', 'id.user_id = u.uid');
1✔
174
                }
175

176
                if (!empty($filter['userId'])) {
1✔
177
                        $qb->where(
×
NEW
178
                                $qb->expr()->eq('id.user_id', $qb->createNamedParameter($filter['userId'])),
×
179
                        );
×
180
                }
181
                if (!empty($filter['approved'])) {
1✔
182
                        if ($filter['approved'] === 'yes') {
×
183
                                $qb->andWhere(
×
184
                                        $qb->expr()->eq('f.status', $qb->createNamedParameter(File::STATUS_SIGNED, Types::INTEGER)),
×
185
                                );
×
186
                        }
187
                }
188
                return $qb;
1✔
189
        }
190

191
        private function getDocs(array $filter = []): Pagination {
192
                $qb = $this->getQueryBuilder(
1✔
193
                        filter: $filter,
1✔
194
                );
1✔
195
                $countQb = $this->getQueryBuilder(
1✔
196
                        filter: $filter,
1✔
197
                        count: true,
1✔
198
                );
1✔
199

200
                $pagination = new Pagination($qb, $this->urlGenerator, $countQb);
1✔
201
                return $pagination;
1✔
202
        }
203

204
        private function formatListRow(array $row, string $url): array {
NEW
205
                $row['nodeId'] = (int)$row['node_id'];
×
NEW
206
                $row['status'] = (int)$row['status'];
×
NEW
207
                $row['statusText'] = $this->getIdDocStatusText((int)$row['status']);
×
208
                $row['account'] = [
×
209
                        'uid' => $row['account_uid'],
×
210
                        'displayName' => $row['account_displayname']
×
211
                ];
×
212
                $row['file_type'] = [
×
213
                        'type' => $row['file_type'],
×
214
                        'name' => $this->fileTypeMapper->getNameOfType($row['file_type']),
×
215
                        'description' => $this->fileTypeMapper->getDescriptionOfType($row['file_type']),
×
NEW
216
                        'key' => $row['file_type'],
×
217
                ];
×
NEW
218
                $row['created_at'] = (new \DateTime())
×
NEW
219
                        ->setTimestamp((int)$row['created_at'])
×
NEW
220
                        ->format('Y-m-d H:i:s');
×
221
                $row['file'] = [
×
222
                        'name' => $row['name'],
×
223
                        'status' => $row['status'],
×
NEW
224
                        'statusText' => $this->getIdDocStatusText((int)$row['status']),
×
225
                        'created_at' => $row['created_at'],
×
226
                        'file' => [
×
227
                                'type' => 'pdf',
×
228
                                'nodeId' => (int)$row['node_id'],
×
229
                                'url' => $url . $row['uuid'],
×
230
                        ],
×
231
                        'callback' => $row['callback'],
×
232
                        'uuid' => $row['uuid'],
×
233
                ];
×
234
                unset(
×
235
                        $row['node_id'],
×
236
                        $row['name'],
×
237
                        $row['account_displayname'],
×
238
                        $row['account_uid'],
×
239
                        $row['callback'],
×
240
                        $row['uuid'],
×
241
                        $row['account_uid'],
×
242
                );
×
243
                return $row;
×
244
        }
245

246
        /**
247
         * @param array $files
248
         * @param SignRequest[] $signers
249
         */
250
        private function assocFileToSignRequestAndFormat(array $files, array $signers): array {
251
                foreach ($files as $key => $file) {
1✔
252
                        $totalSigned = 0;
×
253
                        $files[$key]['file']['signers'] = [];
×
254
                        foreach ($signers as $signerKey => $signer) {
×
255
                                if ($signer->getFileId() === $file['id']) {
×
256
                                        $data = [
×
257
                                                'description' => $signer->getDescription(),
×
258
                                                'displayName' => $signer->getDisplayName(),
×
NEW
259
                                                'request_sign_date' => (new \DateTime())
×
NEW
260
                                                        ->setTimestamp($signer->getCreatedAt()->getTimestamp())
×
NEW
261
                                                        ->format('Y-m-d H:i:s'),
×
NEW
262
                                                'sign_date' => null,
×
263
                                                'signRequestId' => $signer->getId(),
×
264
                                        ];
×
NEW
265
                                        if ($signer->getSigned()) {
×
NEW
266
                                                $data['sign_date'] = (new \DateTime())
×
NEW
267
                                                        ->setTimestamp($signer->getSigned()->getTimestamp())
×
NEW
268
                                                        ->format('Y-m-d H:i:s');
×
269
                                                $totalSigned++;
×
270
                                        }
271
                                        $files[$key]['file']['signers'][] = $data;
×
272
                                        unset($signers[$signerKey]);
×
273
                                }
274
                        }
275
                        unset($files[$key]['id']);
×
276
                }
277
                return $files;
1✔
278
        }
279

280
        private function getIdDocStatusText(int $status): string {
NEW
281
                return match ($status) {
×
NEW
282
                        File::STATUS_ABLE_TO_SIGN => $this->l10n->t('waiting for approval'),
×
NEW
283
                        File::STATUS_SIGNED => $this->l10n->t('approved'),
×
NEW
284
                        default => $this->fileMapper->getTextOfStatus($status) ?? '',
×
NEW
285
                };
×
286
        }
287
}
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