Test Failed
Push — master ( 0beeeb...19c15a )
by Daniel
23:53
created

Website::getTimeZone()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * CMS Pico - Create websites using Pico CMS for Nextcloud.
4
 *
5
 * @copyright Copyright (c) 2017, Maxence Lange (<[email protected]>)
6
 * @copyright Copyright (c) 2019, Daniel Rudolf (<[email protected]>)
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
declare(strict_types=1);
25
26
namespace OCA\CMSPico\Model;
27
28
use OCA\CMSPico\AppInfo\Application;
29
use OCA\CMSPico\Exceptions\TemplateNotCompatibleException;
30
use OCA\CMSPico\Exceptions\TemplateNotFoundException;
31
use OCA\CMSPico\Exceptions\ThemeNotCompatibleException;
32
use OCA\CMSPico\Exceptions\ThemeNotFoundException;
33
use OCA\CMSPico\Exceptions\WebsiteForeignOwnerException;
34
use OCA\CMSPico\Exceptions\WebsiteInvalidDataException;
35
use OCA\CMSPico\Exceptions\WebsiteInvalidFilesystemException;
36
use OCA\CMSPico\Exceptions\WebsiteInvalidOwnerException;
37
use OCA\CMSPico\Files\StorageFolder;
38
use OCA\CMSPico\Service\MiscService;
39
use OCA\CMSPico\Service\TemplatesService;
40
use OCA\CMSPico\Service\ThemesService;
41
use OCA\CMSPico\Service\WebsitesService;
42
use OCP\Files\InvalidPathException;
43
use OCP\Files\NotFoundException;
44
use OCP\IConfig;
45
use OCP\IL10N;
46
use OCP\IURLGenerator;
47
use OCP\IUserManager;
48
49
class Website extends WebsiteCore
50
{
51
	/** @var int */
52
	public const SITE_LENGTH_MIN = 3;
53
54
	/** @var int */
55
	public const SITE_LENGTH_MAX = 255;
56
57
	/** @var string */
58
	public const SITE_REGEX = '^[a-z0-9][a-z0-9_-]+[a-z0-9]$';
59
60
	/** @var int */
61
	public const NAME_LENGTH_MIN = 3;
62
63
	/** @var int */
64
	public const NAME_LENGTH_MAX = 255;
65
66
	/** @var IConfig */
67
	private $config;
68
69
	/** @var IL10N */
70
	private $l10n;
71
72
	/** @var IUserManager */
73
	private $userManager;
74
75
	/** @var IURLGenerator */
76
	private $urlGenerator;
77
78
	/** @var WebsitesService */
79
	private $websitesService;
80
81
	/** @var ThemesService */
82
	private $themesService;
83
84
	/** @var TemplatesService */
85
	private $templatesService;
86
87
	/** @var MiscService */
88
	private $miscService;
89
90
	/** @var StorageFolder */
91
	private $folder;
92
93
	/**
94
	 * Website constructor.
95
	 *
96
	 * @param array|string|null $data
97
	 */
98
	public function __construct($data = null)
99
	{
100
		$this->config = \OC::$server->getConfig();
0 ignored issues
show
Deprecated Code introduced by
The function OC\Server::getConfig() has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

100
		$this->config = /** @scrutinizer ignore-deprecated */ \OC::$server->getConfig();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
101
		$this->l10n = \OC::$server->getL10N(Application::APP_NAME);
0 ignored issues
show
Deprecated Code introduced by
The function OC\Server::getL10N() has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

101
		$this->l10n = /** @scrutinizer ignore-deprecated */ \OC::$server->getL10N(Application::APP_NAME);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
102
		$this->userManager = \OC::$server->getUserManager();
0 ignored issues
show
Deprecated Code introduced by
The function OC\Server::getUserManager() has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

102
		$this->userManager = /** @scrutinizer ignore-deprecated */ \OC::$server->getUserManager();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
103
		$this->urlGenerator = \OC::$server->getURLGenerator();
0 ignored issues
show
Deprecated Code introduced by
The function OC\Server::getURLGenerator() has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

103
		$this->urlGenerator = /** @scrutinizer ignore-deprecated */ \OC::$server->getURLGenerator();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
104
		$this->websitesService = \OC::$server->query(WebsitesService::class);
1 ignored issue
show
Documentation Bug introduced by
It seems like OC::server->query(OCA\CM...WebsitesService::class) can also be of type stdClass. However, the property $websitesService is declared as type OCA\CMSPico\Service\WebsitesService. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
105
		$this->themesService = \OC::$server->query(ThemesService::class);
1 ignored issue
show
Documentation Bug introduced by
It seems like OC::server->query(OCA\CM...e\ThemesService::class) can also be of type stdClass. However, the property $themesService is declared as type OCA\CMSPico\Service\ThemesService. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
106
		$this->templatesService = \OC::$server->query(TemplatesService::class);
1 ignored issue
show
Documentation Bug introduced by
It seems like OC::server->query(OCA\CM...emplatesService::class) can also be of type stdClass. However, the property $templatesService is declared as type OCA\CMSPico\Service\TemplatesService. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
107 3
		$this->miscService = \OC::$server->query(MiscService::class);
1 ignored issue
show
Documentation Bug introduced by
It seems like OC::server->query(OCA\CM...ice\MiscService::class) can also be of type stdClass. However, the property $miscService is declared as type OCA\CMSPico\Service\MiscService. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
108
109 3
		parent::__construct($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type string; however, parameter $data of OCA\CMSPico\Model\WebsiteCore::__construct() does only seem to accept array|null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

109
		parent::__construct(/** @scrutinizer ignore-type */ $data);
Loading history...
110 3
	}
111 3
112 3
	/**
113 3
	 * @return string
114 3
	 */
115 3
	public function getTimeZone(): string
116 3
	{
117 3
		$serverTimeZone = date_default_timezone_get() ?: 'UTC';
118
		return $this->config->getUserValue($this->getUserId(), 'core', 'timezone', $serverTimeZone);
119 3
	}
120 3
121
	/**
122
	 * @throws WebsiteInvalidOwnerException
123
	 */
124
	public function assertValidOwner(): void
125
	{
126
		$user = $this->userManager->get($this->getUserId());
127
		if ($user === null) {
128
			throw new WebsiteInvalidOwnerException();
129
		}
130
		if (!$user->isEnabled()) {
131
			throw new WebsiteInvalidOwnerException();
132
		}
133
		if (!$this->websitesService->isUserAllowed($this->getUserId())) {
134
			throw new WebsiteInvalidOwnerException();
135
		}
136
	}
137
138
	/**
139
	 * @throws WebsiteInvalidDataException
140
	 */
141
	public function assertValidName(): void
142
	{
143
		if (strlen($this->getName()) < self::NAME_LENGTH_MIN) {
144
			throw new WebsiteInvalidDataException('name', $this->l10n->t('The name of the website must be longer.'));
145
		}
146
		if (strlen($this->getName()) > self::NAME_LENGTH_MAX) {
147
			throw new WebsiteInvalidDataException('name', $this->l10n->t('The name of the website is too long.'));
148
		}
149
	}
150
151
	/**
152
	 * @throws WebsiteInvalidDataException
153
	 */
154
	public function assertValidSite(): void
155
	{
156
		if (strlen($this->getSite()) < self::SITE_LENGTH_MIN) {
157
			$error = $this->l10n->t('The identifier of the website must be longer.');
158
			throw new WebsiteInvalidDataException('site', $error);
159
		}
160
		if (strlen($this->getSite()) > self::SITE_LENGTH_MAX) {
161
			$error = $this->l10n->t('The identifier of the website is too long.');
162
			throw new WebsiteInvalidDataException('site', $error);
163
		}
164
		if (preg_match('/' . self::SITE_REGEX . '/', $this->getSite()) !== 1) {
165
			$error = $this->l10n->t('The identifier of the website can only contain lowercase alpha numeric chars.');
166
			throw new WebsiteInvalidDataException('site', $error);
167
		}
168
	}
169
170
	/**
171
	 * @throws WebsiteInvalidDataException
172
	 */
173
	public function assertValidPath(): void
174
	{
175
		try {
176
			$path = $this->miscService->normalizePath($this->getPath());
177
			if ($path === '') {
178
				throw new InvalidPathException();
179
			}
180
		} catch (InvalidPathException $e) {
181
			throw new WebsiteInvalidDataException(
182
				'path',
183
				$this->l10n->t('The path of the website is invalid.')
184
			);
185
		}
186
187
		$userFolder = new StorageFolder(\OC::$server->getUserFolder($this->getUserId()));
0 ignored issues
show
Deprecated Code introduced by
The function OC\Server::getUserFolder() has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

187
		$userFolder = new StorageFolder(/** @scrutinizer ignore-deprecated */ \OC::$server->getUserFolder($this->getUserId()));

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
188
189
		try {
190
			$websiteBaseFolder = $userFolder->getFolder(dirname($path));
191
192
			try {
193
				$websiteFolder = $websiteBaseFolder->getFolder(basename($path));
194
195
				if (!$websiteFolder->isLocal()) {
196
					throw new WebsiteInvalidDataException(
197
						'path',
198
						$this->l10n->t('The website\'s path is stored on a non-local storage.')
199
					);
200
				}
201
			} catch (NotFoundException $e) {
202
				if (!$websiteBaseFolder->isLocal()) {
203
					throw new WebsiteInvalidDataException(
204
						'path',
205
						$this->l10n->t('The website\'s path is stored on a non-local storage.')
206
					);
207
				}
208
			}
209
		} catch (InvalidPathException | NotFoundException $e) {
210
			throw new WebsiteInvalidDataException(
211
				'path',
212
				$this->l10n->t('Parent folder of the website\'s path not found.')
213
			);
214
		}
215
	}
216
217
	/**
218
	 * @throws ThemeNotFoundException
219
	 * @throws ThemeNotCompatibleException
220
	 */
221
	public function assertValidTheme(): void
222
	{
223
		$this->themesService->assertValidTheme($this->getTheme());
224
	}
225 3
226
	/**
227 3
	 * @throws TemplateNotFoundException
228 3
	 * @throws TemplateNotCompatibleException
229
	 */
230
	public function assertValidTemplate(): void
231 3
	{
232
		$this->templatesService->assertValidTemplate($this->getTemplateSource());
0 ignored issues
show
Bug introduced by
It seems like $this->getTemplateSource() can also be of type null; however, parameter $templateName of OCA\CMSPico\Service\Temp...::assertValidTemplate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

232
		$this->templatesService->assertValidTemplate(/** @scrutinizer ignore-type */ $this->getTemplateSource());
Loading history...
233
	}
234 3
235
	/**
236
	 * @param string $userId
237 3
	 *
238
	 * @throws WebsiteForeignOwnerException
239
	 */
240
	public function assertOwnedBy(string $userId): void
241
	{
242 3
		if ($this->getUserId() !== $userId) {
243
			throw new WebsiteForeignOwnerException();
244 3
		}
245
	}
246
247 3
	/**
248
	 * @return StorageFolder
249
	 * @throws WebsiteInvalidFilesystemException
250 3
	 */
251
	public function getWebsiteFolder(): StorageFolder
252
	{
253
		if ($this->folder !== null) {
254
			try {
255 3
				// NC doesn't guarantee that mounts are present for the whole request lifetime
256
				// for example, if you call \OC\Files\Utils\Scanner::scan(), all mounts are reset
257 3
				// this makes OCNode instances, which rely on mounts of different users than the current, unusable
258
				// by calling OCFolder::get('') we can detect this situation and re-init the required mounts
259
				$this->folder->get('');
260
			} catch (\Exception $e) {
261 3
				$this->folder = null;
262
			}
263
		}
264
265 3
		if ($this->folder === null) {
266
			try {
267
				$ocUserFolder = \OC::$server->getUserFolder($this->getUserId());
0 ignored issues
show
Deprecated Code introduced by
The function OC\Server::getUserFolder() has been deprecated: 20.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

267
				$ocUserFolder = /** @scrutinizer ignore-deprecated */ \OC::$server->getUserFolder($this->getUserId());

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
268
				$userFolder = new StorageFolder($ocUserFolder);
269 3
270
				$websiteFolder = $userFolder->getFolder($this->getPath());
271
				$this->folder = $websiteFolder->fakeRoot();
272
			} catch (InvalidPathException | NotFoundException $e) {
273
				throw new WebsiteInvalidFilesystemException($e);
274 3
			}
275
		}
276
277 3
		return $this->folder;
278 3
	}
279 3
280
	/**
281
	 * @return string
282
	 * @throws WebsiteInvalidFilesystemException
283
	 */
284
	public function getWebsitePath(): string
285
	{
286
		try {
287
			return $this->getWebsiteFolder()->getLocalPath() . '/';
288 3
		} catch (InvalidPathException | NotFoundException $e) {
289
			throw new WebsiteInvalidFilesystemException($e);
290
		}
291 3
	}
292
293
	/**
294 3
	 * @return string
295
	 */
296
	public function getWebsiteUrl(bool $proxyRequest = false): string
297
	{
298
		if (!$proxyRequest) {
299
			$route = Application::APP_NAME . '.Pico.getPage';
300
			$parameters = [ 'site' => $this->getSite(), 'page' => '' ];
301
			return $this->urlGenerator->linkToRoute($route, $parameters) . '/';
302 3
		} else {
303 3
			return \OC::$WEBROOT . '/sites/' . urlencode($this->getSite()) . '/';
304
		}
305
	}
306
}
307