-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #27 from veewee/element-aware-encoders
Introduce element aware encoders
- Loading branch information
Showing
10 changed files
with
126 additions
and
9 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,49 @@ | ||
<?php declare(strict_types=1); | ||
require_once \dirname(__DIR__, 3) . '/vendor/autoload.php'; | ||
|
||
use Soap\Encoding\Encoder\Context; | ||
use Soap\Encoding\Encoder\Feature\ElementAware; | ||
use Soap\Encoding\Encoder\SimpleType\ScalarTypeEncoder; | ||
use Soap\Encoding\Encoder\XmlEncoder; | ||
use Soap\Encoding\EncoderRegistry; | ||
use VeeWee\Reflecta\Iso\Iso; | ||
use function VeeWee\Xml\Encoding\document_encode; | ||
use function VeeWee\Xml\Encoding\xml_decode; | ||
|
||
/** | ||
* Most of the time, you don't need access to the wrapping XML element from within a simple type encoder. | ||
* Sometimes, when using anyXml or anyType, you might want to have full control over the wrapping element. | ||
* This allows you to use 3rd party tools to build the full XML structure from within a simple type encoder. | ||
* | ||
* Do note that: | ||
* - You'll need to check if the current provided type is an attribute or not. | ||
* - If you want to add xsi:type information, you need to add / parse it manually. | ||
* - The result will be used as a raw XML input, meaning it should be valid XML (without the header declearations). | ||
*/ | ||
EncoderRegistry::default() | ||
->addSimpleTypeConverter( | ||
'http://www.w3.org/2001/XMLSchema', | ||
'anyXml', | ||
new class implements | ||
ElementAware, | ||
XmlEncoder { | ||
public function iso(Context $context): Iso | ||
{ | ||
if ($context->type->getMeta()->isAttribute()->unwrapOr(false)) { | ||
return (new ScalarTypeEncoder())->iso($context); | ||
} | ||
|
||
$targetElementName = $context->type->getXmlTargetNodeName(); | ||
return new Iso( | ||
to: static fn (array $data): string => document_encode([$targetElementName => $data]) | ||
->manipulate(static fn (\DOMDocument $document) => $document->documentElement->setAttributeNS( | ||
VeeWee\Xml\Xmlns\Xmlns::xsi()->value(), | ||
'xsi:type', | ||
'custom:type' | ||
)) | ||
->stringifyDocumentElement(), | ||
from: static fn (string $xml): array => xml_decode($xml)[$targetElementName], | ||
); | ||
} | ||
} | ||
); |
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,11 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Soap\Encoding\Encoder\Feature; | ||
|
||
/** | ||
* Tells the encoder knows how to encode elements. | ||
* It can be used on simpleType encoders so that you get in control about the wrapping XML element. | ||
*/ | ||
interface ElementAware | ||
{ | ||
} |
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
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
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,54 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Soap\Encoding\Test\Unit\Encoder\Feature; | ||
|
||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use Soap\Encoding\Encoder\Context; | ||
use Soap\Encoding\Encoder\Feature\ElementAware; | ||
use Soap\Encoding\Encoder\SimpleType\EncoderDetector; | ||
use Soap\Encoding\Encoder\XmlEncoder; | ||
use Soap\Encoding\EncoderRegistry; | ||
use Soap\Encoding\Test\Unit\Encoder\AbstractEncoderTests; | ||
use Soap\Engine\Metadata\Model\XsdType; | ||
use Soap\Xml\Xmlns; | ||
use VeeWee\Reflecta\Iso\Iso; | ||
use function VeeWee\Xml\Encoding\document_encode; | ||
use function VeeWee\Xml\Encoding\xml_decode; | ||
|
||
#[CoversClass(EncoderDetector::class)] | ||
final class ElementAwareEncoderTest extends AbstractEncoderTests | ||
{ | ||
public static function provideIsomorphicCases(): iterable | ||
{ | ||
$registry = EncoderRegistry::default() | ||
->addSimpleTypeConverter( | ||
Xmlns::xsd()->value(), | ||
'anyType', | ||
new class implements | ||
ElementAware, | ||
XmlEncoder { | ||
public function iso(Context $context): Iso | ||
{ | ||
$typeName = $context->type->getXmlTargetNodeName(); | ||
return new Iso( | ||
to: static fn (array $data): string => document_encode([$typeName => $data])->stringifyDocumentElement(), | ||
from: static fn (string $xml): array => xml_decode($xml)[$typeName], | ||
); | ||
} | ||
} | ||
); | ||
|
||
$context = self::createContext( | ||
XsdType::any()->withXmlTargetNodeName('data'), | ||
encoderRegistry: $registry | ||
); | ||
$encoder = $registry->detectEncoderForContext($context); | ||
|
||
yield 'element-aware-simple-type' => [ | ||
'encoder' => $encoder, | ||
'context' => $context, | ||
'xml' => '<data><key>value</key></data>', | ||
'data' => ['key' => 'value'], | ||
]; | ||
} | ||
} |