• 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

74.7
/lib/Service/FolderService.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 OCA\Libresign\Exception\LibresignException;
12
use OCP\AppFramework\Services\IAppConfig;
13
use OCP\Files\AppData\IAppDataFactory;
14
use OCP\Files\File;
15
use OCP\Files\Folder;
16
use OCP\Files\IAppData;
17
use OCP\Files\IRootFolder;
18
use OCP\Files\Node;
19
use OCP\Files\NotFoundException;
20
use OCP\Files\NotPermittedException;
21
use OCP\IGroupManager;
22
use OCP\IL10N;
23
use OCP\IUser;
24
use OCP\Lock\LockedException;
25

26
class FolderService {
27
        protected IAppData $appData;
28
        public function __construct(
29
                private IRootFolder $root,
30
                protected IAppDataFactory $appDataFactory,
31
                protected IGroupManager $groupManager,
32
                private IAppConfig $appConfig,
33
                private IL10N $l10n,
34
                private ?string $userId,
35
        ) {
36
                $this->userId = $userId;
62✔
37
                $this->appData = $appDataFactory->get('libresign');
62✔
38
        }
39

40
        public function setUserId(string $userId): void {
41
                $this->userId = $userId;
13✔
42
        }
43

44
        public function getUserId(): ?string {
45
                return $this->userId;
19✔
46
        }
47

48
        /**
49
         * Get folder for user and creates it if non-existent
50
         *
51
         * @psalm-suppress MixedReturnStatement
52
         * @throws NotFoundException
53
         * @throws NotPermittedException
54
         * @throws LockedException
55
         */
56
        public function getFolder(): Folder {
57
                $path = $this->getLibreSignDefaultPath();
18✔
58
                $containerFolder = $this->getContainerFolder();
18✔
59
                try {
60
                        /** @var Folder $folder */
61
                        $folder = $containerFolder->get($path);
18✔
62
                } catch (NotFoundException) {
16✔
63
                        /** @var Folder $folder */
64
                        $folder = $containerFolder->newFolder($path);
16✔
65
                }
66
                return $folder;
18✔
67
        }
68

69
        /**
70
         * @throws NotFoundException
71
         */
72
        public function getFileById(?int $nodeId = null): File {
73
                if ($this->getUserId()) {
×
74

75
                        $file = $this->root->getUserFolder($this->getUserId())->getFirstNodeById($nodeId);
×
76
                        if ($file instanceof File) {
×
77
                                return $file;
×
78
                        }
79
                }
80
                $path = $this->getLibreSignDefaultPath();
×
81
                $containerFolder = $this->getContainerFolder();
×
82
                try {
83
                        /** @var Folder $folder */
84
                        $folder = $containerFolder->get($path);
×
85
                } catch (NotFoundException) {
×
86
                        throw new NotFoundException('Invalid node');
×
87
                }
88
                $file = $folder->getFirstNodeById($nodeId);
×
89
                if (!$file instanceof File) {
×
90
                        throw new NotFoundException('Invalid node');
×
91
                }
92
                return $file;
×
93
        }
94

95
        protected function getContainerFolder(): Folder {
96
                if ($this->getUserId() && !$this->groupManager->isInGroup($this->getUserId(), 'guest_app')) {
19✔
97
                        $containerFolder = $this->root->getUserFolder($this->getUserId());
18✔
98
                        if ($containerFolder->isUpdateable()) {
18✔
99
                                return $containerFolder;
18✔
100
                        }
101
                }
102
                $containerFolder = $this->appData->getFolder('/');
1✔
103
                $reflection = new \ReflectionClass($containerFolder);
1✔
104
                $reflectionProperty = $reflection->getProperty('folder');
1✔
105
                return $reflectionProperty->getValue($containerFolder);
1✔
106
        }
107

108
        private function getLibreSignDefaultPath(): string {
109
                if (!$this->userId) {
18✔
110
                        return 'unauthenticated';
×
111
                }
112
                // TODO: retrieve guest group name from app once exposed
113
                if ($this->groupManager->isInGroup($this->getUserId(), 'guest_app')) {
18✔
114
                        return 'guest_app/' . $this->getUserId();
×
115
                }
116
                $path = $this->appConfig->getUserValue($this->userId, 'folder');
18✔
117

118
                if (empty($path)) {
18✔
119
                        $defaultFolder = $this->appConfig->getAppValueString('default_user_folder', 'LibreSign');
16✔
120
                        $path = '/' . $defaultFolder;
16✔
121
                        $this->appConfig->setUserValue($this->userId, 'folder', $path);
16✔
122
                }
123

124
                return $path;
18✔
125
        }
126

127
        /**
128
         * Get or create the folder where a file should be stored
129
         *
130
         * @param array $data Must contain 'settings' and optionally 'name', 'userManager'
131
         * @param mixed $identifier User or string identifier
132
         * @return Folder The folder where files should be created
133
         * @throws LibresignException
134
         */
135
        public function getFolderForFile(array $data, $identifier): Folder {
136
                $userFolder = $this->getFolder();
17✔
137

138
                if (isset($data['settings']['envelopeFolderId'])) {
17✔
139
                        $envelopeFolder = $userFolder->getFirstNodeById($data['settings']['envelopeFolderId']);
1✔
140
                        if ($envelopeFolder === null || !$envelopeFolder instanceof Folder) {
1✔
NEW
141
                                throw new LibresignException($this->l10n->t('Envelope folder not found'));
×
142
                        }
143
                        return $envelopeFolder;
1✔
144
                }
145

146
                $folderName = $this->getFolderName($data, $identifier);
16✔
147
                return $userFolder->newFolder($folderName);
16✔
148
        }
149

150
        /**
151
         * @param array{settings: array, name: string} $data
152
         * @param IUser $owner
153
         */
154
        public function getFolderName(array $data, $identifier): string {
155
                if (isset($data['settings']['folderName'])) {
28✔
156
                        return $data['settings']['folderName'];
1✔
157
                }
158

159
                if (!isset($data['settings']['folderPatterns'])) {
27✔
160
                        $data['settings']['separator'] = '_';
7✔
161
                        $data['settings']['folderPatterns'][] = [
7✔
162
                                'name' => 'date',
7✔
163
                                'setting' => 'Y-m-d\TH-i-s-u'
7✔
164
                        ];
7✔
165
                        $data['settings']['folderPatterns'][] = [
7✔
166
                                'name' => 'name'
7✔
167
                        ];
7✔
168
                        $data['settings']['folderPatterns'][] = [
7✔
169
                                'name' => 'userId'
7✔
170
                        ];
7✔
171
                }
172
                $folderName = [];
27✔
173
                foreach ($data['settings']['folderPatterns'] as $pattern) {
27✔
174
                        switch ($pattern['name']) {
27✔
175
                                case 'date':
27✔
176
                                        $folderName[] = (new \DateTime('now', new \DateTimeZone('UTC')))->format($pattern['setting']);
23✔
177
                                        break;
23✔
178
                                case 'name':
26✔
179
                                        if (!empty($data['name'])) {
25✔
180
                                                $folderName[] = $data['name'];
23✔
181
                                        }
182
                                        break;
25✔
183
                                case 'userId':
25✔
184
                                        if ($identifier instanceof \OCP\IUser) {
24✔
185
                                                $folderName[] = $identifier->getUID();
24✔
186
                                        } else {
187
                                                $folderName[] = $identifier;
×
188
                                        }
189
                                        break;
24✔
190
                        }
191
                }
192
                return implode($data['settings']['separator'], $folderName);
27✔
193
        }
194

195
        public function getFileByPath(string $path): Node {
196
                $userFolder = $this->root->getUserFolder($this->getUserId());
×
197
                try {
198
                        return $userFolder->get($path);
×
199
                } catch (NotFoundException) {
×
200
                        throw new LibresignException($this->l10n->t('Invalid data to validate file'), 404);
×
201
                }
202
        }
203
}
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