Skip to content

Commit

Permalink
Merge pull request #26 from simplesamlphp/feature/element-registry
Browse files Browse the repository at this point in the history
Add element registry
  • Loading branch information
tvdijen authored Sep 13, 2024
2 parents 900bfed + eabfe6f commit 02bc56e
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
run: composer-require-checker check --config-file=tools/composer-require-checker.json composer.json

- name: Check code for unused dependencies in composer.json
run: composer-unused
run: composer-unused --excludePackage=simplesamlphp/composer-xmlprovider-installer

- name: PHP Code Sniffer
run: phpcs
Expand Down
9 changes: 6 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -34,7 +34,9 @@
"ext-spl": "*",
"ext-xmlreader": "*",

"simplesamlphp/assert": "^1.2"
"simplesamlphp/assert": "^1.2",
"simplesamlphp/composer-xmlprovider-installer": "dev-master",
"symfony/finder": "^6.4"
},
"require-dev": {
"simplesamlphp/simplesamlphp-test-framework": "^1.7"
Expand All @@ -47,7 +49,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
}
}
}
97 changes: 97 additions & 0 deletions src/Registry/ElementRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\XML\Registry;

use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\AbstractElement;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
use SimpleSAML\XML\Exception\IOException;
use Symfony\Component\Finder\Finder;

use function array_merge_recursive;
use function dirname;
use function file_exists;

final class ElementRegistry
{
/** @var \SimpleSAML\XML\Registry\ElementRegistry|null $instance */
private static ?ElementRegistry $instance = null;

/** @var array<string, array<string, string>> */
private array $registry = [];


private function __construct()
{
// Initialize the registry with all the elements we know
$classesDir = dirname(__FILE__, 6) . '/vendor/simplesamlphp/composer-xmlprovider-installer/classes';

if (file_exists($classesDir) === true) {
$finder = Finder::create()->files()->name('element.registry.*.php')->in($classesDir);
if ($finder->hasResults()) {
foreach ($finder as $file) {
$this->importFromFile($file->getPathName());
}
}
}
}


public function importFromFile(string $file): void
{
if (file_exists($file) === true) {
$elements = include($file);
$this->registry = array_merge_recursive($this->registry, $elements);
} else {
throw new IOException('File not found.');
}
}


public static function getInstance(): ElementRegistry
{
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);
$namespace = $class::NS;

$this->registry[$namespace][$className] = $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);

return $this->registry[$namespace][$element] ?? null;
}
}
58 changes: 58 additions & 0 deletions tests/Registry/ElementRegistryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Test\XML;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
use SimpleSAML\XML\Registry\ElementRegistry;

/**
* @package simplesamlphp\xml-common
*/
#[CoversClass(ElementRegistry::class)]
#[Group('registry')]
final class ElementRegistryTest extends TestCase
{
/** @var \SimpleSAML\XML\Registry\ElementRegistry */
protected static ElementRegistry $registry;


/**
*/
public static function setUpBeforeClass(): void
{
self::$registry = ElementRegistry::getInstance();
self::$registry->registerElementHandler('\SimpleSAML\Test\XML\Element');
}


/**
*/
public function testFetchingHandlerWorks(): void
{
$handler = self::$registry->getElementHandler('urn:x-simplesamlphp:namespace', 'Element');
$this->assertEquals($handler, '\SimpleSAML\Test\XML\Element');
}


/**
*/
public function testAddingHandlerWorks(): void
{
self::$registry->registerElementHandler('\SimpleSAML\Test\XML\ExtendableElement');
$handler = self::$registry->getElementHandler('urn:x-simplesamlphp:namespace', 'ExtendableElement');
$this->assertEquals($handler, '\SimpleSAML\Test\XML\ExtendableElement');
}


/**
*/
public function testUnknownHandlerReturnsNull(): void
{
$handler = self::$registry->getElementHandler('urn:x-simplesamlphp:namespace', 'UnknownElement');
$this->assertNull($handler);
}
}

0 comments on commit 02bc56e

Please sign in to comment.