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

LibreSign / libresign / 20604636063

30 Dec 2025 07:49PM UTC coverage: 44.945%. First build
20604636063

Pull #6274

github

web-flow
Merge 279e3c73c into 4540ca717
Pull Request #6274: fix: envelope single folder

13 of 26 new or added lines in 5 files covered. (50.0%)

6615 of 14718 relevant lines covered (44.94%)

5.09 hits per line

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

97.83
/lib/Service/File/UploadProcessor.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
7
 * SPDX-License-Identifier: AGPL-3.0-or-later
8
 */
9

10
namespace OCA\Libresign\Service\File;
11

12
use OCA\Libresign\Exception\LibresignException;
13
use OCA\Libresign\Helper\FileUploadHelper;
14
use OCA\Libresign\Helper\ValidateHelper;
15
use OCA\Libresign\Service\FolderService;
16
use OCP\Files\Node;
17
use OCP\IUser;
18
use Psr\Log\LoggerInterface;
19

20
class UploadProcessor {
21
        public function __construct(
22
                private FileUploadHelper $uploadHelper,
23
                private FolderService $folderService,
24
                private MimeService $mimeService,
25
                private PdfValidator $pdfValidator,
26
                private ValidateHelper $validateHelper,
27
                private LoggerInterface $logger,
28
        ) {
29
        }
48✔
30

31
        /**
32
         * Get Node from uploaded file data
33
         *
34
         * @param array $data Must contain 'uploadedFile', 'userManager', 'name', and optionally 'settings'
35
         * @return Node The created file node
36
         * @throws LibresignException
37
         */
38
        public function getNodeFromUploadedFile(array $data): Node {
39
                if (!$this->folderService->getUserId()) {
8✔
40
                        $this->folderService->setUserId($data['userManager']->getUID());
8✔
41
                }
42

43
                $uploadedFile = $data['uploadedFile'];
8✔
44

45
                $this->uploadHelper->validateUploadedFile($uploadedFile);
8✔
46
                $content = $this->uploadHelper->readUploadedFile($uploadedFile);
8✔
47

48
                $extension = $this->mimeService->getExtension($content);
8✔
49
                $this->validateFileContent($content, $extension);
8✔
50

51
                $folderToFile = $this->folderService->getFolderForFile($data, $data['userManager']);
8✔
52
                if (!$folderToFile instanceof \OCP\Files\Folder) {
8✔
NEW
53
                        throw new LibresignException('Envelope folder not found');
×
54
                }
55

56
                @unlink($uploadedFile['tmp_name']);
8✔
57

58
                return $folderToFile->newFile($data['name'] . '.' . $extension, $content);
8✔
59
        }
60

61
        /**
62
         * Process multiple uploaded files with automatic rollback on error
63
         *
64
         * @param array $filesArray Normalized array of uploaded files
65
         * @param IUser $user User who is uploading
66
         * @param array $settings Upload settings
67
         * @return list<array{fileNode: Node, name: string}>
68
         * @throws LibresignException
69
         */
70
        public function processUploadedFilesWithRollback(array $filesArray, IUser $user, array $settings): array {
71
                $processedFiles = [];
5✔
72
                $createdNodes = [];
5✔
73
                $shouldRollback = true;
5✔
74

75
                try {
76
                        foreach ($filesArray as $uploadedFile) {
5✔
77
                                $fileName = pathinfo($uploadedFile['name'], PATHINFO_FILENAME);
5✔
78

79
                                $node = $this->getNodeFromUploadedFile([
5✔
80
                                        'userManager' => $user,
5✔
81
                                        'name' => $fileName,
5✔
82
                                        'uploadedFile' => $uploadedFile,
5✔
83
                                        'settings' => $settings,
5✔
84
                                ]);
5✔
85

86
                                $createdNodes[] = $node;
5✔
87

88
                                $this->validateHelper->validateNewFile([
5✔
89
                                        'file' => ['fileId' => $node->getId()],
5✔
90
                                        'userManager' => $user,
5✔
91
                                ]);
5✔
92

93
                                $processedFiles[] = [
3✔
94
                                        'fileNode' => $node,
3✔
95
                                        'name' => $fileName,
3✔
96
                                ];
3✔
97
                        }
98

99
                        $shouldRollback = false;
3✔
100
                        return $processedFiles;
3✔
101
                } finally {
102
                        if ($shouldRollback) {
5✔
103
                                $this->rollbackCreatedNodes($createdNodes);
5✔
104
                        }
105
                }
106
        }
107

108
        /**
109
         * Validate file content based on extension
110
         *
111
         * @throws \Exception
112
         * @throws LibresignException
113
         */
114
        private function validateFileContent(string $content, string $extension): void {
115
                if ($extension === 'pdf') {
8✔
116
                        $this->pdfValidator->validate($content);
8✔
117
                }
118
        }
119

120
        /**
121
         * Rollback created nodes on error
122
         *
123
         * @param Node[] $nodes
124
         */
125
        private function rollbackCreatedNodes(array $nodes): void {
126
                foreach ($nodes as $node) {
2✔
127
                        try {
128
                                $node->delete();
2✔
129
                        } catch (\Exception $deleteError) {
1✔
130
                                $this->logger->error('Failed to rollback uploaded file', [
1✔
131
                                        'nodeId' => $node->getId(),
1✔
132
                                        'error' => $deleteError->getMessage(),
1✔
133
                                ]);
1✔
134
                        }
135
                }
136
        }
137
}
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