Skip to content

Commit

Permalink
Merge pull request #24 from veewee/optional-encoding-fix
Browse files Browse the repository at this point in the history
Allow not setting optional objects and arrays whilst encoding.
  • Loading branch information
veewee authored Sep 3, 2024
2 parents 0d1de01 + 76947c9 commit a8f06bf
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/Encoder/EncoderDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public function __invoke(Context $context): XmlEncoder
$encoder = new RepeatingElementEncoder($encoder);
}

if (!$encoder instanceof Feature\OptionalAware && $meta->isNullable()->unwrapOr(false)) {
$encoder = new OptionalElementEncoder($encoder);
}

$encoder = new ErrorHandlingEncoder($encoder);

return $this->cache[$type] = $encoder;
Expand Down
3 changes: 3 additions & 0 deletions src/Encoder/Feature/ListAware.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

namespace Soap\Encoding\Encoder\Feature;

/**
* Tells the encoder knows how to teal with list inputs.
*/
interface ListAware extends DisregardXsiInformation
{
}
11 changes: 11 additions & 0 deletions src/Encoder/Feature/OptionalAware.php
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 about optional (nullable) values.
*/
interface OptionalAware extends DisregardXsiInformation
{
}
2 changes: 1 addition & 1 deletion src/Encoder/OptionalElementEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* @template T of mixed
* @implements XmlEncoder<T, string>
*/
final class OptionalElementEncoder implements XmlEncoder
final class OptionalElementEncoder implements Feature\OptionalAware, XmlEncoder
{
/**
* @param XmlEncoder<T, string> $elementEncoder
Expand Down
10 changes: 5 additions & 5 deletions src/Encoder/RepeatingElementEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

/**
* @template T
* @implements XmlEncoder<iterable<array-key, T>, string>
* @implements XmlEncoder<iterable<array-key, T>|null, string>
*/
final class RepeatingElementEncoder implements Feature\ListAware, XmlEncoder
{
Expand All @@ -25,7 +25,7 @@ public function __construct(
}

/**
* @return Iso<iterable<array-key, T>, string>
* @return Iso<iterable<array-key, T>|null, string>
*/
public function iso(Context $context): Iso
{
Expand All @@ -39,12 +39,12 @@ public function iso(Context $context): Iso

return new Iso(
/**
* @param iterable<array-key, T> $raw
* @param iterable<array-key, T>|null $raw
*/
static function (iterable $raw) use ($innerIso): string {
static function (iterable|null $raw) use ($innerIso): string {
return join(
map(
$raw,
$raw ?? [],
/**
* @param T $item
*/
Expand Down
8 changes: 5 additions & 3 deletions src/Encoder/SimpleType/EncoderDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ public function __invoke(Context $context): XmlEncoder
}

if ($meta->isElement()->unwrapOr(false)) {
$encoder = new OptionalElementEncoder(
new ElementEncoder($encoder)
);
$encoder = new ElementEncoder($encoder);

if ($meta->isNullable()->unwrapOr(false)) {
$encoder = new OptionalElementEncoder($encoder);
}
}

return $encoder;
Expand Down
64 changes: 64 additions & 0 deletions tests/PhpCompatibility/Implied/ImpliedSchema004Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);

namespace Soap\Encoding\Test\PhpCompatibility\Implied;

use PHPUnit\Framework\Attributes\CoversClass;
use Soap\Encoding\Decoder;
use Soap\Encoding\Driver;
use Soap\Encoding\Encoder;
use Soap\Encoding\Test\PhpCompatibility\AbstractCompatibilityTests;

#[CoversClass(Driver::class)]
#[CoversClass(Encoder::class)]
#[CoversClass(Decoder::class)]
final class ImpliedSchema004Test extends AbstractCompatibilityTests
{
protected string $schema = <<<EOXML
<element name="testType">
<complexType>
<sequence>
<element name="OptionalList" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
<element name="OptionalSimpleElement" type="xsd:string" minOccurs="0" maxOccurs="1"/>
<element name="OptionalObject" minOccurs="0">
<complexType>
<sequence>
<element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
EOXML;
protected string $type = 'type="tns:testType"';

protected function calculateParam(): mixed
{
return (object)[];
}

protected function expectDecoded(): mixed
{
return (object)[
'OptionalList' => [],
'OptionalSimpleElement' => null,
'OptionalObject' => null,
];
}

protected function expectXml(): string
{
return <<<XML
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://test-uri/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:test>
<testParam xsi:type="tns:testType" />
</tns:test>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
XML;
}
}
15 changes: 15 additions & 0 deletions tests/Unit/Encoder/RepeatingElementEncoderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,19 @@ public function test_it_can_decode_from_xml_item_list(): void

static::assertEquals(['world'], $actual);
}

public function test_it_can_encode_from_null(): void
{
$encoder = new RepeatingElementEncoder(new ElementEncoder(new StringTypeEncoder()));
$context = self::createContext(
XsdType::guess('string')
->withXmlTargetNodeName('hello')
->withMeta(static fn (TypeMeta $meta): TypeMeta => $meta->withIsQualified(true))
);

$iso = $encoder->iso($context);
$actual = $iso->to(null);

static::assertSame('', $actual);
}
}

0 comments on commit a8f06bf

Please sign in to comment.