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

LibreSign / libresign / 20748684148

06 Jan 2026 12:44PM UTC coverage: 44.872%. First build
20748684148

Pull #6347

github

web-flow
Merge a49822724 into b5e3cf018
Pull Request #6347: feat: delete empty folders and respect checkbox

9 of 20 new or added lines in 2 files covered. (45.0%)

6711 of 14956 relevant lines covered (44.87%)

5.05 hits per line

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

45.83
/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\Envelope\EnvelopeService;
25
use OCA\Libresign\Service\File\CertificateChainService;
26
use OCA\Libresign\Service\File\EnvelopeAssembler;
27
use OCA\Libresign\Service\File\EnvelopeProgressService;
28
use OCA\Libresign\Service\File\FileContentProvider;
29
use OCA\Libresign\Service\File\FileResponseOptions;
30
use OCA\Libresign\Service\File\MessagesLoader;
31
use OCA\Libresign\Service\File\MetadataLoader;
32
use OCA\Libresign\Service\File\MimeService;
33
use OCA\Libresign\Service\File\PdfValidator;
34
use OCA\Libresign\Service\File\SettingsLoader;
35
use OCA\Libresign\Service\File\SignersLoader;
36
use OCA\Libresign\Service\File\UploadProcessor;
37
use OCP\AppFramework\Db\DoesNotExistException;
38
use OCP\Files\IMimeTypeDetector;
39
use OCP\Files\IRootFolder;
40
use OCP\Files\Node;
41
use OCP\Files\NotFoundException;
42
use OCP\IL10N;
43
use OCP\IURLGenerator;
44
use OCP\IUser;
45
use OCP\IUserManager;
46
use Psr\Log\LoggerInterface;
47
use stdClass;
48

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

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

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

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

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

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

125
                $this->validateFileContent($content, $extension);
15✔
126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

354
                if (!in_array($status, [File::STATUS_PARTIAL_SIGNED, File::STATUS_SIGNED])) {
×
355
                        return null;
×
356
                }
357
                return $this->file->getSignedNodeId();
×
358
        }
359

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

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

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

379
        private function loadFileMetadata(): void {
380
                $this->metadataLoader->loadMetadata($this->file, $this->fileData);
2✔
381
        }
382

383
        private function loadSettings(): void {
384
                $this->settingsLoader->loadSettings($this->fileData, $this->options);
2✔
385
        }
386

387
        public function getIdentificationDocumentsStatus(string $userId = ''): int {
388
                return $this->settingsLoader->getIdentificationDocumentsStatus($userId);
3✔
389
        }
390

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

406
                if ($this->fileData->nodeType !== 'envelope' && !$this->file->getParentFileId()) {
2✔
407
                        $fileId = $this->file->getId();
2✔
408

409
                        $childrenFiles = $this->fileMapper->getChildrenFiles($fileId);
2✔
410

411
                        if (!empty($childrenFiles)) {
2✔
412
                                $this->file->setNodeType('envelope');
×
413
                                $this->fileMapper->update($this->file);
×
414

415
                                $this->fileData->nodeType = 'envelope';
×
416
                                $this->fileData->filesCount = count($childrenFiles);
×
417
                                $this->fileData->files = [];
×
418
                        }
419
                }
420

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

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

440
                $this->loadEnvelopeData();
2✔
441

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

463
        private function getLatestSignedDateFromEnvelope(): ?\DateTime {
464
                if (!$this->file || $this->file->getNodeType() !== 'envelope') {
×
465
                        return null;
×
466
                }
467

468
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
×
469
                $latestDate = null;
×
470

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

481
                return $latestDate;
×
482
        }
483

484
        private function loadEnvelopeFiles(): void {
485
                if (!$this->file || $this->file->getNodeType() !== 'envelope') {
×
486
                        return;
×
487
                }
488

489
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
×
490
                foreach ($childrenFiles as $childFile) {
×
491
                        $this->fileData->files[] = $this->buildEnvelopeChildData($childFile);
×
492
                }
493
        }
494

495
        private function buildEnvelopeChildData(File $childFile): stdClass {
496
                return $this->envelopeAssembler->buildEnvelopeChildData($childFile, $this->options);
×
497
        }
498

499
        private function loadEnvelopeData(): void {
500
                if (!$this->file->hasParent()) {
2✔
501
                        return;
2✔
502
                }
503

504
                $envelope = $this->envelopeService->getEnvelopeByFileId($this->file->getId());
×
505
                if (!$envelope) {
×
506
                        return;
×
507
                }
508

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

521
        private function loadMessages(): void {
522
                $this->messagesLoader->loadMessages($this->file, $this->fileData, $this->options, $this->certData);
2✔
523
        }
524

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

537
                $return = json_decode(json_encode($this->fileData), true);
2✔
538
                ksort($return);
2✔
539
                return $return;
2✔
540
        }
541

542
        private function computeEnvelopeSignersProgress(): void {
543
                if (!$this->file || $this->file->getParentFileId()) {
2✔
544
                        return;
×
545
                }
546
                if (empty($this->fileData->signers)) {
2✔
547
                        return;
×
548
                }
549

550
                $childrenFiles = $this->fileMapper->getChildrenFiles($this->file->getId());
2✔
551
                if (empty($childrenFiles)) {
2✔
552
                        return;
2✔
553
                }
554

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

564
                $this->envelopeProgressService->computeProgress(
×
565
                        $this->fileData,
×
566
                        $this->file,
×
567
                        $childrenFiles,
×
568
                        $signRequestsByFileId,
×
569
                        $identifyMethodsBySignRequest
×
570
                );
×
571
        }
572

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

576
                $this->decrementEnvelopeFilesCountIfNeeded($file);
3✔
577

578
                if ($file->getNodeType() === 'envelope') {
3✔
579
                        $childrenFiles = $this->fileMapper->getChildrenFiles($file->getId());
×
580
                        foreach ($childrenFiles as $childFile) {
×
NEW
581
                                $this->delete($childFile->getId(), $deleteFile);
×
582
                        }
583
                }
584

585
                $this->fileElementService->deleteVisibleElements($file->getId());
3✔
586
                $list = $this->signRequestMapper->getByFileId($file->getId());
3✔
587
                foreach ($list as $signRequest) {
3✔
588
                        $this->identifyMethodService->deleteBySignRequestId($signRequest->getId());
×
589
                        $this->signRequestMapper->delete($signRequest);
×
590
                }
591
                $this->idDocsMapper->deleteByFileId($file->getId());
3✔
592
                $this->fileMapper->delete($file);
3✔
593
                if ($deleteFile) {
3✔
594
                        if ($file->getSignedNodeId()) {
2✔
NEW
595
                                $signedNextcloudFile = $this->folderService->getFileByNodeId($file->getSignedNodeId());
×
NEW
596
                                $parentFolder = $signedNextcloudFile->getParent();
×
NEW
597
                                $signedNextcloudFile->delete();
×
NEW
598
                                $this->deleteEmptyFolder($parentFolder);
×
599
                        }
600
                        try {
601
                                $nextcloudFile = $this->folderService->getFileByNodeId($file->getNodeId());
2✔
602
                                $parentFolder = $nextcloudFile->getParent();
2✔
603
                                $nextcloudFile->delete();
2✔
604
                                $this->deleteEmptyFolder($parentFolder);
2✔
NEW
605
                        } catch (NotFoundException) {
×
606
                        }
607
                }
608
        }
609

610
        private function deleteEmptyFolder(\OCP\Files\Folder $folder): void {
611
                try {
612
                        $contents = $folder->getDirectoryListing();
2✔
613
                        if (count($contents) === 0) {
2✔
614
                                $folder->delete();
2✔
615
                        }
NEW
616
                } catch (\Exception $e) {
×
NEW
617
                        $this->logger->debug('Could not delete empty folder: ' . $e->getMessage(), [
×
NEW
618
                                'exception' => $e,
×
NEW
619
                        ]);
×
620
                }
621
        }
622

623
        public function processUploadedFilesWithRollback(array $filesArray, IUser $user, array $settings): array {
624
                return $this->uploadProcessor->processUploadedFilesWithRollback($filesArray, $user, $settings);
×
625
        }
626

627
        public function updateEnvelopeFilesCount(File $envelope, int $delta = 0): void {
628
                $metadata = $envelope->getMetadata();
×
629
                $currentCount = $metadata['filesCount'] ?? 0;
×
630
                $metadata['filesCount'] = max(0, $currentCount + $delta);
×
631
                $envelope->setMetadata($metadata);
×
632
                $this->fileMapper->update($envelope);
×
633
        }
634

635
        private function decrementEnvelopeFilesCountIfNeeded(File $file): void {
636
                if ($file->getParentFileId() === null) {
3✔
637
                        return;
3✔
638
                }
639

640
                $parentEnvelope = $this->fileMapper->getById($file->getParentFileId());
×
641
                if ($parentEnvelope->getNodeType() === 'envelope') {
×
642
                        $this->updateEnvelopeFilesCount($parentEnvelope, -1);
×
643
                }
644
        }
645
}
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