Completed
Push — master ( a5882f...67b08d )
by Maxence
01:27 queued 01:22
created

InterfaceService::isCurrentInterfaceInternal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
6
/**
7
 * Circles - Bring cloud-users closer together.
8
 *
9
 * This file is licensed under the Affero General Public License version 3 or
10
 * later. See the COPYING file.
11
 *
12
 * @author Maxence Lange <[email protected]>
13
 * @copyright 2021
14
 * @license GNU AGPL version 3 or any later version
15
 *
16
 * This program is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License as
18
 * published by the Free Software Foundation, either version 3 of the
19
 * License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28
 *
29
 */
30
31
32
namespace OCA\Circles\Service;
33
34
35
use daita\MySmallPhpTools\Traits\TArrayTools;
36
use daita\MySmallPhpTools\Traits\TStringTools;
37
use OCA\Circles\Db\RemoteRequest;
38
use OCA\Circles\Exceptions\RemoteNotFoundException;
39
use OCA\Circles\Exceptions\UnknownInterfaceException;
40
use OCP\IRequest;
41
use OCP\IURLGenerator;
42
43
44
/**
45
 * Class InterfaceService
46
 *
47
 * @package OCA\Circles\Service
48
 */
49
class InterfaceService {
50
51
	const IFACE0 = 1;
52
	const IFACE1 = 2;
53
	const IFACE2 = 3;
54
	const IFACE3 = 4;
55
	const IFACE4 = 5;
56
	const IFACE_INTERNAL = 6;
57
	const IFACE_FRONTAL = 7;
58
	const IFACE_TEST = 99;
59
60
	public static $LIST_IFACE = [
61
		self::IFACE_INTERNAL => 'internal',
62
		self::IFACE_FRONTAL  => 'frontal',
63
		self::IFACE0         => 'iface0',
64
		self::IFACE1         => 'iface1',
65
		self::IFACE2         => 'iface2',
66
		self::IFACE3         => 'iface3',
67
		self::IFACE4         => 'iface4',
68
	];
69
70
71
	use TStringTools;
72
	use TArrayTools;
73
74
75
	/** @var IURLGenerator */
76
	private $urlGenerator;
77
78
	/** @var RemoteRequest */
79
	private $remoteRequest;
80
81
	/** @var ConfigService */
82
	private $configService;
83
84
85
	/** @var int */
86
	private $currentInterface = 0;
87
88
	/** @var int */
89
	private $outgoingInterface = 0;
90
91
92
	/**
93
	 * InterfaceService constructor.
94
	 *
95
	 * @param IURLGenerator $urlGenerator
96
	 * @param RemoteRequest $remoteRequest
97
	 * @param ConfigService $configService
98
	 */
99
	public function __construct(
100
		IURLGenerator $urlGenerator,
101
		RemoteRequest $remoteRequest,
102
		ConfigService $configService
103
	) {
104
		$this->urlGenerator = $urlGenerator;
105
		$this->remoteRequest = $remoteRequest;
106
		$this->configService = $configService;
107
	}
108
109
110
	/**
111
	 * @param int $interface
112
	 */
113
	public function setCurrentInterface(int $interface): void {
114
		$this->currentInterface = $interface;
115
	}
116
117
	/**
118
	 * @return int
119
	 * @throws UnknownInterfaceException
120
	 */
121
	public function getCurrentInterface(): int {
122
		if ($this->currentInterface === 0) {
123
			throw new UnknownInterfaceException('interface not initialized');
124
		}
125
126
		return $this->currentInterface;
127
	}
128
129
	/**
130
	 * @return bool
131
	 */
132
	public function hasCurrentInterface(): bool {
133
		return ($this->currentInterface !== 0);
134
	}
135
136
137
	/**
138
	 * @return bool
139
	 * @throws UnknownInterfaceException
140
	 */
141
	public function isCurrentInterfaceInternal(): bool {
142
		return $this->isInterfaceInternal($this->getCurrentInterface());
143
	}
144
145
	/**
146
	 * @param int $interface
147
	 *
148
	 * @return bool
149
	 */
150
	public function isInterfaceInternal(int $interface): bool {
151
		if ($interface === self::IFACE_INTERNAL) {
152
			return true;
153
		}
154
155
		switch ($interface) {
156
			case self::IFACE0:
157
				return $this->configService->getAppValueBool(ConfigService::IFACE0_INTERNAL);
158
			case self::IFACE1:
159
				return $this->configService->getAppValueBool(ConfigService::IFACE1_INTERNAL);
160
			case self::IFACE2:
161
				return $this->configService->getAppValueBool(ConfigService::IFACE2_INTERNAL);
162
			case self::IFACE3:
163
				return $this->configService->getAppValueBool(ConfigService::IFACE3_INTERNAL);
164
			case self::IFACE4:
165
				return $this->configService->getAppValueBool(ConfigService::IFACE4_INTERNAL);
166
		}
167
168
		return false;
169
	}
170
171
172
	/**
173
	 * @param IRequest $request
174
	 * @param string $testToken
175
	 */
176
	public function setCurrentInterfaceFromRequest(IRequest $request, string $testToken = ''): void {
177
		$testing = [
178
			self::IFACE_INTERNAL => $this->configService->getInternalInstance(),
179
			self::IFACE_FRONTAL  => $this->configService->getFrontalInstance(),
180
			self::IFACE0         => $this->configService->getIfaceInstance(self::IFACE0),
181
			self::IFACE1         => $this->configService->getIfaceInstance(self::IFACE1),
182
			self::IFACE2         => $this->configService->getIfaceInstance(self::IFACE2),
183
			self::IFACE3         => $this->configService->getIfaceInstance(self::IFACE3),
184
			self::IFACE4         => $this->configService->getIfaceInstance(self::IFACE4),
185
		];
186
187
		if ($testToken !== ''
188
			&& $testToken === $this->configService->getAppValue(ConfigService::IFACE_TEST_TOKEN)) {
189
			$testing[self::IFACE_TEST] = $this->getTestingInstance();
190
		}
191
192
		$serverHost = strtolower($request->getServerHost());
193
		if ($serverHost === '') {
194
			return;
195
		}
196
197
		foreach ($testing as $iface => $instance) {
198
			if ($serverHost === strtolower($instance)) {
199
				$this->setCurrentInterface($iface);
200
201
				return;
202
			}
203
		}
204
	}
205
206
207
	/**
208
	 * @param string $instance
209
	 *
210
	 * @return int
211
	 * @throws RemoteNotFoundException
212
	 */
213
	public function getInterfaceFromInstance(string $instance): int {
214
		$remoteInstance = $this->remoteRequest->getFromInstance($instance);
215
216
		return $remoteInstance->getInterface();
217
	}
218
219
	/**
220
	 *
221
	 */
222
	public function setCurrentInterfaceFromInstance(string $instance): void {
223
		try {
224
			$this->setCurrentInterface($this->getInterfaceFromInstance($instance));
225
		} catch (RemoteNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
226
		}
227
	}
228
229
230
	/**
231
	 * @param bool $useString
232
	 *
233
	 * @return array
234
	 */
235
	public function getInterfaces(bool $useString = false): array {
236
		$interfaces = [
237
			self::IFACE_INTERNAL => $this->configService->getInternalInstance(),
238
			self::IFACE_FRONTAL  => $this->configService->getFrontalInstance(),
239
			self::IFACE0         => $this->configService->getIfaceInstance(InterfaceService::IFACE0),
240
			self::IFACE1         => $this->configService->getIfaceInstance(InterfaceService::IFACE1),
241
			self::IFACE2         => $this->configService->getIfaceInstance(InterfaceService::IFACE2),
242
			self::IFACE3         => $this->configService->getIfaceInstance(InterfaceService::IFACE3),
243
			self::IFACE4         => $this->configService->getIfaceInstance(InterfaceService::IFACE4)
244
		];
245
246
		if (!$useString) {
247
			return $interfaces;
248
		}
249
250
		$detailed = [];
251
		foreach ($interfaces as $id => $iface) {
252
			$detailed[self::$LIST_IFACE[$id]] = $iface;
253
		}
254
255
		return $detailed;
256
	}
257
258
259
	/**
260
	 * @param bool $useString
261
	 *
262
	 * @return array
263
	 */
264
	public function getInternalInterfaces(bool $useString = false): array {
265
		$interfaces = $this->getInterfaces(false);
266
		$internalInterfaces = [];
267
268
		foreach ($interfaces as $id => $iface) {
269
			if (!$this->isInterfaceInternal($id)) {
270
				continue;
271
			}
272
273
			$internalInterfaces[$id] = $iface;
274
		}
275
276
		if (!$useString) {
277
			return $internalInterfaces;
278
		}
279
280
		$detailed = [];
281
		foreach ($internalInterfaces as $id => $iface) {
282
			$detailed[self::$LIST_IFACE[$id]] = $iface;
283
		}
284
285
		return $detailed;
286
	}
287
288
289
	/**
290
	 * use this only if interface must be defined. If not, use getLocalInstance()
291
	 *
292
	 * @throws UnknownInterfaceException
293
	 */
294
	public function getCloudInstance(): string {
295
		switch ($this->getCurrentInterface()) {
296
			case self::IFACE_INTERNAL:
297
				return $this->configService->getInternalInstance();
298
			case self::IFACE_FRONTAL:
299
				return $this->configService->getFrontalInstance();
300
			case self::IFACE0:
301
			case self::IFACE1:
302
			case self::IFACE2:
303
			case self::IFACE3:
304
			case self::IFACE4:
305
				return $this->configService->getIfaceInstance($this->getCurrentInterface());
306
			case self::IFACE_TEST:
307
				return $this->getTestingInstance();
308
		}
309
310
		throw new UnknownInterfaceException('unknown configured interface');
311
	}
312
313
314
	/**
315
	 * @throws UnknownInterfaceException
316
	 */
317
	public function getCloudPath(string $route = '', array $args = []): string {
318
		$scheme = '';
319
		switch ($this->getCurrentInterface()) {
320
			case self::IFACE_INTERNAL:
321
				$scheme = $this->configService->getAppValue(ConfigService::INTERNAL_CLOUD_SCHEME);
322
				break;
323
			case self::IFACE_FRONTAL:
324
				$scheme = $this->configService->getAppValue(ConfigService::FRONTAL_CLOUD_SCHEME);
325
				break;
326
			case self::IFACE0:
327
				$scheme = $this->configService->getAppValue(ConfigService::IFACE0_CLOUD_SCHEME);
328
				break;
329
			case self::IFACE1:
330
				$scheme = $this->configService->getAppValue(ConfigService::IFACE1_CLOUD_SCHEME);
331
				break;
332
			case self::IFACE2:
333
				$scheme = $this->configService->getAppValue(ConfigService::IFACE2_CLOUD_SCHEME);
334
				break;
335
			case self::IFACE3:
336
				$scheme = $this->configService->getAppValue(ConfigService::IFACE3_CLOUD_SCHEME);
337
				break;
338
			case self::IFACE4:
339
				$scheme = $this->configService->getAppValue(ConfigService::IFACE4_CLOUD_SCHEME);
340
				break;
341
			case self::IFACE_TEST:
342
				$scheme = $this->configService->getAppValue(ConfigService::IFACE_TEST_SCHEME);
343
				break;
344
		}
345
346
		if ($scheme === '') {
347
			throw new UnknownInterfaceException('misconfigured scheme');
348
		}
349
350
		$base = $scheme . '://' . $this->getCloudInstance();
351
352
		if ($route === '') {
353
			return $base;
354
		}
355
356
		return $base . $this->urlGenerator->linkToRoute($route, $args);
357
	}
358
359
360
	/**
361
	 * should be used when unsure about the used Interface
362
	 *
363
	 * @return string
364
	 */
365
	public function getLocalInstance(): string {
366
		if ($this->hasCurrentInterface()) {
367
			try {
368
				return $this->getCloudInstance();
369
			} catch (UnknownInterfaceException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
370
			}
371
		}
372
373
		return $this->configService->getLoopbackInstance();
374
	}
375
376
377
	/**
378
	 * @return string
379
	 */
380
	private function getTestingInstance(): string {
381
		return $this->configService->getAppValue(ConfigService::IFACE_TEST_ID);
382
	}
383
384
}
385
386