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

LibreSign / libresign / 21293358735

23 Jan 2026 04:30PM UTC coverage: 45.267%. First build
21293358735

Pull #6548

github

web-flow
Merge 34dc69686 into 3b6e6d7e8
Pull Request #6548: fix: reduce N+1

33 of 68 new or added lines in 6 files covered. (48.53%)

7446 of 16449 relevant lines covered (45.27%)

4.93 hits per line

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

46.53
/lib/Service/FileService.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\Service;
10

11
use DateTimeInterface;
12
use InvalidArgumentException;
13
use OCA\Libresign\Db\File;
14
use OCA\Libresign\Db\FileElementMapper;
15
use OCA\Libresign\Db\FileMapper;
16
use OCA\Libresign\Db\IdDocsMapper;
17
use OCA\Libresign\Db\SignRequest;
18
use OCA\Libresign\Db\SignRequestMapper;
19
use OCA\Libresign\Enum\FileStatus;
20
use OCA\Libresign\Exception\LibresignException;
21
use OCA\Libresign\Handler\DocMdpHandler;
22
use OCA\Libresign\Handler\SignEngine\Pkcs12Handler;
23
use OCA\Libresign\Helper\FileUploadHelper;
24
use OCA\Libresign\ResponseDefinitions;
25
use OCA\Libresign\Service\Envelope\EnvelopeService;
26
use OCA\Libresign\Service\File\CertificateChainService;
27
use OCA\Libresign\Service\File\EnvelopeAssembler;
28
use OCA\Libresign\Service\File\EnvelopeProgressService;
29
use OCA\Libresign\Service\File\FileContentProvider;
30
use OCA\Libresign\Service\File\FileResponseOptions;
31
use OCA\Libresign\Service\File\MessagesLoader;
32
use OCA\Libresign\Service\File\MetadataLoader;
33
use OCA\Libresign\Service\File\MimeService;
34
use OCA\Libresign\Service\File\Pdf\PdfValidator;
35
use OCA\Libresign\Service\File\SettingsLoader;
36
use OCA\Libresign\Service\File\SignersLoader;
37
use OCA\Libresign\Service\File\UploadProcessor;
38
use OCP\AppFramework\Db\DoesNotExistException;
39
use OCP\Files\IMimeTypeDetector;
40
use OCP\Files\IRootFolder;
41
use OCP\Files\Node;
42
use OCP\Files\NotFoundException;
43
use OCP\IL10N;
44
use OCP\IURLGenerator;
45
use OCP\IUser;
46
use OCP\IUserManager;
47
use Psr\Log\LoggerInterface;
48
use stdClass;
49

50
/**
51
 * @psalm-import-type LibresignEnvelopeChildFile from ResponseDefinitions
52
 * @psalm-import-type LibresignValidateFile from ResponseDefinitions
53
 * @psalm-import-type LibresignVisibleElement from ResponseDefinitions
54
 */
55
class FileService {
56

57
        private string $fileContent = '';
58
        private ?File $file = null;
59
        private ?SignRequest $signRequest = null;
60
        private array $certData = [];
61
        private stdClass $fileData;
62
        private FileResponseOptions $options;
63
        public const IDENTIFICATION_DOCUMENTS_DISABLED = 0;
64
        public const IDENTIFICATION_DOCUMENTS_NEED_SEND = 1;
65
        public const IDENTIFICATION_DOCUMENTS_NEED_APPROVAL = 2;
66
        public const IDENTIFICATION_DOCUMENTS_APPROVED = 3;
67
        public function __construct(
68
                protected FileMapper $fileMapper,
69
                protected SignRequestMapper $signRequestMapper,
70
                protected FileElementMapper $fileElementMapper,
71
                protected FileElementService $fileElementService,
72
                protected FolderService $folderService,
73
                private IdDocsMapper $idDocsMapper,
74
                private IdentifyMethodService $identifyMethodService,
75
                private IUserManager $userManager,
76
                private IURLGenerator $urlGenerator,
77
                protected IMimeTypeDetector $mimeTypeDetector,
78
                protected Pkcs12Handler $pkcs12Handler,
79
                protected DocMdpHandler $docMdpHandler,
80
                protected PdfValidator $pdfValidator,
81
                private IRootFolder $root,
82
                protected LoggerInterface $logger,
83
                protected IL10N $l10n,
84
                private EnvelopeService $envelopeService,
85
                private SignersLoader $signersLoader,
86
                protected FileUploadHelper $uploadHelper,
87
                private EnvelopeAssembler $envelopeAssembler,
88
                private EnvelopeProgressService $envelopeProgressService,
89
                private CertificateChainService $certificateChainService,
90
                private MimeService $mimeService,
91
                private FileContentProvider $contentProvider,
92
                private UploadProcessor $uploadProcessor,
93
                private MetadataLoader $metadataLoader,
94
                private SettingsLoader $settingsLoader,
95
                private MessagesLoader $messagesLoader,
96
        ) {
97
                $this->fileData = new stdClass();
40✔
98
                $this->options = new FileResponseOptions();
40✔
99
        }
100

101
        public function getNodeFromData(array $data): Node {
102
                if (!$this->folderService->getUserId()) {
18✔
103
                        $this->folderService->setUserId($data['userManager']->getUID());
12✔
104
                }
105

106
                if (isset($data['uploadedFile'])) {
18✔
107
                        return $this->uploadProcessor->getNodeFromUploadedFile($data);
×
108
                }
109

110
                if (isset($data['file']['fileNode']) && $data['file']['fileNode'] instanceof Node) {
18✔
111
                        return $data['file']['fileNode'];
×
112
                }
113
                if (isset($data['file']['fileId'])) {
18✔
114
                        return $this->folderService->getFileByNodeId($data['file']['fileId']);
2✔
115
                }
116
                if (isset($data['file']['path'])) {
16✔
117
                        return $this->folderService->getFileByPath($data['file']['path']);
×
118
                }
119
                if (isset($data['file']['nodeId'])) {
16✔
120
                        return $this->folderService->getFileByNodeId($data['file']['nodeId']);
1✔
121
                }
122

123
                $content = $this->getFileRaw($data);
15✔
124
                $extension = $this->getExtension($content);
15✔
125

126
                $fileName = $data['name'];
15✔
127
                $this->validateFileContent($content, $fileName, $extension);
15✔
128

129
                $folderToFile = $this->folderService->getFolderForFile($data, $data['userManager']);
15✔
130
                $filename = $this->resolveFileName($data, $extension);
15✔
131
                return $folderToFile->newFile($filename, $content);
15✔
132
        }
133

134
        public function validateFileContent(string $content, string $fileName, string $extension): void {
135
                if ($extension === 'pdf') {
16✔
136
                        $this->pdfValidator->validate($content, $fileName);
15✔
137
                }
138
        }
139

140
        private function getExtension(string $content): string {
141
                return $this->mimeService->getExtension($content);
15✔
142
        }
143

144
        private function getFileRaw(array $data): string {
145
                return $this->contentProvider->getContentFromData($data);
15✔
146
        }
147

148
        private function resolveFileName(array $data, string $extension): string {
149
                $name = '';
15✔
150
                if (isset($data['name'])) {
15✔
151
                        $name = trim((string)$data['name']);
15✔
152
                }
153

154
                if ($name === '') {
15✔
155
                        $basename = '';
×
156
                        if (!empty($data['file']['url'])) {
×
157
                                $path = (string)parse_url((string)$data['file']['url'], PHP_URL_PATH);
×
158
                                if ($path !== '') {
×
159
                                        $basename = basename($path);
×
160
                                }
161
                        }
162
                        if ($basename !== '') {
×
163
                                $filenameNoExt = pathinfo($basename, PATHINFO_FILENAME);
×
164
                                $name = $filenameNoExt !== '' ? $filenameNoExt : $basename;
×
165
                        } else {
166
                                $name = 'document';
×
167
                        }
168
                }
169

170
                $name = preg_replace('/\s+/', '_', $name);
15✔
171
                $name = $name !== '' ? $name : 'document';
15✔
172
                return $name . '.' . $extension;
15✔
173
        }
174

175
        /**
176
         * @return static
177
         */
178
        public function showSigners(bool $show = true): self {
179
                $this->options->showSigners($show);
2✔
180
                return $this;
2✔
181
        }
182

183
        /**
184
         * @return static
185
         */
186
        public function showSettings(bool $show = true): self {
187
                $this->options->showSettings($show);
2✔
188
                if ($show) {
2✔
189
                        $this->fileData->settings = [
2✔
190
                                'canSign' => false,
2✔
191
                                'canRequestSign' => false,
2✔
192
                                'signerFileUuid' => null,
2✔
193
                                'phoneNumber' => '',
2✔
194
                        ];
2✔
195
                } else {
196
                        unset($this->fileData->settings);
×
197
                }
198
                return $this;
2✔
199
        }
200

201
        /**
202
         * @return static
203
         */
204
        public function showVisibleElements(bool $show = true): self {
205
                $this->options->showVisibleElements($show);
2✔
206
                return $this;
2✔
207
        }
208

209
        /**
210
         * @return static
211
         */
212
        public function showMessages(bool $show = true): self {
213
                $this->options->showMessages($show);
2✔
214
                return $this;
2✔
215
        }
216

217
        /**
218
         * @return static
219
         */
220
        public function setMe(?IUser $user): self {
221
                $this->options->setMe($user);
2✔
222
                return $this;
2✔
223
        }
224

225
        public function setSignerIdentified(bool $identified = true): self {
226
                $this->options->setSignerIdentified($identified);
×
227
                return $this;
×
228
        }
229

230
        public function setIdentifyMethodId(?int $id): self {
231
                $this->options->setIdentifyMethodId($id);
2✔
232
                return $this;
2✔
233
        }
234

235
        public function setHost(string $host): self {
236
                $this->options->setHost($host);
2✔
237
                return $this;
2✔
238
        }
239

240
        /**
241
         * @return static
242
         */
243
        public function setFile(File $file): self {
244
                $this->file = $file;
3✔
245
                $this->fileData->status = $this->file->getStatus();
3✔
246
                return $this;
3✔
247
        }
248

249
        public function setSignRequest(SignRequest $signRequest): self {
250
                $this->signRequest = $signRequest;
×
251
                return $this;
×
252
        }
253

254
        public function showValidateFile(bool $validateFile = true): self {
255
                $this->options->validateFile($validateFile);
2✔
256
                return $this;
2✔
257
        }
258

259
        private function setFileOrFail(callable $resolver): self {
260
                try {
261
                        $file = $resolver();
6✔
262
                } catch (\Throwable) {
3✔
263
                        throw new LibresignException($this->l10n->t('Invalid data to validate file'), 404);
3✔
264
                }
265

266
                if (!$file instanceof File) {
3✔
267
                        throw new LibresignException($this->l10n->t('Invalid file identifier'), 404);
×
268
                }
269

270
                return $this->setFile($file);
3✔
271
        }
272

273
        public function setFileById(int $fileId): self {
274
                return $this->setFileOrFail(fn () => $this->fileMapper->getById($fileId));
3✔
275
        }
276

277
        public function setFileByUuid(string $uuid): self {
278
                return $this->setFileOrFail(fn () => $this->fileMapper->getByUuid($uuid));
3✔
279
        }
280

281
        public function setFileBySignerUuid(string $uuid): self {
282
                return $this->setFileOrFail(fn () => $this->fileMapper->getBySignerUuid($uuid));
1✔
283
        }
284

285
        public function setFileByNodeId(int $nodeId): self {
286
                return $this->setFileOrFail(fn () => $this->fileMapper->getByNodeId($nodeId));
×
287
        }
288

289
        public function validateUploadedFile(array $file): void {
290
                $this->uploadHelper->validateUploadedFile($file);
×
291
        }
292

293
        public function setFileFromRequest(?array $file): self {
294
                if ($file === null) {
×
295
                        throw new InvalidArgumentException($this->l10n->t('No file provided'));
×
296
                }
297
                $this->uploadHelper->validateUploadedFile($file);
×
298

299
                $this->fileContent = file_get_contents($file['tmp_name']);
×
300
                $mimeType = $this->mimeService->getMimeType($this->fileContent);
×
301
                if ($mimeType !== 'application/pdf') {
×
302
                        $this->fileContent = '';
×
303
                        unlink($file['tmp_name']);
×
304
                        throw new InvalidArgumentException($this->l10n->t('Invalid file provided'));
×
305
                }
306
                $this->fileData->size = $file['size'];
×
307

308
                $memoryFile = fopen($file['tmp_name'], 'rb');
×
309
                try {
310
                        $this->certData = $this->pkcs12Handler->getCertificateChain($memoryFile);
×
311
                        $this->fileData->status = FileStatus::SIGNED->value;
×
312
                } catch (LibresignException) {
×
313
                        $this->fileData->status = FileStatus::DRAFT->value;
×
314
                }
315
                fclose($memoryFile);
×
316
                unlink($file['tmp_name']);
×
317
                $this->fileData->hash = hash('sha256', $this->fileContent);
×
318
                try {
319
                        $libresignFile = $this->fileMapper->getBySignedHash($this->fileData->hash);
×
320
                        $this->setFile($libresignFile);
×
321
                } catch (DoesNotExistException) {
×
322
                        $this->fileData->status = FileStatus::NOT_LIBRESIGN_FILE->value;
×
323
                }
324
                $this->fileData->name = $file['name'];
×
325
                return $this;
×
326
        }
327

328
        private function getFile(): \OCP\Files\File {
329
                $nodeId = $this->file->getSignedNodeId();
×
330
                if (!$nodeId) {
×
331
                        $nodeId = $this->file->getNodeId();
×
332
                }
333
                $fileToValidate = $this->root->getUserFolder($this->file->getUserId())->getFirstNodeById($nodeId);
×
334
                if (!$fileToValidate instanceof \OCP\Files\File) {
×
335
                        throw new LibresignException($this->l10n->t('File not found'), 404);
×
336
                }
337
                return $fileToValidate;
×
338
        }
339

340
        public function getStatus(): int {
341
                return $this->file->getStatus();
1✔
342
        }
343

344
        public function isLibresignFile(int $nodeId): bool {
345
                return $this->fileMapper->nodeIdExists($nodeId);
×
346
        }
347

348
        public function getSignedNodeId(): ?int {
349
                $status = $this->file->getStatus();
×
350

351
                if (!in_array($status, [FileStatus::PARTIAL_SIGNED->value, FileStatus::SIGNED->value])) {
×
352
                        return null;
×
353
                }
354
                return $this->file->getSignedNodeId();
×
355
        }
356

357
        private function loadSigners(): void {
358
                if (!$this->options->isShowSigners()) {
2✔
359
                        return;
×
360
                }
361

362
                if (!$this->file instanceof File) {
2✔
363
                        return;
×
364
                }
365

366
                if ($this->file->getSignedNodeId()) {
2✔
367
                        $fileNode = $this->getFile();
×
368
                        $certData = $this->certificateChainService->getCertificateChain($fileNode, $this->file, $this->options);
×
369
                        if ($certData) {
×
370
                                $this->signersLoader->loadSignersFromCertData($this->fileData, $certData, $this->options->getHost());
×
371
                        }
372
                }
373
                $this->signersLoader->loadLibreSignSigners($this->file, $this->fileData, $this->options, $this->certData);
2✔
374
                $this->loadSignRequestData();
2✔
375
        }
376

377
        private function loadSignRequestData(): void {
378
                if (empty($this->fileData->signers) || !is_array($this->fileData->signers)) {
2✔
379
                        return;
×
380
                }
381

382
                foreach ($this->fileData->signers as $signer) {
2✔
383
                        if (!empty($signer->me) && isset($signer->sign_uuid)) {
2✔
384
                                $this->fileData->url = $this->urlGenerator->linkToRoute('libresign.page.getPdfFile', ['uuid' => $signer->sign_uuid]);
1✔
385
                                $this->fileData->signUuid = $signer->sign_uuid;
1✔
386
                                return;
1✔
387
                        }
388
                }
389
        }
390

391
        private function loadFileMetadata(): void {
392
                $this->metadataLoader->loadMetadata($this->file, $this->fileData);
2✔
393
        }
394

395
        private function loadSettings(): void {
396
                $this->settingsLoader->loadSettings($this->fileData, $this->options);
2✔
397
        }
398

399
        public function getIdentificationDocumentsStatus(string $userId = ''): int {
400
                return $this->settingsLoader->getIdentificationDocumentsStatus($userId);
3✔
401
        }
402

403
        private function loadLibreSignData(): void {
404
                if (!$this->file) {
2✔
405
                        return;
×
406
                }
407
                $this->fileData->id = $this->file->getId();
2✔
408
                $this->fileData->uuid = $this->file->getUuid();
2✔
409
                $this->fileData->name = $this->file->getName();
2✔
410
                $this->fileData->status = $this->file->getStatus();
2✔
411
                $this->fileData->created_at = $this->file->getCreatedAt()->format(DateTimeInterface::ATOM);
2✔
412
                $this->fileData->statusText = $this->fileMapper->getTextOfStatus($this->file->getStatus());
2✔
413
                $this->fileData->nodeId = $this->file->getNodeId();
2✔
414
                $this->fileData->signatureFlow = $this->file->getSignatureFlow();
2✔
415
                $this->fileData->docmdpLevel = $this->file->getDocmdpLevel();
2✔
416
                $this->fileData->nodeType = $this->file->getNodeType();
2✔
417

418
                if ($this->fileData->nodeType !== 'envelope' && !$this->file->getParentFileId()) {
2✔
419
                        $fileId = $this->file->getId();
2✔
420

421
                        $childrenFiles = $this->fileMapper->getChildrenFiles($fileId);
2✔
422

423
                        if (!empty($childrenFiles)) {
2✔
424
                                $this->file->setNodeType('envelope');
×
425
                                $this->fileMapper->update($this->file);
×
426

427
                                $this->fileData->nodeType = 'envelope';
×
428
                                $this->fileData->filesCount = count($childrenFiles);
×
429
                                $this->fileData->files = [];
×
430
                        }
431
                }
432

433
                if ($this->fileData->nodeType === 'envelope') {
2✔
434
                        $metadata = $this->file->getMetadata();
×
435
                        $this->fileData->filesCount = $metadata['filesCount'] ?? 0;
×
436
                        $this->fileData->files = [];
×
437
                        $this->loadEnvelopeFiles();
×
438
                        if ($this->file->getStatus() === FileStatus::SIGNED->value) {
×
439
                                $latestSignedDate = $this->getLatestSignedDateFromEnvelope();
×
440
                                if ($latestSignedDate) {
×
441
                                        $this->fileData->signedDate = $latestSignedDate->format(DateTimeInterface::ATOM);
×
442
                                }
443
                        }
444
                }
445

446
                $this->fileData->requested_by = [
2✔
447
                        'userId' => $this->file->getUserId(),
2✔
448
                        'displayName' => $this->userManager->get($this->file->getUserId())->getDisplayName(),
2✔
449
                ];
2✔
450
                $this->fileData->file = $this->urlGenerator->linkToRoute('libresign.page.getPdf', ['uuid' => $this->file->getUuid()]);
2✔
451

452
                $this->loadEnvelopeData();
2✔
453

454
                if (!isset($this->fileData->files) || !is_array($this->fileData->files)) {
2✔
455
                        $this->fileData->files = [];
2✔
456
                }
457

458
                if ($this->options->isShowVisibleElements()) {
2✔
459
                        $signers = $this->signRequestMapper->getByMultipleFileId([$this->file->getId()]);
2✔
460
                        $this->fileData->visibleElements = [];
2✔
461
                        foreach ($this->signRequestMapper->getVisibleElementsFromSigners($signers) as $visibleElements) {
2✔
462
                                if (empty($visibleElements)) {
×
463
                                        continue;
×
464
                                }
465
                                $file = array_filter($this->fileData->files, fn (stdClass $file) => $file->id === $visibleElements[0]->getFileId());
×
466
                                if (empty($file)) {
×
467
                                        continue;
×
468
                                }
469
                                $file = current($file);
×
470
                                $fileMetadata = $this->file->getMetadata();
×
471
                                $this->fileData->visibleElements = array_merge(
×
472
                                        $this->fileElementService->formatVisibleElements($visibleElements, $fileMetadata),
×
473
                                        $this->fileData->visibleElements
×
474
                                );
×
475
                        }
476
                }
477
        }
478

479
        private function getLatestSignedDateFromEnvelope(): ?\DateTime {
480
                if (!$this->file || $this->file->getNodeType() !== 'envelope') {
×
481
                        return null;
×
482
                }
483

484
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
×
485
                $latestDate = null;
×
486

NEW
487
                $childFileIds = array_map(fn ($childFile) => $childFile->getId(), $childrenFiles);
×
NEW
488
                if (empty($childFileIds)) {
×
NEW
489
                        return null;
×
490
                }
491

NEW
492
                $signRequests = $this->signRequestMapper->getByMultipleFileId($childFileIds);
×
NEW
493
                foreach ($signRequests as $signRequest) {
×
NEW
494
                        $signed = $signRequest->getSigned();
×
NEW
495
                        if ($signed && (!$latestDate || $signed > $latestDate)) {
×
NEW
496
                                $latestDate = $signed;
×
497
                        }
498
                }
499

500
                return $latestDate;
×
501
        }
502

503
        private function loadEnvelopeFiles(): void {
504
                if (!$this->file || $this->file->getNodeType() !== 'envelope') {
×
505
                        return;
×
506
                }
507

508
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
×
509
                foreach ($childrenFiles as $childFile) {
×
510
                        $this->fileData->files[] = $this->buildEnvelopeChildData($childFile);
×
511
                }
512
        }
513

514
        private function buildEnvelopeChildData(File $childFile): stdClass {
515
                return $this->envelopeAssembler->buildEnvelopeChildData($childFile, $this->options);
×
516
        }
517

518
        private function loadEnvelopeData(): void {
519
                if (!$this->file->hasParent()) {
2✔
520
                        return;
2✔
521
                }
522

523
                $envelope = $this->envelopeService->getEnvelopeByFileId($this->file->getId());
×
524
                if (!$envelope) {
×
525
                        return;
×
526
                }
527

528
                $envelopeMetadata = $envelope->getMetadata();
×
529
                $this->fileData->envelope = [
×
530
                        'id' => $envelope->getId(),
×
531
                        'uuid' => $envelope->getUuid(),
×
532
                        'name' => $envelope->getName(),
×
533
                        'status' => $envelope->getStatus(),
×
534
                        'statusText' => $this->fileMapper->getTextOfStatus($envelope->getStatus()),
×
535
                        'filesCount' => $envelopeMetadata['filesCount'] ?? 0,
×
536
                        'files' => [],
×
537
                ];
×
538
        }
539

540
        private function loadMessages(): void {
541
                $this->messagesLoader->loadMessages($this->file, $this->fileData, $this->options, $this->certData);
2✔
542
        }
543

544
        /**
545
         * @return LibresignValidateFile
546
         * @psalm-return LibresignValidateFile
547
         */
548
        public function toArray(): array {
549
                $this->loadLibreSignData();
2✔
550
                $this->loadFileMetadata();
2✔
551
                $this->loadSettings();
2✔
552
                $this->loadSigners();
2✔
553
                $this->loadMessages();
2✔
554
                $this->computeEnvelopeSignersProgress();
2✔
555

556
                $return = json_decode(json_encode($this->fileData), true);
2✔
557
                ksort($return);
2✔
558
                return $return;
2✔
559
        }
560

561
        private function computeEnvelopeSignersProgress(): void {
562
                if (!$this->file || $this->file->getParentFileId() || empty($this->fileData->signers)) {
2✔
563
                        return;
×
564
                }
565

566
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
2✔
567
                if (empty($childrenFiles)) {
2✔
568
                        return;
2✔
569
                }
570

NEW
571
                $childFileIds = array_map(fn ($childFile) => $childFile->getId(), $childrenFiles);
×
NEW
572
                $allSignRequests = $this->signRequestMapper->getByMultipleFileId($childFileIds);
×
573

NEW
574
                $signRequestsByFileId = array_fill_keys($childFileIds, []);
×
NEW
575
                foreach ($allSignRequests as $signRequest) {
×
NEW
576
                        $signRequestsByFileId[$signRequest->getFileId()][] = $signRequest;
×
577
                }
578

579
                $identifyMethodsBySignRequest = [];
×
NEW
580
                if (!empty($allSignRequests)) {
×
NEW
581
                        $allSignRequestIds = array_map(fn ($sr) => $sr->getId(), $allSignRequests);
×
NEW
582
                        $identifyMethodsBySignRequest = $this->identifyMethodService
×
NEW
583
                                ->setIsRequest(false)
×
NEW
584
                                ->getIdentifyMethodsFromSignRequestIds($allSignRequestIds);
×
585
                }
586

587
                $this->envelopeProgressService->computeProgress(
×
588
                        $this->fileData,
×
589
                        $this->file,
×
590
                        $childrenFiles,
×
591
                        $signRequestsByFileId,
×
592
                        $identifyMethodsBySignRequest
×
593
                );
×
594
        }
595

596
        public function delete(int $fileId, bool $deleteFile = true): void {
597
                $file = $this->fileMapper->getById($fileId);
3✔
598

599
                $this->decrementEnvelopeFilesCountIfNeeded($file);
3✔
600

601
                if ($file->getNodeType() === 'envelope') {
3✔
602
                        $childrenFiles = $this->fileMapper->getChildrenFiles($file->getId());
×
603
                        foreach ($childrenFiles as $childFile) {
×
604
                                $this->delete($childFile->getId(), $deleteFile);
×
605
                        }
606
                }
607

608
                $this->fileElementService->deleteVisibleElements($file->getId());
3✔
609
                $list = $this->signRequestMapper->getByFileId($file->getId());
3✔
610
                foreach ($list as $signRequest) {
3✔
611
                        $this->identifyMethodService->deleteBySignRequestId($signRequest->getId());
×
612
                        $this->signRequestMapper->delete($signRequest);
×
613
                }
614
                $this->idDocsMapper->deleteByFileId($file->getId());
3✔
615
                $this->fileMapper->delete($file);
3✔
616
                if ($deleteFile) {
3✔
617
                        if ($file->getSignedNodeId()) {
2✔
618
                                $signedNextcloudFile = $this->folderService->getFileByNodeId($file->getSignedNodeId());
×
619
                                $parentFolder = $signedNextcloudFile->getParent();
×
620
                                $signedNextcloudFile->delete();
×
621
                                $this->deleteEmptyFolder($parentFolder);
×
622
                        }
623
                        try {
624
                                $nextcloudFile = $this->folderService->getFileByNodeId($file->getNodeId());
2✔
625
                                $parentFolder = $nextcloudFile->getParent();
2✔
626
                                $nextcloudFile->delete();
2✔
627
                                $this->deleteEmptyFolder($parentFolder);
2✔
628
                        } catch (NotFoundException) {
×
629
                        }
630
                }
631
        }
632

633
        private function deleteEmptyFolder(\OCP\Files\Folder $folder): void {
634
                try {
635
                        $contents = $folder->getDirectoryListing();
2✔
636
                        if (count($contents) === 0) {
2✔
637
                                $folder->delete();
2✔
638
                        }
639
                } catch (\Exception $e) {
×
640
                        $this->logger->debug('Could not delete empty folder: ' . $e->getMessage(), [
×
641
                                'exception' => $e,
×
642
                        ]);
×
643
                }
644
        }
645

646
        public function processUploadedFilesWithRollback(array $filesArray, IUser $user, array $settings): array {
647
                return $this->uploadProcessor->processUploadedFilesWithRollback($filesArray, $user, $settings);
×
648
        }
649

650
        public function updateEnvelopeFilesCount(File $envelope, int $delta = 0): void {
651
                $metadata = $envelope->getMetadata();
×
652
                $currentCount = $metadata['filesCount'] ?? 0;
×
653
                $metadata['filesCount'] = max(0, $currentCount + $delta);
×
654
                $envelope->setMetadata($metadata);
×
655
                $this->fileMapper->update($envelope);
×
656
        }
657

658
        private function decrementEnvelopeFilesCountIfNeeded(File $file): void {
659
                if ($file->getParentFileId() === null) {
3✔
660
                        return;
3✔
661
                }
662

663
                $parentEnvelope = $this->fileMapper->getById($file->getParentFileId());
×
664
                if ($parentEnvelope->getNodeType() === 'envelope') {
×
665
                        $this->updateEnvelopeFilesCount($parentEnvelope, -1);
×
666
                }
667
        }
668
}
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