• 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

46.78
/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\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->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
                $this->validateFileContent($content, $extension);
15✔
127

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

133
        public function getNodeFromUploadedFile(array $data): Node {
134
                return $this->uploadProcessor->getNodeFromUploadedFile($data);
×
135
        }
136

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

143
        private function getExtension(string $content): string {
144
                return $this->mimeService->getExtension($content);
15✔
145
        }
146

147
        private function getFileRaw(array $data): string {
148
                return $this->contentProvider->getContentFromData($data);
15✔
149
        }
150

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

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

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

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

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

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

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

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

228
        public function setSignerIdentified(bool $identified = true): self {
229
                $this->options->setSignerIdentified($identified);
×
230
                return $this;
×
231
        }
232

233
        public function setIdentifyMethodId(?int $id): self {
234
                $this->options->setIdentifyMethodId($id);
2✔
235
                return $this;
2✔
236
        }
237

238
        public function setHost(string $host): self {
239
                $this->options->setHost($host);
2✔
240
                return $this;
2✔
241
        }
242

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

252
        public function setSignRequest(SignRequest $signRequest): self {
253
                $this->signRequest = $signRequest;
×
254
                return $this;
×
255
        }
256

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

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

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

273
                return $this->setFile($file);
3✔
274
        }
275

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

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

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

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

292
        public function validateUploadedFile(array $file): void {
293
                $this->uploadHelper->validateUploadedFile($file);
×
294
        }
295

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

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

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

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

344
        public function getStatus(): int {
345
                return $this->file->getStatus();
1✔
346
        }
347

348
        public function isLibresignFile(int $nodeId): bool {
349
                return $this->fileMapper->fileIdExists($nodeId);
×
350
        }
351

352
        public function getSignedNodeId(): ?int {
353
                $status = $this->file->getStatus();
×
354

NEW
355
                if (!in_array($status, [FileStatus::PARTIAL_SIGNED->value, FileStatus::SIGNED->value])) {
×
356
                        return null;
×
357
                }
358
                return $this->file->getSignedNodeId();
×
359
        }
360

361
        private function loadSigners(): void {
362
                if (!$this->options->isShowSigners()) {
2✔
363
                        return;
×
364
                }
365

366
                if (!$this->file instanceof File) {
2✔
367
                        return;
×
368
                }
369

370
                if ($this->file->getSignedNodeId()) {
2✔
371
                        $fileNode = $this->getFile();
×
372
                        $certData = $this->certificateChainService->getCertificateChain($fileNode, $this->file, $this->options);
×
373
                        if ($certData) {
×
374
                                $this->signersLoader->loadSignersFromCertData($this->fileData, $certData, $this->options->getHost());
×
375
                        }
376
                }
377
                $this->signersLoader->loadLibreSignSigners($this->file, $this->fileData, $this->options, $this->certData);
2✔
378
                $this->loadSignRequestUrl();
2✔
379
        }
380

381
        private function loadSignRequestUrl(): void {
382
                if (empty($this->fileData->signers) || !is_array($this->fileData->signers)) {
2✔
383
                        return;
×
384
                }
385

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

394
        private function loadFileMetadata(): void {
395
                $this->metadataLoader->loadMetadata($this->file, $this->fileData);
2✔
396
        }
397

398
        private function loadSettings(): void {
399
                $this->settingsLoader->loadSettings($this->fileData, $this->options);
2✔
400
        }
401

402
        public function getIdentificationDocumentsStatus(string $userId = ''): int {
403
                return $this->settingsLoader->getIdentificationDocumentsStatus($userId);
3✔
404
        }
405

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

421
                if ($this->fileData->nodeType !== 'envelope' && !$this->file->getParentFileId()) {
2✔
422
                        $fileId = $this->file->getId();
2✔
423

424
                        $childrenFiles = $this->fileMapper->getChildrenFiles($fileId);
2✔
425

426
                        if (!empty($childrenFiles)) {
2✔
427
                                $this->file->setNodeType('envelope');
×
428
                                $this->fileMapper->update($this->file);
×
429

430
                                $this->fileData->nodeType = 'envelope';
×
431
                                $this->fileData->filesCount = count($childrenFiles);
×
432
                                $this->fileData->files = [];
×
433
                        }
434
                }
435

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

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

455
                $this->loadEnvelopeData();
2✔
456

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

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

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

486
                foreach ($childrenFiles as $childFile) {
×
487
                        $signRequests = $this->signRequestMapper->getByFileId($childFile->getId());
×
488
                        foreach ($signRequests as $signRequest) {
×
489
                                $signed = $signRequest->getSigned();
×
490
                                if ($signed && (!$latestDate || $signed > $latestDate)) {
×
491
                                        $latestDate = $signed;
×
492
                                }
493
                        }
494
                }
495

496
                return $latestDate;
×
497
        }
498

499
        private function loadEnvelopeFiles(): void {
500
                if (!$this->file || $this->file->getNodeType() !== 'envelope') {
×
501
                        return;
×
502
                }
503

504
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
×
505
                foreach ($childrenFiles as $childFile) {
×
506
                        $this->fileData->files[] = $this->buildEnvelopeChildData($childFile);
×
507
                }
508
        }
509

510
        private function buildEnvelopeChildData(File $childFile): stdClass {
511
                return $this->envelopeAssembler->buildEnvelopeChildData($childFile, $this->options);
×
512
        }
513

514
        private function loadEnvelopeData(): void {
515
                if (!$this->file->hasParent()) {
2✔
516
                        return;
2✔
517
                }
518

519
                $envelope = $this->envelopeService->getEnvelopeByFileId($this->file->getId());
×
520
                if (!$envelope) {
×
521
                        return;
×
522
                }
523

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

536
        private function loadMessages(): void {
537
                $this->messagesLoader->loadMessages($this->file, $this->fileData, $this->options, $this->certData);
2✔
538
        }
539

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

552
                $return = json_decode(json_encode($this->fileData), true);
2✔
553
                ksort($return);
2✔
554
                return $return;
2✔
555
        }
556

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

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

570
                $signRequestsByFileId = [];
×
571
                $identifyMethodsBySignRequest = [];
×
572
                foreach ($childrenFiles as $child) {
×
573
                        $signRequestsByFileId[$child->getId()] = $this->signRequestMapper->getByFileId($child->getId());
×
574
                        foreach ($signRequestsByFileId[$child->getId()] as $sr) {
×
575
                                $identifyMethodsBySignRequest[$sr->getId()] = $this->identifyMethodService->setIsRequest(false)->getIdentifyMethodsFromSignRequestId($sr->getId());
×
576
                        }
577
                }
578

579
                $this->envelopeProgressService->computeProgress(
×
580
                        $this->fileData,
×
581
                        $this->file,
×
582
                        $childrenFiles,
×
583
                        $signRequestsByFileId,
×
584
                        $identifyMethodsBySignRequest
×
585
                );
×
586
        }
587

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

591
                $this->decrementEnvelopeFilesCountIfNeeded($file);
3✔
592

593
                if ($file->getNodeType() === 'envelope') {
3✔
594
                        $childrenFiles = $this->fileMapper->getChildrenFiles($file->getId());
×
595
                        foreach ($childrenFiles as $childFile) {
×
596
                                $this->delete($childFile->getId(), $deleteFile);
×
597
                        }
598
                }
599

600
                $this->fileElementService->deleteVisibleElements($file->getId());
3✔
601
                $list = $this->signRequestMapper->getByFileId($file->getId());
3✔
602
                foreach ($list as $signRequest) {
3✔
603
                        $this->identifyMethodService->deleteBySignRequestId($signRequest->getId());
×
604
                        $this->signRequestMapper->delete($signRequest);
×
605
                }
606
                $this->idDocsMapper->deleteByFileId($file->getId());
3✔
607
                $this->fileMapper->delete($file);
3✔
608
                if ($deleteFile) {
3✔
609
                        if ($file->getSignedNodeId()) {
2✔
610
                                $signedNextcloudFile = $this->folderService->getFileByNodeId($file->getSignedNodeId());
×
611
                                $parentFolder = $signedNextcloudFile->getParent();
×
612
                                $signedNextcloudFile->delete();
×
613
                                $this->deleteEmptyFolder($parentFolder);
×
614
                        }
615
                        try {
616
                                $nextcloudFile = $this->folderService->getFileByNodeId($file->getNodeId());
2✔
617
                                $parentFolder = $nextcloudFile->getParent();
2✔
618
                                $nextcloudFile->delete();
2✔
619
                                $this->deleteEmptyFolder($parentFolder);
2✔
620
                        } catch (NotFoundException) {
×
621
                        }
622
                }
623
        }
624

625
        private function deleteEmptyFolder(\OCP\Files\Folder $folder): void {
626
                try {
627
                        $contents = $folder->getDirectoryListing();
2✔
628
                        if (count($contents) === 0) {
2✔
629
                                $folder->delete();
2✔
630
                        }
631
                } catch (\Exception $e) {
×
632
                        $this->logger->debug('Could not delete empty folder: ' . $e->getMessage(), [
×
633
                                'exception' => $e,
×
634
                        ]);
×
635
                }
636
        }
637

638
        public function processUploadedFilesWithRollback(array $filesArray, IUser $user, array $settings): array {
639
                return $this->uploadProcessor->processUploadedFilesWithRollback($filesArray, $user, $settings);
×
640
        }
641

642
        public function updateEnvelopeFilesCount(File $envelope, int $delta = 0): void {
643
                $metadata = $envelope->getMetadata();
×
644
                $currentCount = $metadata['filesCount'] ?? 0;
×
645
                $metadata['filesCount'] = max(0, $currentCount + $delta);
×
646
                $envelope->setMetadata($metadata);
×
647
                $this->fileMapper->update($envelope);
×
648
        }
649

650
        private function decrementEnvelopeFilesCountIfNeeded(File $file): void {
651
                if ($file->getParentFileId() === null) {
3✔
652
                        return;
3✔
653
                }
654

655
                $parentEnvelope = $this->fileMapper->getById($file->getParentFileId());
×
656
                if ($parentEnvelope->getNodeType() === 'envelope') {
×
657
                        $this->updateEnvelopeFilesCount($parentEnvelope, -1);
×
658
                }
659
        }
660
}
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