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

Read xml from memory #10

Merged
merged 1 commit into from
Jun 13, 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
8 changes: 4 additions & 4 deletions src/Decoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Soap\WsdlReader\Model\Definitions\BindingUse;
use Soap\WsdlReader\Model\Definitions\Namespaces;
use function count;
use function Psl\Type\non_empty_string;
use function Psl\invariant;
use function Psl\Vec\map;

final class Decoder implements SoapDecoder
Expand Down Expand Up @@ -39,9 +39,9 @@ public function decode(string $method, SoapResponse $response): mixed

// The SoapResponse only contains the payload of the response (with no headers).
// It can be parsed directly as XML.
$parts = (new OperationReader($meta))(
non_empty_string()->assert($response->getPayload())
);
$payload = $response->getPayload();
invariant($payload !== '', 'Expected a non-empty response payload. Received an empty HTTP response');
$parts = (new OperationReader($meta))($payload)->elements();

return match(count($parts)) {
0 => null,
Expand Down
8 changes: 4 additions & 4 deletions src/Encoder/ElementEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

namespace Soap\Encoding\Encoder;

use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Reader\ElementValueReader;
use Soap\Encoding\Xml\Writer\ElementValueBuilder;
use Soap\Encoding\Xml\Writer\XsdTypeXmlElementWriter;
use VeeWee\Reflecta\Iso\Iso;
use VeeWee\Xml\Dom\Document;

/**
* @implements XmlEncoder<mixed, string>
Expand Down Expand Up @@ -38,13 +38,13 @@ public function iso(Context $context): Iso
(new ElementValueBuilder($context, $typeEncoder, $raw))
),
/**
* @psalm-param non-empty-string $xml
* @psalm-param non-empty-string|Element $xml
* @psalm-return mixed
*/
static fn (string $xml): mixed => (new ElementValueReader())(
static fn (Element|string $xml): mixed => (new ElementValueReader())(
$context,
$typeEncoder,
Document::fromXmlString($xml)->locateDocumentElement(),
($xml instanceof Element ? $xml : Element::fromString($xml))->element()
)
);
}
Expand Down
14 changes: 9 additions & 5 deletions src/Encoder/ObjectEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Soap\Encoding\Normalizer\PhpPropertyNameNormalizer;
use Soap\Encoding\TypeInference\ComplexTypeBuilder;
use Soap\Encoding\TypeInference\XsiTypeDetector;
use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Reader\DocumentToLookupArrayReader;
use Soap\Encoding\Xml\Writer\AttributeBuilder;
use Soap\Encoding\Xml\Writer\NilAttributeBuilder;
Expand Down Expand Up @@ -62,11 +63,15 @@ function (object|array $value) use ($context, $properties) : string {
return $this->to($context, $properties, $value);
},
/**
* @param non-empty-string $value
* @param non-empty-string|Element $value
* @return TObj
*/
function (string $value) use ($context, $properties) : object {
return $this->from($context, $properties, $value);
function (string|Element $value) use ($context, $properties) : object {
return $this->from(
$context,
$properties,
($value instanceof Element ? $value : Element::fromString($value))
);
}
);
}
Expand Down Expand Up @@ -131,11 +136,10 @@ function (Property $property) use ($context, $data, $defaultAction) : Closure {

/**
* @param array<string, Property> $properties
* @param non-empty-string $data
*
* @return TObj
*/
private function from(Context $context, array $properties, string $data): object
private function from(Context $context, array $properties, Element $data): object
{
$nodes = (new DocumentToLookupArrayReader())($data);
/** @var Iso<TObj, array<string, mixed>> $objectData */
Expand Down
7 changes: 4 additions & 3 deletions src/Encoder/OptionalElementEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

namespace Soap\Encoding\Encoder;

use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Writer\NilAttributeBuilder;
use Soap\Encoding\Xml\Writer\XsdTypeXmlElementWriter;
use VeeWee\Reflecta\Iso\Iso;
use VeeWee\Xml\Dom\Document;
use VeeWee\Xml\Xmlns\Xmlns;

/**
Expand Down Expand Up @@ -48,16 +48,17 @@ public function iso(Context $context): Iso
/**
* @return T|null
*/
static function (string $xml) use ($elementIso) : mixed {
static function (Element|string $xml) use ($elementIso) : mixed {
if ($xml === '') {
return null;
}

$documentElement = Document::fromXmlString($xml)->locateDocumentElement();
$documentElement = ($xml instanceof Element ? $xml : Element::fromString($xml))->element();
if ($documentElement->getAttributeNS(Xmlns::xsi()->value(), 'nil') === 'true') {
return null;
}

/** @var Iso<T|null, Element|non-empty-string> $elementIso */
return $elementIso->from($xml);
}
);
Expand Down
20 changes: 13 additions & 7 deletions src/Encoder/RepeatingElementEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

namespace Soap\Encoding\Encoder;

use DOMElement;
use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Node\ElementList;
use Soap\Engine\Metadata\Model\TypeMeta;
use VeeWee\Reflecta\Iso\Iso;
use VeeWee\Xml\Dom\Document;
use function Psl\Str\join;
use function Psl\Vec\map;
use function VeeWee\Xml\Dom\Locator\Element\children as readChildren;

/**
* @template T
Expand Down Expand Up @@ -57,11 +56,18 @@ static function (iterable $raw) use ($innerIso): string {
/**
* @return iterable<array-key, T>
*/
static function (string $xml) use ($innerIso): iterable {
$doc = Document::fromXmlString('<list>'.$xml.'</list>');
static function (Element|ElementList|string $xml) use ($innerIso): iterable {

return readChildren($doc->locateDocumentElement())->map(
static fn (DOMElement $element): mixed => $innerIso->from($doc->stringifyNode($element))
$elements = match (true) {
$xml instanceof Element => [$xml],
$xml instanceof ElementList => $xml->elements(),
default => ElementList::fromString('<list>'.$xml.'</list>')->elements()
};

/** @var Iso<T|null, Element|non-empty-string> $innerIso */
return map(
$elements,
static fn (Element $element): mixed => $innerIso->from($element)
);
}
);
Expand Down
19 changes: 9 additions & 10 deletions src/Encoder/SoapEnc/ApacheMapEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
use Soap\Encoding\Encoder\SimpleType\ScalarTypeEncoder;
use Soap\Encoding\Encoder\XmlEncoder;
use Soap\Encoding\TypeInference\XsiTypeDetector;
use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Reader\ElementValueReader;
use Soap\Encoding\Xml\Writer\XsdTypeXmlElementWriter;
use Soap\Encoding\Xml\Writer\XsiAttributeBuilder;
use Soap\Engine\Metadata\Model\XsdType;
use VeeWee\Reflecta\Iso\Iso;
use VeeWee\Xml\Dom\Document;
use function Psl\Dict\merge;
use function Psl\Type\string;
use function VeeWee\Xml\Dom\Assert\assert_element;
Expand All @@ -39,9 +39,12 @@ public function iso(Context $context): Iso
*/
fn (array $value): string => $this->encodeArray($context, $value),
/**
* @param non-empty-string $value
* @param non-empty-string|Element $value
*/
fn (string $value): array => $this->decodeArray($context, $value),
fn (string|Element $value): array => $this->decodeArray(
$context,
$value instanceof Element ? $value : Element::fromString($value)
),
));
}

Expand Down Expand Up @@ -76,14 +79,10 @@ private function encodeArray(Context $context, array $data): string
);
}

/**
* @param non-empty-string $value
*/
private function decodeArray(Context $context, string $value): array
private function decodeArray(Context $context, Element $value): array
{
$document = Document::fromXmlString($value);
$xpath = $document->xpath();
$element = $document->locateDocumentElement();
$element = $value->element();
$xpath = $value->document()->xpath();

return readChildren($element)->reduce(
static function (array $map, DOMElement $item) use ($context, $xpath): array {
Expand Down
15 changes: 8 additions & 7 deletions src/Encoder/SoapEnc/SoapArrayEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
use Soap\Encoding\Encoder\SimpleType\ScalarTypeEncoder;
use Soap\Encoding\Encoder\XmlEncoder;
use Soap\Encoding\TypeInference\XsiTypeDetector;
use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Reader\ElementValueReader;
use Soap\Encoding\Xml\Writer\XsdTypeXmlElementWriter;
use Soap\Encoding\Xml\Writer\XsiAttributeBuilder;
use Soap\Engine\Metadata\Model\XsdType;
use Soap\WsdlReader\Model\Definitions\BindingUse;
use Soap\WsdlReader\Parser\Xml\QnameParser;
use VeeWee\Reflecta\Iso\Iso;
use VeeWee\Xml\Dom\Document;
use XMLWriter;
use function count;
use function Psl\Vec\map;
Expand Down Expand Up @@ -46,10 +46,13 @@ public function iso(Context $context): Iso
*/
fn (array $value): string => $this->encodeArray($context, $value),
/**
* @param non-empty-string $value
* @param non-empty-string|Element $value
* @return list<mixed>
*/
fn (string $value): array => $this->decodeArray($context, $value),
fn (string|Element $value): array => $this->decodeArray(
$context,
$value instanceof Element ? $value : Element::fromString($value)
),
));
}

Expand Down Expand Up @@ -125,13 +128,11 @@ private function itemElement(Context $context, ?string $itemNodeName, string $it
}

/**
* @param non-empty-string $value
* @return list<mixed>
*/
private function decodeArray(Context $context, string $value): array
private function decodeArray(Context $context, Element $value): array
{
$document = Document::fromXmlString($value);
$element = $document->locateDocumentElement();
$element = $value->element();

return readChildren($element)->reduce(
/**
Expand Down
17 changes: 8 additions & 9 deletions src/Encoder/SoapEnc/SoapObjectEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
use Soap\Encoding\Encoder\SimpleType\ScalarTypeEncoder;
use Soap\Encoding\Encoder\XmlEncoder;
use Soap\Encoding\TypeInference\XsiTypeDetector;
use Soap\Encoding\Xml\Node\Element;
use Soap\Encoding\Xml\Reader\ElementValueReader;
use Soap\Encoding\Xml\Writer\XsdTypeXmlElementWriter;
use Soap\Encoding\Xml\Writer\XsiAttributeBuilder;
use Soap\Engine\Metadata\Model\XsdType;
use VeeWee\Reflecta\Iso\Iso;
use VeeWee\Xml\Dom\Document;
use function Psl\Dict\merge;
use function VeeWee\Xml\Dom\Locator\Element\children as readChildren;
use function VeeWee\Xml\Writer\Builder\children;
Expand All @@ -37,9 +37,12 @@ public function iso(Context $context): Iso
*/
fn (object $value): string => $this->encodeArray($context, $value),
/**
* @param non-empty-string $value
* @param non-empty-string|Element $value
*/
fn (string $value): object => $this->decodeArray($context, $value),
fn (string|Element $value): object => $this->decodeArray(
$context,
$value instanceof Element ? $value : Element::fromString($value)
),
));
}

Expand Down Expand Up @@ -68,13 +71,9 @@ private function encodeArray(Context $context, object $data): string
);
}

/**
* @param non-empty-string $value
*/
private function decodeArray(Context $context, string $value): object
private function decodeArray(Context $context, Element $value): object
{
$document = Document::fromXmlString($value);
$element = $document->locateDocumentElement();
$element = $value->element();

return (object) readChildren($element)->reduce(
static function (array $map, DOMElement $item) use ($context): array {
Expand Down
3 changes: 2 additions & 1 deletion src/EncoderRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Soap\WsdlReader\Model\Definitions\EncodingStyle;
use Soap\Xml\Xmlns;
use stdClass;
use Stringable;
use function Psl\Dict\pull;

final class EncoderRegistry
Expand Down Expand Up @@ -312,7 +313,7 @@ public function hasRegisteredComplexTypeForXsdType(XsdType $type): bool
}

/**
* @return XmlEncoder<mixed, string>
* @return XmlEncoder<mixed, string|Stringable>
*/
public function detectEncoderForContext(Context $context): XmlEncoder
{
Expand Down
79 changes: 79 additions & 0 deletions src/Xml/Node/Element.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);

namespace Soap\Encoding\Xml\Node;

use DOMElement;
use Stringable;
use VeeWee\Xml\Dom\Document;
use function Psl\invariant;

final class Element implements Stringable
{
private ?DOMElement $element = null;
/**
* @var non-empty-string|null
*/
private ?string $value = null;

private function __construct()
{
}

/**
* @param non-empty-string $xml
*/
public static function fromString(string $xml): Element
{
$new = new self();
$new->element = null;
$new->value = $xml;

return $new;
}

public static function fromDOMElement(DOMElement $element): self
{
$new = new self();
$new->element = $element;
$new->value = null;

return $new;
}

public function element(): DOMElement
{
if (!$this->element) {
invariant($this->value !== null, 'Expected an XML value to be present');
$this->element = Document::fromXmlString($this->value)->locateDocumentElement();
}

return $this->element;
}

/**
* @return non-empty-string
*/
public function value(): string
{
if ($this->value === null) {
invariant($this->element !== null, 'Expected an DOMElement to be present');
$this->value = Document::fromXmlNode($this->element)->stringifyDocumentElement();
}

return $this->value;
}

public function document(): Document
{
return Document::fromUnsafeDocument($this->element()->ownerDocument);
}

/**
* @return non-empty-string
*/
public function __toString()
{
return $this->value();
}
}
Loading