Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HexBinaryElementTrait #39

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/HexBinaryElementTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\XML;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\XML\Exception\SchemaViolationException;

/**
* Trait grouping common functionality for simple elements with hexbinary textContent
*
* @package simplesamlphp/xml-common
*/
trait HexBinaryElementTrait
{
use StringElementTrait;


/**
* Sanitize the content of the element.
*
* Note: There are no processing rules for xs:hexBinary regarding whitespace. General consensus is to strip them
*
* @param string $content The unsanitized textContent
* @throws \Exception on failure
* @return string
*/
protected function sanitizeContent(string $content): string
{
return str_replace(["\f", "\r", "\n", "\t", "\v", ' '], '', $content);
}


/**
* Validate the content of the element.
*
* @param string $content The value to go in the XML textContent
* @throws \Exception on failure
* @return void
*/
protected function validateContent(string $content): void
{
// Note: content must already be sanitized before validating
Assert::regex(
$this->sanitizeContent($content),
'/([0-9A-F]{2})*/i',
SchemaViolationException::class,
);
}


/** @return string */
abstract public static function getLocalName(): string;


/**
* Create a document structure for this element
*
* @param \DOMElement|null $parent The element we should append to.
* @return \DOMElement
*/
abstract public function instantiateParentElement(?DOMElement $parent = null): DOMElement;
}
33 changes: 33 additions & 0 deletions tests/Utils/HexBinaryElement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Test\XML;

use SimpleSAML\XML\AbstractElement;
use SimpleSAML\XML\HexBinaryElementTrait;

/**
* Empty shell class for testing HexBinaryElement.
*
* @package simplesaml/xml-common
*/
final class HexBinaryElement extends AbstractElement
{
use HexBinaryElementTrait;

/** @var string */
public const NS = 'urn:x-simplesamlphp:namespace';

/** @var string */
public const NS_PREFIX = 'ssp';


/**
* @param string $content
*/
public function __construct(string $content)
{
$this->setContent($content);
}
}
112 changes: 112 additions & 0 deletions tests/XML/HexBinaryElementTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Test\XML;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use SimpleSAML\Test\XML\XMLDumper;
use SimpleSAML\XML\AbstractElement;
use SimpleSAML\XML\DOMDocumentFactory;
use SimpleSAML\XML\HexBinaryElementTrait;
use SimpleSAML\XML\StringElementTrait;
use SimpleSAML\XML\TestUtils\SerializableElementTestTrait;

use function dirname;
use function strval;

/**
* Class \SimpleSAML\XML\HexBinaryElementTraitTest
*
* @package simplesamlphp\xml-common
*/
#[CoversClass(SerializableElementTestTrait::class)]
#[CoversClass(HexBinaryElementTrait::class)]
#[CoversClass(StringElementTrait::class)]
#[CoversClass(AbstractElement::class)]
final class HexBinaryElementTraitTest extends TestCase
{
use SerializableElementTestTrait;


/**
*/
public static function setUpBeforeClass(): void
{
self::$testedClass = HexBinaryElement::class;

self::$xmlRepresentation = DOMDocumentFactory::fromFile(
dirname(__FILE__, 2) . '/resources/xml/ssp_HexBinaryElement.xml',
);
}

/**
*/
public function testMarshalling(): void
{
$hexBinaryElement = new HexBinaryElement(
'3f3c6d78206c657673726f693d6e3122302e20226e656f636964676e223d54552d4622383e3f',
);

$this->assertEquals(
XMLDumper::dumpDOMDocumentXMLWithBase64Content(self::$xmlRepresentation),
strval($hexBinaryElement),
);
}


/**
*/
public function testUnmarshalling(): void
{
/** @var \DOMElement $xml */
$xml = self::$xmlRepresentation->documentElement;
$hexBinaryElement = HexBinaryElement::fromXML($xml);

$this->assertEquals(
'3f3c6d78206c657673726f693d6e3122302e20226e656f636964676e223d54552d4622383e3f',
$hexBinaryElement->getContent(),
);
}


/**
* @param non-empty-string $xml
*/
#[DataProvider('provideHexBinaryCases')]
public function testHexBinaryCases(string $xml): void
{
$xmlRepresentation = DOMDocumentFactory::fromString($xml);
/** @var \DOMElement $xmlElement */
$xmlElement = $xmlRepresentation->documentElement;

$hexBinary = HexBinaryElement::fromXML($xmlElement);

$this->assertStringContainsString($hexBinary->getRawContent(), $xml);
}

/**
* @return array<string, array{0: string}>
*/
public static function provideHexBinaryCases(): array
{
return [
'inline' => [
<<<XML
<ssp:HexBinaryElement xmlns:ssp="urn:x-simplesamlphp:namespace">3f3c6d78206c657673726f693d6e3122302e20226e656f636964676e223d54552d4622383e3f</ssp:HexBinaryElement>
XML
,
],
'multiline' => [
<<<XML
<ssp:HexBinaryElement xmlns:ssp="urn:x-simplesamlphp:namespace">
3f3c6d78206c657673726f693d6e3122302e20226e656f636964676e223d54552d4622383e3f
</ssp:HexBinaryElement>
XML
,
],
];
}
}
1 change: 1 addition & 0 deletions tests/resources/xml/ssp_HexBinaryElement.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ssp:HexBinaryElement xmlns:ssp="urn:x-simplesamlphp:namespace">3f3c6d78206c657673726f693d6e3122302e20226e656f636964676e223d54552d4622383e3f</ssp:HexBinaryElement>
Loading