Passed
Push — master ( 235c52...927bab )
by Daniel
30:30 queued 10s
created

LocalFolder::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
rs 10
cc 2
nc 2
nop 2
crap 2.0625
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 */
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 6
	public function __construct(string $path, string $basePath)
51
	{
52 6
		parent::__construct($path, $basePath);
53
54 6
		if (!is_dir($this->getLocalPath())) {
55
			throw new InvalidPathException();
56
		}
57 6
	}
58
59
	/**
60
	 * {@inheritDoc}
61
	 */
62 1
	public function delete()
63
	{
64 1
		if (!$this->isDeletable()) {
65
			throw new NotPermittedException();
66
		}
67
68 1
		foreach ($this as $node) {
69 1
			$node->delete();
70
		}
71
72 1
		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 1
	}
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 4
	protected function getGenerator(): \Generator
94
	{
95 4
		if (!$this->isReadable()) {
96
			throw new NotPermittedException();
97
		}
98
99 4
		$files = @scandir($this->getLocalPath());
100 4
		if ($files === false) {
101
			throw new GenericFileException();
102
		}
103
104 4
		foreach ($files as $file) {
105 4
			if (($file === '.') || ($file === '..')) {
106 4
				continue;
107
			}
108
109 4
			$path = (($this->path !== '/') ? $this->path . '/' : '/') . $file;
110 4
			$node = $this->createNode($path);
111 4
			if ($node !== null) {
112 4
				yield $node;
113
			}
114
		}
115 4
	}
116
117
	/**
118
	 * {@inheritDoc}
119
	 */
120 6
	public function exists(string $path): bool
121
	{
122 6
		$path = $this->normalizePath($this->path . '/' . $path);
123
124 6
		return file_exists($this->basePath . $path);
125
	}
126
127
	/**
128
	 * {@inheritDoc}
129
	 */
130 6
	public function get(string $path): NodeInterface
131
	{
132 6
		if (!$this->exists($path)) {
133 1
			throw new NotFoundException();
134
		}
135
136 6
		$path = $this->normalizePath($this->path . '/' . $path);
137
138 6
		$node = $this->createNode($path);
139 6
		if ($node !== null) {
140 6
			return $node;
141
		}
142
143
		throw new NotFoundException();
144
	}
145
146
	/**
147
	 * {@inheritDoc}
148
	 */
149 1
	public function newFolder(string $path): FolderInterface
150
	{
151 1
		if ($this->exists($path)) {
152
			throw new AlreadyExistsException();
153
		}
154
155 1
		$path = $this->normalizePath($this->path . '/' . $path);
156
157 1
		$parentPath = dirname($path);
158
159 1
		if ($parentPath !== '/') {
160
			if (!$this->getBaseFolder()->exists($parentPath)) {
161
				$parentFolder = $this->getBaseFolder()->newFolder($parentPath);
162
			} else {
163
				/** @var FolderInterface $parentFolder */
164
				$parentFolder = $this->getBaseFolder()->get($parentPath);
165
				if (!$parentFolder->isFolder()) {
166
					throw new AlreadyExistsException();
167
				}
168
			}
169
		} else {
170 1
			$parentFolder = $this->getBaseFolder();
171
		}
172
173 1
		if (!$parentFolder->isCreatable()) {
174
			throw new NotPermittedException();
175
		}
176
177 1
		if (!@mkdir($this->basePath . '/' . $path)) {
178
			throw new GenericFileException();
179
		}
180
181 1
		return new LocalFolder($path, $this->basePath);
182
	}
183
184
	/**
185
	 * {@inheritDoc}
186
	 */
187 1
	public function newFile(string $path): FileInterface
188
	{
189 1
		if ($this->exists($path)) {
190
			throw new AlreadyExistsException();
191
		}
192
193 1
		$path = $this->normalizePath($this->path . '/' . $path);
194
195 1
		$parentPath = dirname($path);
196
197 1
		if ($parentPath !== '/') {
198 1
			if (!$this->getBaseFolder()->exists($parentPath)) {
199
				$parentFolder = $this->getBaseFolder()->newFolder($parentPath);
200
			} else {
201
				/** @var FolderInterface $parentFolder */
202 1
				$parentFolder = $this->getBaseFolder()->get($parentPath);
203 1
				if (!$parentFolder->isFolder()) {
204 1
					throw new AlreadyExistsException();
205
				}
206
			}
207
		} else {
208
			$parentFolder = $this->getBaseFolder();
209
		}
210
211 1
		if (!$parentFolder->isCreatable()) {
212
			throw new NotPermittedException();
213
		}
214
215 1
		if (!@touch($this->basePath . '/' . $path)) {
216
			throw new GenericFileException();
217
		}
218
219 1
		return new LocalFile($path, $this->basePath);
220
	}
221
222
	/**
223
	 * {@inheritDoc}
224
	 */
225 6
	public function fakeRoot(): FolderInterface
226
	{
227 6
		return new LocalFolder('/', $this->getLocalPath());
228
	}
229
230
	/**
231
	 * {@inheritDoc}
232
	 */
233 3
	public function sync(bool $recursive = self::SYNC_RECURSIVE)
234
	{
235
		// nothing to do
236 3
	}
237
238
	/**
239
	 * {@inheritDoc}
240
	 */
241 1
	public function isCreatable(): bool
242
	{
243 1
		return ($this->getPermissions() & Constants::PERMISSION_CREATE) === Constants::PERMISSION_CREATE;
244
	}
245
246
	/**
247
	 * @param string $path
248
	 *
249
	 * @return AbstractLocalNode|null
250
	 */
251 6
	private function createNode(string $path)
252
	{
253
		try {
254 6
			if ($path === '/') {
255
				return new LocalFolder('/', $this->basePath);
256 6
			} elseif (is_file($this->basePath . '/' . $path)) {
257 4
				return new LocalFile($path, $this->basePath);
258 6
			} elseif (is_dir($this->basePath . '/' . $path)) {
259 6
				return new LocalFolder($path, $this->basePath);
260
			}
261
262
			return null;
263
		} catch (NotFoundException $e) {
264
			return null;
265
		}
266
	}
267
268
	/**
269
	 * @return LocalFolder
270
	 */
271 1
	private function getBaseFolder(): self
272
	{
273 1
		if ($this->baseFolder === null) {
274 1
			$this->baseFolder = new LocalFolder('/', $this->basePath);
275
		}
276
277 1
		return $this->baseFolder;
278
	}
279
}
280