From a09b96509ca77e553d480e377a9c705b4f04138b Mon Sep 17 00:00:00 2001 From: Tim van Dijen Date: Thu, 12 Sep 2024 00:01:44 +0200 Subject: [PATCH] Add element registry --- composer.json | 8 ++- src/Registry/AbstractElementRegistry.php | 89 ++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 src/Registry/AbstractElementRegistry.php diff --git a/composer.json b/composer.json index b60c64c..7168968 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "simplesamlphp/xml-common", "description": "A library with classes and utilities for handling XML structures.", - "type": "project", + "type": "simplesamlphp-xmlprovider", "keywords": ["saml", "xml"], "homepage": "http://simplesamlphp.org", "license": "LGPL-2.1-or-later", @@ -34,7 +34,8 @@ "ext-spl": "*", "ext-xmlreader": "*", - "simplesamlphp/assert": "^1.2" + "simplesamlphp/assert": "^1.2", + "symfony/finder": "^6.4" }, "require-dev": { "simplesamlphp/simplesamlphp-test-framework": "^1.7" @@ -47,7 +48,8 @@ "allow-plugins": { "composer/package-versions-deprecated": true, "dealerdirect/phpcodesniffer-composer-installer": true, - "phpstan/extension-installer": true + "phpstan/extension-installer": true, + "simplesamlphp/composer-xmlprovider-installer": true } } } diff --git a/src/Registry/AbstractElementRegistry.php b/src/Registry/AbstractElementRegistry.php new file mode 100644 index 0000000..60586b5 --- /dev/null +++ b/src/Registry/AbstractElementRegistry.php @@ -0,0 +1,89 @@ + */ + protected array $registry = []; + + final private function __construct() + { + // Initialize the registry with all the elements we know + $classesDir = dirname(__FILE__, 3) . '/vendor/simplesamlphp/composer-xmlprovider-installer/classes'; + + $finder = Finder::create()->files()->name('element.registry.*.php')->in($classesDir); + if ($finder->hasResults()) { + foreach ($finder as $file) { + $elements = include($file); + $this->registry = array_merge($this->registry, $elements); + } + } + } + + + public static function getInstance(): AbstractElementRegistry + { + if (self::$instance === null) { + self::$instance = new static(); + } + + return self::$instance; + } + + + /** + * Register a class that can process a certain XML-element. + * + * @param string $class The class name of a class extending AbstractElement. + */ + public function registerElementHandler(string $class): void + { + Assert::subclassOf($class, AbstractElement::class); + $className = AbstractElement::getClassName($class); + $key = ($class::NS === null) ? $className : implode(':', [$class::NS, $className]); + $this->registry[$key] = $class; + } + + + /** + * Search for a class that implements an $element in the given $namespace. + * + * Such classes must have been registered previously by calling registerElementHandler(), and they must + * extend \SimpleSAML\XML\AbstractElement. + * + * @param string|null $namespace The namespace URI for the given element. + * @param string $element The local name of the element. + * + * @return string|null The fully-qualified name of a class extending \SimpleSAML\XML\AbstractElement and + * implementing support for the given element, or null if no such class has been registered before. + */ + public function getElementHandler(?string $namespace, string $element): ?string + { + Assert::nullOrValidURI($namespace, InvalidDOMElementException::class); + Assert::validNCName($element, InvalidDOMElementException::class); + + $key = ($namespace === null) ? $element : implode(':', [$namespace, $element]); + if (array_key_exists($key, $this->registry) === true) { + return $this->registry[$key]; + } + + return null; + } +}