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

LibreSign / libresign / 20621495436

31 Dec 2025 02:59PM UTC coverage: 44.647%. First build
20621495436

Pull #6256

github

web-flow
Merge 4343635f1 into 27812ed76
Pull Request #6256: feat: add dashboard pending signatures widget

57 of 239 new or added lines in 16 files covered. (23.85%)

6618 of 14823 relevant lines covered (44.65%)

5.05 hits per line

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

40.15
/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\Exception\LibresignException;
20
use OCA\Libresign\Handler\DocMdpHandler;
21
use OCA\Libresign\Handler\SignEngine\Pkcs12Handler;
22
use OCA\Libresign\Helper\FileUploadHelper;
23
use OCA\Libresign\ResponseDefinitions;
24
use OCA\Libresign\Service\File\CertificateChainService;
25
use OCA\Libresign\Service\File\EnvelopeAssembler;
26
use OCA\Libresign\Service\File\EnvelopeProgressService;
27
use OCA\Libresign\Service\File\FileContentProvider;
28
use OCA\Libresign\Service\File\FileResponseOptions;
29
use OCA\Libresign\Service\File\MessagesLoader;
30
use OCA\Libresign\Service\File\MetadataLoader;
31
use OCA\Libresign\Service\File\MimeService;
32
use OCA\Libresign\Service\File\PdfValidator;
33
use OCA\Libresign\Service\File\SettingsLoader;
34
use OCA\Libresign\Service\File\SignersLoader;
35
use OCA\Libresign\Service\File\UploadProcessor;
36
use OCP\AppFramework\Db\DoesNotExistException;
37
use OCP\Files\IMimeTypeDetector;
38
use OCP\Files\IRootFolder;
39
use OCP\Files\Node;
40
use OCP\Files\NotFoundException;
41
use OCP\IL10N;
42
use OCP\IURLGenerator;
43
use OCP\IUser;
44
use OCP\IUserManager;
45
use Psr\Log\LoggerInterface;
46
use stdClass;
47

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

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

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

104
                if (isset($data['uploadedFile'])) {
15✔
105
                        return $this->getNodeFromUploadedFile($data);
×
106
                }
107

108
                if (isset($data['file']['fileNode']) && $data['file']['fileNode'] instanceof Node) {
15✔
109
                        return $data['file']['fileNode'];
×
110
                }
111
                if (isset($data['file']['fileId'])) {
15✔
NEW
112
                        return $this->folderService->getFileByNodeId($data['file']['fileId']);
×
113
                }
114
                if (isset($data['file']['path'])) {
15✔
115
                        return $this->folderService->getFileByPath($data['file']['path']);
×
116
                }
117

118
                $content = $this->getFileRaw($data);
15✔
119
                $extension = $this->getExtension($content);
15✔
120

121
                $this->validateFileContent($content, $extension);
15✔
122

123
                $folderToFile = $this->folderService->getFolderForFile($data, $data['userManager']);
15✔
124
                $filename = $this->resolveFileName($data, $extension);
15✔
125
                return $folderToFile->newFile($filename, $content);
15✔
126
        }
127

128
        public function getNodeFromUploadedFile(array $data): Node {
129
                return $this->uploadProcessor->getNodeFromUploadedFile($data);
×
130
        }
131

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

268
                return $this->setFile($file);
3✔
269
        }
270

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

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

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

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

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

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

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

306
                $memoryFile = fopen($file['tmp_name'], 'rb');
×
307
                try {
308
                        $this->certData = $this->pkcs12Handler->getCertificateChain($memoryFile);
×
309
                        $this->fileData->status = File::STATUS_SIGNED;
×
310
                        // Ignore when isnt a signed file
311
                } catch (LibresignException) {
×
312
                        $this->fileData->status = File::STATUS_DRAFT;
×
313
                }
314
                fclose($memoryFile);
×
315
                unlink($file['tmp_name']);
×
316
                $this->fileData->hash = hash('sha256', $this->fileContent);
×
317
                try {
318
                        $libresignFile = $this->fileMapper->getBySignedHash($this->fileData->hash);
×
319
                        $this->setFile($libresignFile);
×
320
                } catch (DoesNotExistException) {
×
321
                        $this->fileData->status = File::STATUS_NOT_LIBRESIGN_FILE;
×
322
                }
323
                $this->fileData->name = $file['name'];
×
324
                return $this;
×
325
        }
326

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

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

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

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

350
                if (!in_array($status, [File::STATUS_PARTIAL_SIGNED, File::STATUS_SIGNED])) {
×
351
                        return null;
×
352
                }
353
                return $this->file->getSignedNodeId();
×
354
        }
355

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

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

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

375
        private function loadFileMetadata(): void {
376
                $this->metadataLoader->loadMetadata($this->file, $this->fileData);
2✔
377
        }
378

379
        private function loadSettings(): void {
380
                $this->settingsLoader->loadSettings($this->fileData, $this->options);
2✔
381
        }
382

383
        public function getIdentificationDocumentsStatus(string $userId = ''): int {
384
                return $this->settingsLoader->getIdentificationDocumentsStatus($userId);
3✔
385
        }
386

387
        private function loadLibreSignData(): void {
388
                if (!$this->file) {
2✔
389
                        return;
×
390
                }
391
                $this->fileData->id = $this->file->getId();
2✔
392
                $this->fileData->uuid = $this->file->getUuid();
2✔
393
                $this->fileData->name = $this->file->getName();
2✔
394
                $this->fileData->status = $this->file->getStatus();
2✔
395
                $this->fileData->created_at = $this->file->getCreatedAt()->format(DateTimeInterface::ATOM);
2✔
396
                $this->fileData->statusText = $this->fileMapper->getTextOfStatus($this->file->getStatus());
2✔
397
                $this->fileData->nodeId = $this->file->getNodeId();
2✔
398
                $this->fileData->signatureFlow = $this->file->getSignatureFlow();
2✔
399
                $this->fileData->docmdpLevel = $this->file->getDocmdpLevel();
2✔
400
                $this->fileData->nodeType = $this->file->getNodeType();
2✔
401

402
                if ($this->fileData->nodeType !== 'envelope' && !$this->file->getParentFileId()) {
2✔
403
                        $fileId = $this->file->getId();
2✔
404

405
                        $childrenFiles = $this->fileMapper->getChildrenFiles($fileId);
2✔
406

407
                        if (!empty($childrenFiles)) {
2✔
408
                                $this->file->setNodeType('envelope');
×
409
                                $this->fileMapper->update($this->file);
×
410

411
                                $this->fileData->nodeType = 'envelope';
×
412
                                $this->fileData->filesCount = count($childrenFiles);
×
413
                                $this->fileData->files = [];
×
414
                        }
415
                }
416

417
                if ($this->fileData->nodeType === 'envelope') {
2✔
418
                        $metadata = $this->file->getMetadata();
×
419
                        $this->fileData->filesCount = $metadata['filesCount'] ?? 0;
×
420
                        $this->fileData->files = [];
×
421
                        $this->loadEnvelopeFiles();
×
422
                        if ($this->file->getStatus() === File::STATUS_SIGNED) {
×
423
                                $latestSignedDate = $this->getLatestSignedDateFromEnvelope();
×
424
                                if ($latestSignedDate) {
×
425
                                        $this->fileData->signedDate = $latestSignedDate->format(DateTimeInterface::ATOM);
×
426
                                }
427
                        }
428
                }
429

430
                $this->fileData->requested_by = [
2✔
431
                        'userId' => $this->file->getUserId(),
2✔
432
                        'displayName' => $this->userManager->get($this->file->getUserId())->getDisplayName(),
2✔
433
                ];
2✔
434
                $this->fileData->file = $this->urlGenerator->linkToRoute('libresign.page.getPdf', ['uuid' => $this->file->getUuid()]);
2✔
435

436
                $this->loadEnvelopeData();
2✔
437

438
                if ($this->options->isShowVisibleElements()) {
2✔
439
                        $signers = $this->signRequestMapper->getByMultipleFileId([$this->file->getId()]);
2✔
440
                        $this->fileData->visibleElements = [];
2✔
441
                        foreach ($this->signRequestMapper->getVisibleElementsFromSigners($signers) as $visibleElements) {
2✔
442
                                if (empty($visibleElements)) {
×
443
                                        continue;
×
444
                                }
445
                                $file = array_filter($this->fileData->files, fn (stdClass $file) => $file->id === $visibleElements[0]->getFileId());
×
446
                                if (empty($file)) {
×
447
                                        continue;
×
448
                                }
449
                                $file = current($file);
×
450
                                $fileMetadata = $this->file->getMetadata();
×
451
                                $this->fileData->visibleElements = array_merge(
×
452
                                        $this->fileElementService->formatVisibleElements($visibleElements, $fileMetadata),
×
453
                                        $this->fileData->visibleElements
×
454
                                );
×
455
                        }
456
                }
457
        }
458

459
        private function getLatestSignedDateFromEnvelope(): ?\DateTime {
460
                if (!$this->file || $this->file->getNodeType() !== 'envelope') {
×
461
                        return null;
×
462
                }
463

464
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
×
465
                $latestDate = null;
×
466

467
                foreach ($childrenFiles as $childFile) {
×
468
                        $signRequests = $this->signRequestMapper->getByFileId($childFile->getId());
×
469
                        foreach ($signRequests as $signRequest) {
×
470
                                $signed = $signRequest->getSigned();
×
471
                                if ($signed && (!$latestDate || $signed > $latestDate)) {
×
472
                                        $latestDate = $signed;
×
473
                                }
474
                        }
475
                }
476

477
                return $latestDate;
×
478
        }
479

480
        private function loadEnvelopeFiles(): void {
481
                if (!$this->file || $this->file->getNodeType() !== 'envelope') {
×
482
                        return;
×
483
                }
484

485
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
×
486
                foreach ($childrenFiles as $childFile) {
×
487
                        $this->fileData->files[] = $this->buildEnvelopeChildData($childFile);
×
488
                }
489
        }
490

491
        private function buildEnvelopeChildData(File $childFile): stdClass {
492
                return $this->envelopeAssembler->buildEnvelopeChildData($childFile, $this->options);
×
493
        }
494

495
        private function loadEnvelopeData(): void {
496
                if (!$this->file->hasParent()) {
2✔
497
                        return;
2✔
498
                }
499

500
                $envelope = $this->envelopeService->getEnvelopeByFileId($this->file->getId());
×
501
                if (!$envelope) {
×
502
                        return;
×
503
                }
504

505
                $envelopeMetadata = $envelope->getMetadata();
×
506
                $this->fileData->envelope = [
×
507
                        'id' => $envelope->getId(),
×
508
                        'uuid' => $envelope->getUuid(),
×
509
                        'name' => $envelope->getName(),
×
510
                        'status' => $envelope->getStatus(),
×
511
                        'statusText' => $this->fileMapper->getTextOfStatus($envelope->getStatus()),
×
512
                        'filesCount' => $envelopeMetadata['filesCount'] ?? 0,
×
513
                        'files' => [],
×
514
                ];
×
515
        }
516

517
        private function loadMessages(): void {
518
                $this->messagesLoader->loadMessages($this->file, $this->fileData, $this->options, $this->certData);
2✔
519
        }
520

521
        /**
522
         * @return LibresignValidateFile
523
         * @psalm-return LibresignValidateFile
524
         */
525
        public function toArray(): array {
526
                $this->loadLibreSignData();
2✔
527
                $this->loadFileMetadata();
2✔
528
                $this->loadSettings();
2✔
529
                $this->loadSigners();
2✔
530
                $this->loadMessages();
2✔
531
                $this->computeEnvelopeSignersProgress();
2✔
532

533
                $return = json_decode(json_encode($this->fileData), true);
2✔
534
                ksort($return);
2✔
535
                return $return;
2✔
536
        }
537

538
        private function computeEnvelopeSignersProgress(): void {
539
                if (!$this->file || $this->file->getParentFileId()) {
2✔
540
                        return;
×
541
                }
542
                if (empty($this->fileData->signers)) {
2✔
543
                        return;
×
544
                }
545

546
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
2✔
547
                if (empty($childrenFiles)) {
2✔
548
                        return;
2✔
549
                }
550

551
                $signRequestsByFileId = [];
×
552
                $identifyMethodsBySignRequest = [];
×
553
                foreach ($childrenFiles as $child) {
×
554
                        $signRequestsByFileId[$child->getId()] = $this->signRequestMapper->getByFileId($child->getId());
×
555
                        foreach ($signRequestsByFileId[$child->getId()] as $sr) {
×
556
                                $identifyMethodsBySignRequest[$sr->getId()] = $this->identifyMethodService->setIsRequest(false)->getIdentifyMethodsFromSignRequestId($sr->getId());
×
557
                        }
558
                }
559

560
                $this->envelopeProgressService->computeProgress(
×
561
                        $this->fileData,
×
562
                        $this->file,
×
563
                        $childrenFiles,
×
564
                        $signRequestsByFileId,
×
565
                        $identifyMethodsBySignRequest
×
566
                );
×
567
        }
568

569
        public function delete(int $fileId): void {
570
                $file = $this->fileMapper->getById($fileId);
×
571

572
                $this->decrementEnvelopeFilesCountIfNeeded($file);
×
573

574
                if ($file->getNodeType() === 'envelope') {
×
575
                        $childrenFiles = $this->fileMapper->getChildrenFiles($file->getId());
×
576
                        foreach ($childrenFiles as $childFile) {
×
577
                                $this->delete($childFile->getId());
×
578
                        }
579
                }
580

581
                $this->fileElementService->deleteVisibleElements($file->getId());
×
582
                $list = $this->signRequestMapper->getByFileId($file->getId());
×
583
                foreach ($list as $signRequest) {
×
584
                        $this->identifyMethodService->deleteBySignRequestId($signRequest->getId());
×
585
                        $this->signRequestMapper->delete($signRequest);
×
586
                }
587
                $this->idDocsMapper->deleteByFileId($file->getId());
×
588
                $this->fileMapper->delete($file);
×
589
                if ($file->getSignedNodeId()) {
×
NEW
590
                        $signedNextcloudFile = $this->folderService->getFileByNodeId($file->getSignedNodeId());
×
591
                        $signedNextcloudFile->delete();
×
592
                }
593
                try {
NEW
594
                        $nextcloudFile = $this->folderService->getFileByNodeId($file->getNodeId());
×
595
                        $nextcloudFile->delete();
×
596
                } catch (NotFoundException) {
×
597
                }
598
        }
599

600
        public function processUploadedFilesWithRollback(array $filesArray, IUser $user, array $settings): array {
601
                return $this->uploadProcessor->processUploadedFilesWithRollback($filesArray, $user, $settings);
×
602
        }
603

604
        public function updateEnvelopeFilesCount(File $envelope, int $delta = 0): void {
605
                $metadata = $envelope->getMetadata();
×
606
                $currentCount = $metadata['filesCount'] ?? 0;
×
607
                $metadata['filesCount'] = max(0, $currentCount + $delta);
×
608
                $envelope->setMetadata($metadata);
×
609
                $this->fileMapper->update($envelope);
×
610
        }
611

612
        private function decrementEnvelopeFilesCountIfNeeded(File $file): void {
613
                if ($file->getParentFileId() === null) {
×
614
                        return;
×
615
                }
616

617
                $parentEnvelope = $this->fileMapper->getById($file->getParentFileId());
×
618
                if ($parentEnvelope->getNodeType() === 'envelope') {
×
619
                        $this->updateEnvelopeFilesCount($parentEnvelope, -1);
×
620
                }
621
        }
622
}
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