-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add container classes to accomodate extension points
- Loading branch information
Showing
5 changed files
with
218 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\Compat; | ||
|
||
use Psr\Clock\ClockInterface; | ||
use Psr\Log\LoggerInterface; | ||
use SimpleSAML\Assert\Assert; | ||
use SimpleSAML\SAML11\XML\ExtensionPointInterface; | ||
use SimpleSAML\XML\AbstractElement; | ||
use SimpleSAML\XML\Exception\SchemaViolationException; | ||
|
||
use function array_key_exists; | ||
use function implode; | ||
use function is_subclass_of; | ||
|
||
abstract class AbstractContainer | ||
{ | ||
/** @var string */ | ||
private const XSI_TYPE_PREFIX = '<xsi:type>'; | ||
|
||
/** @var array */ | ||
protected array $registry = []; | ||
|
||
|
||
/** | ||
* Register a class that can handle given extension points of the standard. | ||
* | ||
* @param string $class The class name of a class extending AbstractElement or implementing ExtensionPointInterface. | ||
* @psalm-param class-string $class | ||
*/ | ||
public function registerExtensionHandler(string $class): void | ||
{ | ||
Assert::subclassOf($class, AbstractElement::class); | ||
if (is_subclass_of($class, ExtensionPointInterface::class, true)) { | ||
$key = implode(':', [self::XSI_TYPE_PREFIX, $class::getXsiTypeNamespaceURI(), $class::getXsiTypeName()]); | ||
} else { | ||
$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 registerExtensionHandler(), 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. | ||
* @psalm-return class-string|null | ||
*/ | ||
public function getElementHandler(?string $namespace, string $element): ?string | ||
{ | ||
Assert::nullOrValidURI($namespace, SchemaViolationException::class); | ||
Assert::validNCName($element, SchemaViolationException::class); | ||
|
||
$key = ($namespace === null) ? $element : implode(':', [$namespace, $element]); | ||
if (array_key_exists($key, $this->registry) === true) { | ||
return $this->registry[$key]; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
|
||
/** | ||
* Search for a class that implements a custom element type. | ||
* | ||
* Such classes must have been registered previously by calling registerExtensionHandler(), and they must | ||
* implement \SimpleSAML\SAML11\XML\saml\ExtensionPointInterface. | ||
* | ||
* @param string $type The type of the identifier (xsi:type of a BaseID element). | ||
* | ||
* @return string|null The fully-qualified name of a class implementing | ||
* \SimpleSAML\SAML11\XML\saml\ExtensionPointInterface or null if no such class has been registered before. | ||
* @psalm-return class-string|null | ||
*/ | ||
public function getExtensionHandler(string $type): ?string | ||
{ | ||
Assert::notEmpty($type, 'Cannot search for identifier handlers with an empty type.'); | ||
$type = implode(':', [self::XSI_TYPE_PREFIX, $type]); | ||
if (!array_key_exists($type, $this->registry)) { | ||
return null; | ||
} | ||
Assert::implementsInterface($this->registry[$type], ExtensionPointInterface::class); | ||
return $this->registry[$type]; | ||
} | ||
|
||
|
||
/** | ||
* Get a PSR-3 compatible logger. | ||
* @return \Psr\Log\LoggerInterface | ||
*/ | ||
abstract public function getLogger(): LoggerInterface; | ||
|
||
|
||
/** | ||
* Get the system clock, using UTC for a timezone | ||
*/ | ||
abstract public function getClock(): ClockInterface; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\Compat; | ||
|
||
use SimpleSAML\Assert\Assert; | ||
|
||
class ContainerSingleton | ||
{ | ||
/** @var \SimpleSAML\SAML11\Compat\AbstractContainer */ | ||
protected static AbstractContainer $container; | ||
|
||
|
||
/** | ||
* @return \SimpleSAML\SAML11\Compat\AbstractContainer | ||
*/ | ||
public static function getInstance(): AbstractContainer | ||
{ | ||
Assert::notNull(self::$container, 'No container set.'); | ||
return self::$container; | ||
} | ||
|
||
|
||
/** | ||
* Set a container to use. | ||
* | ||
* @param \SimpleSAML\SAML11\Compat\AbstractContainer $container | ||
*/ | ||
public static function setContainer(AbstractContainer $container): void | ||
{ | ||
self::$container = $container; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11\Compat; | ||
|
||
use Psr\Clock\ClockInterface; | ||
use Psr\Log\LoggerInterface; | ||
use Psr\Log\NullLogger; | ||
|
||
/** | ||
* Class \SimpleSAML\SAML11\Compat\MockContainer | ||
*/ | ||
class MockContainer extends AbstractContainer | ||
{ | ||
/** @var \Psr\Clock\ClockInterface */ | ||
private ClockInterface $clock; | ||
|
||
|
||
/** | ||
* Get a PSR-3 compatible logger. | ||
* @return \Psr\Log\LoggerInterface | ||
*/ | ||
public function getLogger(): LoggerInterface | ||
{ | ||
return new NullLogger(); | ||
} | ||
|
||
|
||
/** | ||
* Set the system clock | ||
* | ||
* @param \Psr\Clock\ClockInterface $clock | ||
* @return void | ||
*/ | ||
public function setClock(ClockInterface $clock): void | ||
{ | ||
$this->clock = $clock; | ||
} | ||
|
||
|
||
/** | ||
* Get the system clock | ||
* | ||
* @return \Psr\Clock\ClockInterface | ||
*/ | ||
public function getClock(): ClockInterface | ||
{ | ||
return $this->clock; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace SimpleSAML\SAML11; | ||
|
||
use SimpleSAML\SAML11\Compat\AbstractContainer; | ||
use SimpleSAML\SAML11\Compat\ContainerSingleton; | ||
|
||
/** | ||
* Helper functions for the SAML 1.1 library. | ||
* | ||
* @package simplesamlphp/saml11 | ||
*/ | ||
class Utils | ||
{ | ||
/** | ||
* @return \SimpleSAML\SAML11\Compat\AbstractContainer | ||
*/ | ||
public static function getContainer(): AbstractContainer | ||
{ | ||
return ContainerSingleton::getInstance(); | ||
} | ||
} |