Passed
Pull Request — master (#26)
by Tim
02:03
created

ElementRegistry::getInstance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XML\Registry;
6
7
use SimpleSAML\Assert\Assert;
8
use SimpleSAML\XML\AbstractElement;
9
use SimpleSAML\XML\Exception\InvalidDOMElementException;
10
use SimpleSAML\XML\Exception\IOException;
11
use Symfony\Component\Finder\Finder;
12
13
use function array_merge_recursive;
14
use function dirname;
15
use function file_exists;
16
17
final class ElementRegistry
18
{
19
    /** @var \SimpleSAML\XML\Registry\ElementRegistry|null $instance */
20
    private static ?ElementRegistry $instance = null;
21
22
    /** @var array<string, array<string, string>> */
23
    private array $registry = [];
24
25
26
    private function __construct()
27
    {
28
        // Initialize the registry with all the elements we know
29
        $classesDir = dirname(__FILE__, 6) . '/vendor/simplesamlphp/composer-xmlprovider-installer/classes';
30
31
        if (file_exists($classesDir) === true) {
32
            $finder = Finder::create()->files()->name('element.registry.*.php')->in($classesDir);
33
            if ($finder->hasResults()) {
34
                foreach ($finder as $file) {
35
                    $this->importFromFile($file->getPathName());
36
                }
37
            }
38
        }
39
    }
40
41
42
    public function importFromFile(string $file): void
43
    {
44
        if (file_exists($file) === true) {
45
            $elements = include($file);
46
            $this->registry = array_merge_recursive($this->registry, $elements);
47
        } else {
48
            throw new IOException('File not found.');
49
        }
50
    }
51
52
53
    public static function getInstance(): ElementRegistry
54
    {
55
        if (self::$instance === null) {
56
            self::$instance = new static();
57
        }
58
59
        return self::$instance;
1 ignored issue
show
Bug Best Practice introduced by
The expression return self::instance could return the type null which is incompatible with the type-hinted return SimpleSAML\XML\Registry\ElementRegistry. Consider adding an additional type-check to rule them out.
Loading history...
60
    }
61
62
63
    /**
64
     * Register a class that can process a certain XML-element.
65
     *
66
     * @param string $class The class name of a class extending AbstractElement.
67
     */
68
    public function registerElementHandler(string $class): void
69
    {
70
        Assert::subclassOf($class, AbstractElement::class);
71
        $className = AbstractElement::getClassName($class);
72
        $namespace = $class::NS;
73
74
        $this->registry[$namespace][$className] = $class;
75
    }
76
77
78
    /**
79
     * Search for a class that implements an $element in the given $namespace.
80
     *
81
     * Such classes must have been registered previously by calling registerElementHandler(), and they must
82
     * extend \SimpleSAML\XML\AbstractElement.
83
     *
84
     * @param string|null $namespace The namespace URI for the given element.
85
     * @param string $element The local name of the element.
86
     *
87
     * @return string|null The fully-qualified name of a class extending \SimpleSAML\XML\AbstractElement and
88
     * implementing support for the given element, or null if no such class has been registered before.
89
     */
90
    public function getElementHandler(?string $namespace, string $element): ?string
91
    {
92
        Assert::nullOrValidURI($namespace, InvalidDOMElementException::class);
93
        Assert::validNCName($element, InvalidDOMElementException::class);
94
95
        return $this->registry[$namespace][$element] ?? null;
96
    }
97
}
98