Passed
Push — master ( 4bdb47...6c7738 )
by Daniel
25:23 queued 10s
created

LocalFolder   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Test Coverage

Coverage 74.7%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 39
eloc 71
c 3
b 0
f 0
dl 0
loc 214
ccs 62
cts 83
cp 0.747
rs 9.28

13 Methods

Rating   Name   Duplication   Size   Complexity  
A listing() 0 3 1
B getGenerator() 0 20 8
A __construct() 0 6 2
A exists() 0 5 1
A delete() 0 16 6
A get() 0 14 3
A newFile() 0 18 4
A isCreatable() 0 3 1
A newFolder() 0 18 4
A fakeRoot() 0 3 1
A createNode() 0 14 5
A sync() 0 2 1
A getRootFolder() 0 7 2
1
<?php
2
/**
3
 * CMS Pico - Create websites using Pico CMS for Nextcloud.
4
 *
5
 * @copyright Copyright (c) 2019, Daniel Rudolf (<[email protected]>)
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
declare(strict_types=1);
24
25
namespace OCA\CMSPico\Files;
26
27
use OCP\Constants;
28
use OCP\Files\AlreadyExistsException;
29
use OCP\Files\GenericFileException;
30
use OCP\Files\InvalidPathException;
31
use OCP\Files\NotFoundException;
32
use OCP\Files\NotPermittedException;
33
34
class LocalFolder extends AbstractLocalNode implements FolderInterface
35
{
36
	use FolderTrait;
37
38
	/** @var LocalFolder|null */
39
	protected $rootFolder;
40
41
	/**
42
	 * LocalFolder constructor.
43
	 *
44
	 * @param string      $path
45
	 * @param string|null $rootPath
46
	 *
47
	 * @throws InvalidPathException
48
	 * @throws NotFoundException
49
	 */
50 16
	public function __construct(string $path, string $rootPath = null)
51
	{
52 16
		parent::__construct($path, $rootPath);
53
54 16
		if (!is_dir($this->getLocalPath())) {
55
			throw new InvalidPathException();
56
		}
57 16
	}
58
59
	/**
60
	 * {@inheritDoc}
61
	 */
62 4
	public function delete(): void
63
	{
64 4
		if (!$this->isDeletable()) {
65
			throw new NotPermittedException();
66
		}
67
68 4
		foreach ($this as $node) {
69 4
			$node->delete();
70
		}
71
72 4
		if (!@rmdir($this->getLocalPath())) {
73
			$files = @scandir($this->getLocalPath());
74
			if (($files === false) || ($files === [ '.', '..' ])) {
75
				throw new GenericFileException();
76
			} else {
77
				throw new NotPermittedException();
78
			}
79
		}
80 4
	}
81
82
	/**
83
	 * {@inheritDoc}
84
	 */
85
	public function listing(): array
86
	{
87
		return iterator_to_array($this->getGenerator());
88
	}
89
90
	/**
91
	 * {@inheritDoc}
92
	 */
93 9
	protected function getGenerator(): \Generator
94
	{
95 9
		if (!$this->isReadable()) {
96
			throw new NotPermittedException();
97
		}
98
99 9
		$files = @scandir($this->getLocalPath());
100 9
		if ($files === false) {
101
			throw new GenericFileException();
102
		}
103
104 9
		foreach ($files as $file) {
105 9
			if (($file === '.') || ($file === '..')) {
106 9
				continue;
107
			}
108
109 9
			$path = (($this->path !== '/') ? $this->path . '/' : '/') . $file;
110 9
			$node = $this->createNode($path);
111 9
			if ($node !== null) {
112 9
				yield $node;
113
			}
114
		}
115 9
	}
116
117
	/**
118
	 * {@inheritDoc}
119
	 */
120 16
	public function exists(string $path): bool
121
	{
122 16
		$path = $this->normalizePath($this->path . '/' . $path);
123
124 16
		return file_exists($this->rootPath . $path);
125
	}
126
127
	/**
128
	 * {@inheritDoc}
129
	 */
130 16
	public function get(string $path): NodeInterface
131
	{
132 16
		if (!$this->exists($path)) {
133 7
			throw new NotFoundException();
134
		}
135
136 16
		$path = $this->normalizePath($this->path . '/' . $path);
137
138 16
		$node = $this->createNode($path);
139 16
		if ($node !== null) {
140 16
			return $node;
141
		}
142
143
		throw new NotFoundException();
144
	}
145
146
	/**
147
	 * {@inheritDoc}
148
	 */
149 7
	public function newFolder(string $path): FolderInterface
150
	{
151 7
		if ($this->exists($path)) {
152
			throw new AlreadyExistsException();
153
		}
154
155 7
		$path = $this->normalizePath($this->path . '/' . $path);
156 7
		$parentFolder = $this->newFolderRecursive(dirname($path));
157
158 7
		if (!$parentFolder->isCreatable()) {
159
			throw new NotPermittedException();
160
		}
161
162 7
		if (!@mkdir($this->rootPath . '/' . $path)) {
163
			throw new GenericFileException();
164
		}
165
166 7
		return new LocalFolder($path, $this->rootPath);
167
	}
168
169
	/**
170
	 * {@inheritDoc}
171
	 */
172 7
	public function newFile(string $path): FileInterface
173
	{
174 7
		if ($this->exists($path)) {
175
			throw new AlreadyExistsException();
176
		}
177
178 7
		$path = $this->normalizePath($this->path . '/' . $path);
179 7
		$parentFolder = $this->newFolderRecursive(dirname($path));
180
181 7
		if (!$parentFolder->isCreatable()) {
182
			throw new NotPermittedException();
183
		}
184
185 7
		if (!@touch($this->rootPath . '/' . $path)) {
186
			throw new GenericFileException();
187
		}
188
189 7
		return new LocalFile($path, $this->rootPath);
190
	}
191
192
	/**
193
	 * {@inheritDoc}
194
	 */
195 16
	public function fakeRoot(): FolderInterface
196
	{
197 16
		return new LocalFolder('/', $this->getLocalPath());
198
	}
199
200
	/**
201
	 * {@inheritDoc}
202
	 */
203 4
	public function sync(bool $recursive = self::SYNC_RECURSIVE): void
204
	{
205
		// nothing to do
206 4
	}
207
208
	/**
209
	 * {@inheritDoc}
210
	 */
211 7
	public function isCreatable(): bool
212
	{
213 7
		return ($this->getPermissions() & Constants::PERMISSION_CREATE) === Constants::PERMISSION_CREATE;
214
	}
215
216
	/**
217
	 * @param string $path
218
	 *
219
	 * @return LocalFolder|LocalFile|null
220
	 */
221 16
	protected function createNode(string $path): ?AbstractLocalNode
222
	{
223
		try {
224 16
			if ($path === '/') {
225
				return new LocalFolder('/', $this->rootPath);
226 16
			} elseif (is_file($this->rootPath . '/' . $path)) {
227 13
				return new LocalFile($path, $this->rootPath);
228 16
			} elseif (is_dir($this->rootPath . '/' . $path)) {
229 16
				return new LocalFolder($path, $this->rootPath);
230
			}
231
232
			return null;
233
		} catch (NotFoundException $e) {
234
			return null;
235
		}
236
	}
237
238
	/**
239
	 * {@inheritDoc}
240
	 */
241 7
	protected function getRootFolder(): self
242
	{
243 7
		if ($this->rootFolder === null) {
244 7
			$this->rootFolder = new LocalFolder('/', $this->rootPath);
245
		}
246
247 7
		return $this->rootFolder;
248
	}
249
}
250