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

LibreSign / libresign / 20469125400

23 Dec 2025 06:57PM UTC coverage: 43.466%. First build
20469125400

Pull #6243

github

web-flow
Merge d8263f711 into 4f1a71d46
Pull Request #6243: feat: unified search

4 of 87 new or added lines in 2 files covered. (4.6%)

5937 of 13659 relevant lines covered (43.47%)

5.12 hits per line

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

45.52
/lib/Db/SignRequestMapper.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 DateTimeInterface;
12
use OCA\Libresign\Enum\SignatureFlow;
13
use OCA\Libresign\Enum\SignRequestStatus;
14
use OCA\Libresign\Helper\Pagination;
15
use OCA\Libresign\Service\IdentifyMethod\IIdentifyMethod;
16
use OCA\Libresign\Service\IdentifyMethodService;
17
use OCP\AppFramework\Db\DoesNotExistException;
18
use OCP\AppFramework\Db\Entity;
19
use OCP\AppFramework\Db\QBMapper;
20
use OCP\DB\QueryBuilder\IQueryBuilder;
21
use OCP\IDateTimeFormatter;
22
use OCP\IDBConnection;
23
use OCP\IL10N;
24
use OCP\IURLGenerator;
25
use OCP\IUser;
26
use OCP\IUserManager;
27

28
/**
29
 * Class SignRequestMapper
30
 *
31
 * @package OCA\Libresign\DB
32
 * @template-extends QBMapper<SignRequest>
33
 */
34
class SignRequestMapper extends QBMapper {
35
        /**
36
         * @var SignRequest[]
37
         */
38
        private $signers = [];
39
        private bool $firstNotification = false;
40

41
        public function __construct(
42
                IDBConnection $db,
43
                protected IL10N $l10n,
44
                protected FileMapper $fileMapper,
45
                private IUserManager $userManager,
46
                private IDateTimeFormatter $dateTimeFormatter,
47
                private IURLGenerator $urlGenerator,
48
        ) {
49
                parent::__construct($db, 'libresign_sign_request');
47✔
50
        }
51

52
        /**
53
         * @return boolean true when is the first notification
54
         */
55
        public function incrementNotificationCounter(SignRequest $signRequest, string $method): bool {
56
                $this->db->beginTransaction();
13✔
57
                try {
58
                        $fromDatabase = $this->getById($signRequest->getId());
13✔
59
                        $metadata = $fromDatabase->getMetadata();
13✔
60
                        if (!isset($metadata['notify'])) {
13✔
61
                                $this->firstNotification = true;
13✔
62
                        }
63

64
                        $notificationEntry = [
13✔
65
                                'method' => $method,
13✔
66
                                'date' => time(),
13✔
67
                        ];
13✔
68

69
                        if (!empty($fromDatabase->getDescription())) {
13✔
70
                                $notificationEntry['description'] = $fromDatabase->getDescription();
×
71
                        }
72

73
                        $metadata['notify'][] = $notificationEntry;
13✔
74
                        $fromDatabase->setMetadata($metadata);
13✔
75
                        $this->update($fromDatabase);
13✔
76
                        $this->db->commit();
13✔
77
                } catch (\Throwable) {
×
78
                        $this->db->rollBack();
×
79
                }
80
                return $this->firstNotification;
13✔
81
        }
82

83
        /**
84
         * @inheritDoc
85
         */
86
        #[\Override]
87
        public function update(Entity $entity): SignRequest {
88
                /** @var SignRequest */
89
                $signRequest = parent::update($entity);
13✔
90
                $this->signers[$signRequest->getId()] = $signRequest;
13✔
91
                return $signRequest;
13✔
92
        }
93

94
        /**
95
         * Get sign request by UUID
96
         *
97
         * @throws DoesNotExistException
98
         */
99
        public function getByUuid(string $uuid): SignRequest {
100
                foreach ($this->signers as $signRequest) {
5✔
101
                        if ($signRequest->getUuid() === $uuid) {
5✔
102
                                return $signRequest;
4✔
103
                        }
104
                }
105
                $qb = $this->db->getQueryBuilder();
1✔
106

107
                $qb->select('*')
1✔
108
                        ->from($this->getTableName())
1✔
109
                        ->where(
1✔
110
                                $qb->expr()->eq('uuid', $qb->createNamedParameter($uuid))
1✔
111
                        );
1✔
112
                /** @var SignRequest */
113
                $signRequest = $this->findEntity($qb);
1✔
114
                if (!isset($this->signers[$signRequest->getId()])) {
×
115
                        $this->signers[$signRequest->getId()] = $signRequest;
×
116
                }
117
                return $signRequest;
×
118
        }
119

120
        public function getByEmailAndFileId(string $email, int $fileId): SignRequest {
121
                $qb = $this->db->getQueryBuilder();
×
122

123
                $qb->select('*')
×
124
                        ->from($this->getTableName())
×
125
                        ->where(
×
126
                                $qb->expr()->eq('email', $qb->createNamedParameter($email))
×
127
                        )
×
128
                        ->andWhere(
×
129
                                $qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))
×
130
                        );
×
131
                /** @var SignRequest */
132
                return $this->findEntity($qb);
×
133
        }
134

135
        public function getByIdentifyMethodAndFileId(IIdentifyMethod $identifyMethod, int $fileId): SignRequest {
136
                $qb = $this->db->getQueryBuilder();
13✔
137
                $qb->select('sr.*')
13✔
138
                        ->from($this->getTableName(), 'sr')
13✔
139
                        ->join('sr', 'libresign_identify_method', 'im', 'sr.id = im.sign_request_id')
13✔
140
                        ->where($qb->expr()->eq('im.identifier_key', $qb->createNamedParameter($identifyMethod->getEntity()->getIdentifierKey())))
13✔
141
                        ->andWhere($qb->expr()->eq('im.identifier_value', $qb->createNamedParameter($identifyMethod->getEntity()->getIdentifierValue())))
13✔
142
                        ->andWhere($qb->expr()->eq('sr.file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
13✔
143
                /** @var SignRequest */
144
                return $this->findEntity($qb);
13✔
145
        }
146

147
        /**
148
         * Get all signers by fileId
149
         *
150
         * @return SignRequest[]
151
         */
152
        public function getByFileId(int $fileId): array {
153
                $qb = $this->db->getQueryBuilder();
14✔
154

155
                $qb->select('*')
14✔
156
                        ->from($this->getTableName())
14✔
157
                        ->where(
14✔
158
                                $qb->expr()->eq('file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))
14✔
159
                        );
14✔
160
                /** @var SignRequest[] */
161
                $signers = $this->findEntities($qb);
14✔
162
                foreach ($signers as $signRequest) {
14✔
163
                        if (!isset($this->signers[$signRequest->getId()])) {
11✔
164
                                $this->signers[$signRequest->getId()] = $signRequest;
1✔
165
                        }
166
                }
167
                return $signers;
14✔
168
        }
169

170
        /**
171
         * @throws DoesNotExistException
172
         */
173
        public function getById(int $signRequestId): SignRequest {
174
                if (isset($this->signers[$signRequestId])) {
15✔
175
                        return $this->signers[$signRequestId];
14✔
176
                }
177
                $qb = $this->db->getQueryBuilder();
14✔
178

179
                $qb->select('*')
14✔
180
                        ->from($this->getTableName())
14✔
181
                        ->where(
14✔
182
                                $qb->expr()->eq('id', $qb->createNamedParameter($signRequestId, IQueryBuilder::PARAM_INT))
14✔
183
                        );
14✔
184

185
                /** @var SignRequest */
186
                $signRequest = $this->findEntity($qb);
14✔
187
                if (!isset($this->signers[$signRequest->getId()])) {
14✔
188
                        $this->signers[$signRequest->getId()] = $signRequest;
14✔
189
                }
190
                return $signRequest;
14✔
191
        }
192

193
        /**
194
         * @return \Generator<IdentifyMethod>
195
         */
196
        public function findRemindersCandidates(): \Generator {
197
                $qb = $this->db->getQueryBuilder();
×
198
                $qb->select(
×
199
                        'sr.id AS sr_id',
×
200
                        'sr.file_id AS sr_file_id',
×
201
                        'sr.uuid AS sr_uuid',
×
202
                        'sr.display_name AS sr_display_name',
×
203
                        'sr.description AS sr_description',
×
204
                        'sr.metadata AS sr_metadata',
×
205
                        'sr.signed_hash AS sr_signed_hash',
×
206
                        'sr.created_at AS sr_created_at',
×
207
                        'sr.signed AS sr_signed',
×
208

209
                        'im.id AS im_id',
×
210
                        'im.mandatory AS im_mandatory',
×
211
                        'im.code AS im_code',
×
212
                        'im.identifier_key AS im_identifier_key',
×
213
                        'im.identifier_value AS im_identifier_value',
×
214
                        'im.attempts AS im_attempts',
×
215
                        'im.identified_at_date AS im_identified_at_date',
×
216
                        'im.last_attempt_date AS im_last_attempt_date',
×
217
                        'im.sign_request_id AS im_sign_request_id',
×
218
                        'im.metadata AS im_metadata',
×
219
                )
×
220
                        ->from('libresign_sign_request', 'sr')
×
221
                        ->join('sr', 'libresign_identify_method', 'im', 'sr.id = im.sign_request_id')
×
222
                        ->join('sr', 'libresign_file', 'f', 'sr.file_id = f.id')
×
223
                        ->where($qb->expr()->isNull('sr.signed'))
×
224
                        ->andWhere($qb->expr()->neq('im.identifier_value', $qb->createNamedParameter('deleted_users')))
×
225
                        ->andWhere($qb->expr()->in('f.status', $qb->createNamedParameter([
×
226
                                File::STATUS_ABLE_TO_SIGN,
×
227
                                File::STATUS_PARTIAL_SIGNED
×
228
                        ], IQueryBuilder::PARAM_INT_ARRAY)))
×
229
                        ->setParameter('st', [1,2], IQueryBuilder::PARAM_INT_ARRAY)
×
230
                        ->orderBy('sr.id', 'ASC');
×
231

232
                $result = $qb->executeQuery();
×
233
                try {
234
                        /** @var array<string, mixed> $row */
235
                        while ($row = $result->fetch()) {
×
236
                                $signRequest = new SignRequest();
×
237
                                $identifyMethod = new IdentifyMethod();
×
238
                                foreach ($row as $key => $value) {
×
239
                                        $prop = $identifyMethod->columnToProperty(substr($key, 3));
×
240
                                        if (str_starts_with($key, 'sr_')) {
×
241
                                                $signRequest->{'set' . lcfirst($prop)}($value);
×
242
                                        } else {
243
                                                $identifyMethod->{'set' . lcfirst($prop)}($value);
×
244
                                        }
245
                                }
246
                                $signRequest->resetUpdatedFields();
×
247
                                $identifyMethod->resetUpdatedFields();
×
248
                                if (!isset($this->signers[$signRequest->getId()])) {
×
249
                                        $this->signers[$signRequest->getId()] = $signRequest;
×
250
                                }
251
                                yield $identifyMethod;
×
252
                        }
253
                } finally {
254
                        $result->closeCursor();
×
255
                }
256
        }
257

258
        /**
259
         * Get all signers by multiple fileId
260
         *
261
         * @return SignRequest[]
262
         */
263
        public function getByMultipleFileId(array $fileId) {
264
                $qb = $this->db->getQueryBuilder();
6✔
265

266
                $qb->select('*')
6✔
267
                        ->from($this->getTableName(), 'sr')
6✔
268
                        ->where(
6✔
269
                                $qb->expr()->in('sr.file_id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT_ARRAY))
6✔
270
                        )
6✔
271
                        ->orderBy('sr.id', 'ASC');
6✔
272

273
                /** @var SignRequest[] */
274
                return $this->findEntities($qb);
6✔
275
        }
276

277
        /**
278
         * Get all signers by fileId
279
         *
280
         * @return SignRequest[]
281
         */
282
        public function getByNodeId(int $nodeId) {
283
                $qb = $this->db->getQueryBuilder();
3✔
284

285
                $qb->select('sr.*')
3✔
286
                        ->from($this->getTableName(), 'sr')
3✔
287
                        ->join('sr', 'libresign_file', 'f', 'sr.file_id = f.id')
3✔
288
                        ->where(
3✔
289
                                $qb->expr()->eq('f.node_id', $qb->createNamedParameter($nodeId, IQueryBuilder::PARAM_INT))
3✔
290
                        );
3✔
291

292
                /** @var SignRequest[] */
293
                $signers = $this->findEntities($qb);
3✔
294
                return $signers;
3✔
295
        }
296

297
        /**
298
         * Get all signers by File Uuid
299
         *
300
         * @param string $nodeId
301
         * @return SignRequest[]
302
         */
303
        public function getByFileUuid(string $uuid) {
304
                $qb = $this->db->getQueryBuilder();
1✔
305

306
                $qb->select('sr.*')
1✔
307
                        ->from($this->getTableName(), 'sr')
1✔
308
                        ->join('sr', 'libresign_file', 'f', 'sr.file_id = f.id')
1✔
309
                        ->where(
1✔
310
                                $qb->expr()->eq('f.uuid', $qb->createNamedParameter($uuid))
1✔
311
                        );
1✔
312

313
                /** @var SignRequest[] */
314
                $signers = $this->findEntities($qb);
1✔
315
                foreach ($signers as $signRequest) {
1✔
316
                        if (!isset($this->signers[$signRequest->getId()])) {
1✔
317
                                $this->signers[$signRequest->getId()] = $signRequest;
×
318
                        }
319
                }
320
                return $signers;
1✔
321
        }
322

323
        public function getBySignerUuidAndUserId(string $uuid): SignRequest {
324
                $qb = $this->db->getQueryBuilder();
×
325

326
                $qb->select('sr.*')
×
327
                        ->from($this->getTableName(), 'sr')
×
328
                        ->where(
×
329
                                $qb->expr()->eq('sr.uuid', $qb->createNamedParameter($uuid))
×
330
                        );
×
331

332
                /** @var SignRequest */
333
                $signRequest = $this->findEntity($qb);
×
334
                if (!isset($this->signers[$signRequest->getId()])) {
×
335
                        $this->signers[$signRequest->getId()] = $signRequest;
×
336
                }
337
                return $signRequest;
×
338
        }
339

340
        public function getByFileIdAndUserId(int $file_id): SignRequest {
341
                $qb = $this->db->getQueryBuilder();
×
342

343
                $qb->select('sr.*')
×
344
                        ->from($this->getTableName(), 'sr')
×
345
                        ->join('sr', 'libresign_file', 'f', 'sr.file_id = f.id')
×
346
                        ->where(
×
347
                                $qb->expr()->eq('f.node_id', $qb->createNamedParameter($file_id, IQueryBuilder::PARAM_INT))
×
348
                        );
×
349

350
                /** @var SignRequest */
351
                return $this->findEntity($qb);
×
352
        }
353

354
        public function getByFileIdAndEmail(int $file_id, string $email): SignRequest {
355
                $qb = $this->db->getQueryBuilder();
×
356

357
                $qb->select('sr.*')
×
358
                        ->from($this->getTableName(), 'sr')
×
359
                        ->join('sr', 'libresign_file', 'f', 'sr.file_id = f.id')
×
360
                        ->where(
×
361
                                $qb->expr()->eq('f.node_id', $qb->createNamedParameter($file_id, IQueryBuilder::PARAM_INT))
×
362
                        )
×
363
                        ->andWhere(
×
364
                                $qb->expr()->eq('sr.email', $qb->createNamedParameter($email))
×
365
                        );
×
366

367
                /** @var SignRequest */
368
                return $this->findEntity($qb);
×
369
        }
370

371
        public function getByFileIdAndSignRequestId(int $fileId, int $signRequestId): SignRequest {
372
                if (isset($this->signers[$signRequestId])) {
2✔
373
                        return $this->signers[$signRequestId];
2✔
374
                }
375
                $qb = $this->db->getQueryBuilder();
×
376

377
                $qb->select('sr.*')
×
378
                        ->from($this->getTableName(), 'sr')
×
379
                        ->join('sr', 'libresign_file', 'f', 'sr.file_id = f.id')
×
380
                        ->where(
×
381
                                $qb->expr()->eq('f.node_id', $qb->createNamedParameter($fileId))
×
382
                        )
×
383
                        ->andWhere(
×
384
                                $qb->expr()->eq('sr.id', $qb->createNamedParameter($signRequestId))
×
385
                        );
×
386

387
                $signRequest = $this->findEntity($qb);
×
388
                if (!isset($this->signers[$signRequest->getId()])) {
×
389
                        $this->signers[$signRequest->getId()] = $signRequest;
×
390
                }
391
                /** @var SignRequest */
392
                return end($this->signers);
×
393
        }
394

395
        public function getFilesAssociatedFilesWithMeFormatted(
396
                IUser $user,
397
                array $filter,
398
                ?int $page = null,
399
                ?int $length = null,
400
                ?array $sort = [],
401
        ): array {
402
                $filter['email'] = $user->getEMailAddress();
1✔
403
                $filter['length'] = $length;
1✔
404
                $filter['page'] = $page;
1✔
405
                $pagination = $this->getFilesAssociatedFilesWithMeStmt($user->getUID(), $filter, $sort);
1✔
406
                $pagination->setMaxPerPage($length);
1✔
407
                $pagination->setCurrentPage($page);
1✔
408
                $currentPageResults = $pagination->getCurrentPageResults();
1✔
409

410
                $data = [];
1✔
411
                foreach ($currentPageResults as $row) {
1✔
412
                        $data[] = $this->formatListRow($row);
×
413
                }
414
                $return['data'] = $data;
1✔
415
                $return['pagination'] = $pagination;
1✔
416
                return $return;
1✔
417
        }
418

419
        public function getFilesToSearchProvider(IUser $user, string $fileName, int $limit, int $offset): array {
NEW
420
                $filter = [
×
NEW
421
                        'page' => ($offset / $limit) + 1,
×
NEW
422
                        'length' => $limit,
×
NEW
423
                        'fileName' => $fileName,
×
NEW
424
                ];
×
425

NEW
426
                $sort = [
×
NEW
427
                        'sortBy' => 'created_at',
×
NEW
428
                        'sortDirection' => 'desc',
×
NEW
429
                ];
×
430

NEW
431
                $qb = $this->getFilesAssociatedFilesWithMeQueryBuilder($user->getUID(), $filter, false, $sort);
×
432

433

NEW
434
                $qb->orderBy('f.created_at', 'DESC');
×
435

NEW
436
                $result = $qb->executeQuery();
×
NEW
437
                $files = [];
×
438

NEW
439
                while ($row = $result->fetch()) {
×
440
                        try {
NEW
441
                                $file = File::fromRow($row);
×
442

NEW
443
                                $files[] = $file;
×
NEW
444
                        } catch (\Exception $e) {
×
NEW
445
                                continue;
×
446
                        }
447
                }
448

NEW
449
                $result->closeCursor();
×
450

NEW
451
                return $files;
×
452
        }
453

454
        /**
455
         * @param array<SignRequest> $signRequests
456
         * @return FileElement[][]
457
         */
458
        public function getVisibleElementsFromSigners(array $signRequests): array {
459
                $signRequestIds = array_map(fn (SignRequest $signRequest): int => $signRequest->getId(), $signRequests);
5✔
460
                if (!$signRequestIds) {
5✔
461
                        return [];
1✔
462
                }
463
                $qb = $this->db->getQueryBuilder();
4✔
464
                $qb->select('fe.*')
4✔
465
                        ->from('libresign_file_element', 'fe')
4✔
466
                        ->where(
4✔
467
                                $qb->expr()->in('fe.sign_request_id', $qb->createParameter('signRequestIds'))
4✔
468
                        );
4✔
469
                $return = [];
4✔
470
                foreach (array_chunk($signRequestIds, 1000) as $signRequestIdsChunk) {
4✔
471
                        $qb->setParameter('signRequestIds', $signRequestIdsChunk, IQueryBuilder::PARAM_INT_ARRAY);
4✔
472
                        $cursor = $qb->executeQuery();
4✔
473
                        while ($row = $cursor->fetch()) {
4✔
474
                                $fileElement = new FileElement();
×
475
                                $return[$row['sign_request_id']][] = $fileElement->fromRow($row);
×
476
                        }
477
                }
478
                return $return;
4✔
479
        }
480

481
        /**
482
         * @param array<SignRequest> $signRequests
483
         * @return array<array-key, array<array-key, \OCP\AppFramework\Db\Entity&\OCA\Libresign\Db\IdentifyMethod>>
484
         */
485
        public function getIdentifyMethodsFromSigners(array $signRequests): array {
486
                $signRequestIds = array_map(fn (SignRequest $signRequest): int => $signRequest->getId(), $signRequests);
1✔
487
                if (!$signRequestIds) {
1✔
488
                        return [];
1✔
489
                }
490
                $qb = $this->db->getQueryBuilder();
×
491
                $qb->select('im.*')
×
492
                        ->from('libresign_identify_method', 'im')
×
493
                        ->where(
×
494
                                $qb->expr()->in('im.sign_request_id', $qb->createParameter('signRequestIds'))
×
495
                        )
×
496
                        ->orderBy('im.mandatory', 'DESC')
×
497
                        ->addOrderBy('im.identified_at_date', 'ASC');
×
498

499
                $return = [];
×
500
                foreach (array_chunk($signRequestIds, 1000) as $signRequestIdsChunk) {
×
501
                        $qb->setParameter('signRequestIds', $signRequestIdsChunk, IQueryBuilder::PARAM_INT_ARRAY);
×
502
                        $cursor = $qb->executeQuery();
×
503
                        while ($row = $cursor->fetch()) {
×
504
                                $identifyMethod = new IdentifyMethod();
×
505
                                $return[$row['sign_request_id']][$row['identifier_key']] = $identifyMethod->fromRow($row);
×
506
                        }
507
                }
508
                return $return;
×
509
        }
510

511
        public function getMyLibresignFile(string $userId, ?array $filter = []): File {
512
                $qb = $this->getFilesAssociatedFilesWithMeQueryBuilder(
×
513
                        userId: $userId,
×
514
                        filter: $filter,
×
515
                );
×
516
                $cursor = $qb->executeQuery();
×
517
                $row = $cursor->fetch();
×
518
                if (!$row) {
×
519
                        throw new DoesNotExistException('LibreSign file not found');
×
520
                }
521
                $file = new File();
×
522
                return $file->fromRow($row);
×
523
        }
524

525
        private function getFilesAssociatedFilesWithMeQueryBuilder(string $userId, array $filter = [], bool $count = false, array $sort = []): IQueryBuilder {
526
                $qb = $this->db->getQueryBuilder();
1✔
527
                $qb->from('libresign_file', 'f')
1✔
528
                        ->leftJoin('f', 'libresign_sign_request', 'sr', 'sr.file_id = f.id')
1✔
529
                        ->leftJoin('f', 'libresign_identify_method', 'im', $qb->expr()->eq('sr.id', 'im.sign_request_id'))
1✔
530
                        ->leftJoin('f', 'libresign_id_docs', 'id', 'id.file_id = f.id');
1✔
531
                if ($count) {
1✔
532
                        $qb->select($qb->func()->count())
1✔
533
                                ->setFirstResult(0)
1✔
534
                                ->setMaxResults(null);
1✔
535
                } else {
536
                        $qb->select(
1✔
537
                                'f.id',
1✔
538
                                'f.node_id',
1✔
539
                                'f.signed_node_id',
1✔
540
                                'f.user_id',
1✔
541
                                'f.uuid',
1✔
542
                                'f.name',
1✔
543
                                'f.status',
1✔
544
                                'f.metadata',
1✔
545
                                'f.created_at',
1✔
546
                                'f.signature_flow',
1✔
547
                                'f.docmdp_level',
1✔
548
                        )
1✔
549
                                ->groupBy(
1✔
550
                                        'f.id',
1✔
551
                                        'f.node_id',
1✔
552
                                        'f.signed_node_id',
1✔
553
                                        'f.user_id',
1✔
554
                                        'f.uuid',
1✔
555
                                        'f.name',
1✔
556
                                        'f.status',
1✔
557
                                        'f.created_at',
1✔
558
                                        'f.signature_flow',
1✔
559
                                        'f.docmdp_level',
1✔
560
                                );
1✔
561
                        // metadata is a json column, the right way is to use f.metadata::text
562
                        // when the database is PostgreSQL. The problem is that the command
563
                        // addGroupBy add quotes over all text send as argument. With
564
                        // PostgreSQL json columns don't have problem if not added to group by.
565
                        if ($qb->getConnection()->getDatabaseProvider() !== IDBConnection::PLATFORM_POSTGRES) {
1✔
566
                                $qb->addGroupBy('f.metadata');
1✔
567
                        }
568
                        if (isset($filter['length']) && isset($filter['page'])) {
1✔
569
                                $qb->setFirstResult($filter['length'] * ($filter['page'] - 1));
1✔
570
                                $qb->setMaxResults($filter['length']);
1✔
571
                        }
572
                }
573

574
                $or = [
1✔
575
                        $qb->expr()->eq('f.user_id', $qb->createNamedParameter($userId)),
1✔
576
                        $qb->expr()->andX(
1✔
577
                                $qb->expr()->eq('im.identifier_key', $qb->createNamedParameter(IdentifyMethodService::IDENTIFY_ACCOUNT)),
1✔
578
                                $qb->expr()->eq('im.identifier_value', $qb->createNamedParameter($userId)),
1✔
579
                                $qb->expr()->neq('f.status', $qb->createNamedParameter(File::STATUS_DRAFT)),
1✔
580
                                $qb->expr()->neq('sr.status', $qb->createNamedParameter(SignRequestStatus::DRAFT->value)),
1✔
581
                        )
1✔
582
                ];
1✔
583
                $qb->where($qb->expr()->orX(...$or))->andWhere($qb->expr()->isNull('id.id'));
1✔
584
                if ($filter) {
1✔
585
                        if (isset($filter['email']) && filter_var($filter['email'], FILTER_VALIDATE_EMAIL)) {
1✔
586
                                $or[] = $qb->expr()->andX(
×
587
                                        $qb->expr()->eq('im.identifier_key', $qb->createNamedParameter(IdentifyMethodService::IDENTIFY_EMAIL)),
×
588
                                        $qb->expr()->eq('im.identifier_value', $qb->createNamedParameter($filter['email']))
×
589
                                );
×
590
                        }
591
                        if (!empty($filter['signer_uuid'])) {
1✔
592
                                $qb->andWhere(
×
593
                                        $qb->expr()->eq('sr.uuid', $qb->createNamedParameter($filter['signer_uuid']))
×
594
                                );
×
595
                        }
596
                        if (!empty($filter['nodeIds'])) {
1✔
597
                                $qb->andWhere(
×
598
                                        $qb->expr()->in('f.node_id', $qb->createNamedParameter($filter['nodeIds'], IQueryBuilder::PARAM_STR_ARRAY))
×
599
                                );
×
600
                        }
601
                        if (!empty($filter['status'])) {
1✔
602
                                $qb->andWhere(
×
603
                                        $qb->expr()->in('f.status', $qb->createNamedParameter($filter['status'], IQueryBuilder::PARAM_INT_ARRAY))
×
604
                                );
×
605
                        }
606
                        if (!empty($filter['start'])) {
1✔
607
                                $start = (new \DateTime('@' . $filter['start'], new \DateTimeZone('UTC')))->format('Y-m-d H:i:s');
×
608
                                $qb->andWhere(
×
609
                                        $qb->expr()->gte('f.created_at', $qb->createNamedParameter($start, IQueryBuilder::PARAM_STR))
×
610
                                );
×
611
                        }
612
                        if (!empty($filter['end'])) {
1✔
613
                                $end = (new \DateTime('@' . $filter['end'], new \DateTimeZone('UTC')))->format('Y-m-d H:i:s');
×
614
                                $qb->andWhere(
×
615
                                        $qb->expr()->lte('f.created_at', $qb->createNamedParameter($end, IQueryBuilder::PARAM_STR))
×
616
                                );
×
617
                        }
618
                        if (!empty($filter['fileName'])) {
1✔
NEW
619
                                $qb->andWhere(
×
NEW
620
                                        $qb->expr()->like('f.name', $qb->createNamedParameter('%' . $this->db->escapeLikeParameter($filter['fileName']) . '%'))
×
NEW
621
                                );
×
622
                        }
623
                }
624

625
                if (!empty($sort['sortBy']) && !empty($sort['sortDirection'])) {
1✔
626
                        switch ($sort['sortBy']) {
×
627
                                case 'name':
×
628
                                case 'status':
×
629
                                        $qb->orderBy(
×
630
                                                $qb->func()->lower('f.' . $sort['sortBy']),
×
631
                                                $sort['sortDirection'] == 'asc' ? 'asc' : 'desc'
×
632
                                        );
×
633
                                        break;
×
634
                                case 'created_at':
×
635
                                        $qb->orderBy(
×
636
                                                'f.' . $sort['sortBy'],
×
637
                                                $sort['sortDirection'] == 'asc' ? 'asc' : 'desc'
×
638
                                        );
×
639
                        }
640
                }
641

642
                return $qb;
1✔
643
        }
644

645
        private function getFilesAssociatedFilesWithMeStmt(
646
                string $userId,
647
                ?array $filter = [],
648
                ?array $sort = [],
649
        ): Pagination {
650
                $qb = $this->getFilesAssociatedFilesWithMeQueryBuilder($userId, $filter, false, $sort);
1✔
651

652
                $countQb = $this->getFilesAssociatedFilesWithMeQueryBuilder(
1✔
653
                        userId: $userId,
1✔
654
                        filter: $filter,
1✔
655
                        count: true,
1✔
656
                );
1✔
657

658
                $pagination = new Pagination($qb, $this->urlGenerator, $countQb);
1✔
659
                return $pagination;
1✔
660
        }
661

662
        private function formatListRow(array $row): array {
663
                $row['id'] = (int)$row['id'];
×
664
                $row['status'] = (int)$row['status'];
×
665
                $row['statusText'] = $this->fileMapper->getTextOfStatus($row['status']);
×
666
                $row['nodeId'] = (int)$row['node_id'];
×
667
                $row['signedNodeId'] = (int)$row['signed_node_id'];
×
668
                $row['requested_by'] = [
×
669
                        'userId' => $row['user_id'],
×
670
                        'displayName' => $this->userManager->get($row['user_id'])?->getDisplayName(),
×
671
                ];
×
672
                $row['created_at'] = (new \DateTime($row['created_at']))->setTimezone(new \DateTimeZone('UTC'))->format(DateTimeInterface::ATOM);
×
673
                $row['file'] = $this->urlGenerator->linkToRoute('libresign.page.getPdf', ['uuid' => $row['uuid']]);
×
674
                $row['nodeId'] = (int)$row['node_id'];
×
675

676
                $row['name'] = $this->removeExtensionFromName($row['name'], $row['metadata']);
×
677
                $row['signatureFlow'] = SignatureFlow::fromNumeric((int)($row['signature_flow']))->value;
×
678
                $row['docmdpLevel'] = (int)($row['docmdp_level'] ?? 0);
×
679

680
                unset(
×
681
                        $row['user_id'],
×
682
                        $row['node_id'],
×
683
                        $row['signed_node_id'],
×
684
                        $row['signature_flow'],
×
685
                        $row['docmdp_level'],
×
686
                );
×
687
                return $row;
×
688
        }
689

690
        private function removeExtensionFromName(string $name, ?string $metadataJson): string {
691
                if (empty($name) || empty($metadataJson)) {
×
692
                        return $name;
×
693
                }
694

695
                $metadata = json_decode($metadataJson, true);
×
696
                if (!isset($metadata['extension'])) {
×
697
                        return $name;
×
698
                }
699

700
                $extensionPattern = '/\.' . preg_quote($metadata['extension'], '/') . '$/i';
×
701
                $result = preg_replace($extensionPattern, '', $name);
×
702
                return $result ?? $name;
×
703
        }
704

705
        public function getTextOfSignerStatus(int $status): string {
706
                return SignRequestStatus::from($status)->getLabel($this->l10n);
5✔
707
        }
708
}
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

© 2025 Coveralls, Inc