Passed
Pull Request — master (#77)
by Daniel
47:29
created

Plugin::checkCompatibility()   B

Complexity

Conditions 9
Paths 17

Size

Total Lines 55
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 34
c 1
b 0
f 0
dl 0
loc 55
ccs 0
cts 45
cp 0
rs 8.0555
cc 9
nc 17
nop 0
crap 90

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Model;
26
27
use OCA\CMSPico\Exceptions\PluginNotCompatibleException;
28
use OCA\CMSPico\Files\LocalFolder;
29
30
class Plugin implements \JsonSerializable
31
{
32
	/** @var int */
33
	const PLUGIN_TYPE_SYSTEM = 1;
34
35
	/** @var int */
36
	const PLUGIN_TYPE_CUSTOM = 2;
37
38
	/** @var LocalFolder */
39
	private $folder;
40
41
	/** @var int */
42
	private $type;
43
44
	/** @var bool|null */
45
	private $compat;
46
47
	/** @var PluginNotCompatibleException|null */
48
	private $compatException;
49
50
	/**
51
	 * Plugin constructor.
52
	 *
53
	 * @param LocalFolder $folder
54
	 * @param int         $type
55
	 */
56
	public function __construct(LocalFolder $folder, int $type = self::PLUGIN_TYPE_SYSTEM)
57
	{
58
		$this->folder = $folder;
59
		$this->type = $type;
60
	}
61
62
	/**
63
	 * @return string
64
	 */
65
	public function getName(): string
66
	{
67
		return $this->folder->getName();
68
	}
69
70
	/**
71
	 * @return LocalFolder
72
	 */
73
	public function getFolder(): LocalFolder
74
	{
75
		return $this->folder;
76
	}
77
78
	/**
79
	 * @return int
80
	 */
81
	public function getType(): int
82
	{
83
		return $this->type;
84
	}
85
86
	/**
87
	 * @return bool
88
	 */
89
	public function isCompatible(): bool
90
	{
91
		if ($this->compat !== null) {
92
			return $this->compat;
93
		}
94
95
		try {
96
			$this->checkCompatibility();
97
			return true;
98
		} catch (PluginNotCompatibleException $e) {
99
			return false;
100
		}
101
	}
102
103
	/**
104
	 * @throws PluginNotCompatibleException
105
	 */
106
	public function checkCompatibility()
107
	{
108
		if ($this->compat === false) {
109
			throw $this->compatException;
110
		} elseif ($this->compat) {
111
			return;
112
		}
113
114
		$includeClosure = static function (string $pluginFile) {
115
			/** @noinspection PhpIncludeInspection */
116
			require($pluginFile);
117
		};
118
119
		try {
120
			if (!is_file($this->getFolder()->getLocalPath() . '/' . $this->getName() . '.php')) {
121
				throw new PluginNotCompatibleException(
122
					$this->getName(),
123
					'Incompatible plugin: Plugin file "{file}" not found.',
124
					[ 'file' => $this->getName() . '/' . $this->getName() . '.php' ]
125
				);
126
			}
127
128
			$includeClosure($this->getFolder()->getLocalPath() . '/' . $this->getName() . '.php');
129
130
			$className = $this->getName();
131
			if (!class_exists($className, false)) {
132
				throw new PluginNotCompatibleException(
133
					$this->getName(),
134
					'Incompatible plugin: Plugin class "{class}" not found.',
135
					[ 'class' => $className ]
136
				);
137
			}
138
139
			$apiVersion = 0;
140
			if (is_a($className, \PicoPluginInterface::class, true)) {
141
				/** @noinspection PhpUndefinedFieldInspection */
142
				$apiVersion = defined($className . '::API_VERSION') ? $className::API_VERSION : 1;
143
			}
144
145
			if ($apiVersion < \Pico::API_VERSION) {
146
				throw new PluginNotCompatibleException(
147
					$this->getName(),
148
					'Incompatible plugin: Plugins for Pico CMS for Nextcloud must use API version {minApiVersion} '
149
							. 'or later, but this plugin uses API version {apiVersion}.',
150
					[ 'minApiVersion' => \Pico::API_VERSION, 'apiVersion' => $apiVersion ]
151
				);
152
			}
153
154
			$this->compat = true;
155
			$this->compatException = null;
156
		} catch (PluginNotCompatibleException $e) {
157
			$this->compat = false;
158
			$this->compatException = $e;
159
160
			throw $e;
161
		}
162
	}
163
164
	/**
165
	 * @return array
166
	 */
167
	public function toArray(): array
168
	{
169
		$data = [
170
			'name' => $this->getName(),
171
			'type' => $this->getType(),
172
			'compat' => $this->isCompatible(),
173
		];
174
175
		if (!$this->isCompatible() && ($this->compatException !== null)) {
176
			$data['compatReason'] = $this->compatException->getRawReason();
177
			$data['compatReasonData'] = $this->compatException->getRawReasonData();
178
		}
179
180
		return $data;
181
	}
182
183
	/**
184
	 * @return array
185
	 */
186
	public function jsonSerialize(): array
187
	{
188
		return $this->toArray();
189
	}
190
}
191