Passed
Pull Request — master (#640)
by Vitor
03:36
created

AFactory::getFqcnList()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
dl 0
loc 20
rs 9.2222
c 1
b 0
f 0
cc 6
nc 6
nop 0
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8
9
namespace OCA\TwoFactorGateway\Provider;
10
11
abstract class AFactory {
12
	/** @var array<string,object> */
13
	protected array $instances = [];
14
	/** @var array<string> */
15
	protected array $fqcn = [];
16
17
	abstract protected function getPrefix(): string;
18
	abstract protected function getSuffix(): string;
19
	abstract protected function getBaseClass(): string;
20
21
	public function isValid(string $fqcn): bool {
22
		return true;
23
	}
24
25
	public function get(string $name): object {
26
		$needle = strtolower($name);
27
		if (isset($this->instances[$needle])) {
28
			return $this->instances[$needle];
29
		}
30
31
		foreach ($this->getFqcnList() as $fqcn) {
32
			$type = $this->typeFrom($fqcn);
33
			if ($type !== $needle) {
34
				continue;
35
			}
36
			$instance = \OCP\Server::get($fqcn);
37
			$this->instances[$needle] = $instance;
38
			return $instance;
39
		}
40
41
		throw new \InvalidArgumentException("Invalid type <$name>");
42
	}
43
44
	/** @return array<string> */
45
	public function getFqcnList(): array {
46
		if (!empty($this->fqcn)) {
47
			return $this->fqcn;
48
		}
49
50
		$loader = require __DIR__ . '/../../vendor/autoload.php';
51
		foreach ($loader->getClassMap() as $fqcn => $_) {
52
			$type = $this->typeFrom($fqcn);
53
			if ($type === null) {
54
				continue;
55
			}
56
			if (!is_subclass_of($fqcn, $this->getBaseClass(), true)) {
57
				continue;
58
			}
59
			if (!$this->isValid($fqcn)) {
60
				continue;
61
			}
62
			$this->fqcn[] = $fqcn;
63
		}
64
		return $this->fqcn;
65
	}
66
67
	protected function typeFrom(string $fqcn): ?string {
68
		$prefix = $this->getPrefix();
69
		if (strncmp($fqcn, $prefix, strlen($prefix)) !== 0) {
70
			return null;
71
		}
72
		$suffix = $this->getSuffix();
73
		if (!str_ends_with($fqcn, $suffix)) {
74
			return null;
75
		}
76
		$type = substr($fqcn, strlen($prefix));
77
		$type = substr($type, 0, -strlen('\\' . $suffix));
78
		if (strpos($type, '\\') !== false || $type === '') {
79
			return null;
80
		}
81
		return strtolower($type);
82
	}
83
}
84