Passed
Pull Request — master (#167)
by Daniel
22:53
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 getBaseFolder() 0 7 2
A newFolder() 0 18 4
A fakeRoot() 0 3 1
A createNode() 0 14 5
A sync() 0 2 1
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
	private $baseFolder;
40
41
	/**
42
	 * LocalFolder constructor.
43
	 *
44
	 * @param string $path
45
	 * @param string $basePath
46
	 *
47
	 * @throws InvalidPathException
48
	 * @throws NotFoundException
49
	 */
50 16
	public function __construct(string $path, string $basePath)
51
	{
52 16
		parent::__construct($path, $basePath);
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->basePath . $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->basePath . '/' . $path)) {
163
			throw new GenericFileException();
164
		}
165
166 7
		return new LocalFolder($path, $this->basePath);
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->basePath . '/' . $path)) {
186
			throw new GenericFileException();
187
		}
188
189 7
		return new LocalFile($path, $this->basePath);
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 AbstractLocalNode|null
220
	 */
221 16
	private function createNode(string $path): ?AbstractLocalNode
222
	{
223
		try {
224 16
			if ($path === '/') {
225
				return new LocalFolder('/', $this->basePath);
226 16
			} elseif (is_file($this->basePath . '/' . $path)) {
227 13
				return new LocalFile($path, $this->basePath);
228 16
			} elseif (is_dir($this->basePath . '/' . $path)) {
229 16
				return new LocalFolder($path, $this->basePath);
230
			}
231
232
			return null;
233
		} catch (NotFoundException $e) {
234
			return null;
235
		}
236
	}
237
238
	/**
239
	 * @return LocalFolder
240
	 */
241 7
	private function getBaseFolder(): self
0 ignored issues
show
Unused Code introduced by
The method getBaseFolder() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
242
	{
243 7
		if ($this->baseFolder === null) {
244 7
			$this->baseFolder = new LocalFolder('/', $this->basePath);
245
		}
246
247 7
		return $this->baseFolder;
248
	}
249
}
250