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

Introduce element aware encoders #27

Merged
merged 1 commit into from
Sep 30, 2024

Conversation

veewee
Copy link
Member

@veewee veewee commented Sep 29, 2024

Q A
Type feature
BC Break no
Fixed issues #25

Summary

Fixes #25

/**
 * 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 XmlEncoder, ElementAware {
            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],
                );
            }
        }
    );

/cc @rauanmayemir : can you check if this allows you to solve the issues you are facing?

@veewee veewee force-pushed the element-aware-encoders branch 2 times, most recently from 4319586 to 6f4f8e4 Compare September 29, 2024 13:19
@veewee veewee force-pushed the element-aware-encoders branch from 6f4f8e4 to ba88883 Compare September 29, 2024 13:24
@rauanmayemir
Copy link
Collaborator

request part worked as expected, gotta get used to this new way. Trying the response part now.

@rauanmayemir
Copy link
Collaborator

@veewee This is a dream come true 🥹🥹🥹

data is perfectly decoded from XSD-backed types.

image

Kindly request for guidance for a situation where my data is of anyType and the incoming XML string looks like:

<data><ns123:response>...</ns123:response></data>

I always get confused with how to use Xml locators and manipulators with proper chaining, so the code looks a bit ugly:

      $value = Document::fromXmlNode(
          Document::fromXmlNode($data->element())
              ->locate(Locator\elements_with_tagname('response'))
              ->item(0),
      )
          ->toXmlString();

      return $this->serializer->deserialize(
          data: $value,
          type: Response::class,
          format: 'xml'
      );

@veewee
Copy link
Member Author

veewee commented Sep 30, 2024

I don't think it makes much sense to copy the node into a document twice, since this will take up quite some time and you already have access to the parsed DOM node. Maybe rather something like this:

$element = $data->element();
Document::fromUnsafeDocument($element->ownerDocument)->stringifyNode(
    \VeeWee\Xml\Dom\Locator\Element\locate_by_tag_name($element, 'response')->item(0)
);

@rauanmayemir
Copy link
Collaborator

Thank you, that looks much better!
Should this be merged and tagged?

@veewee veewee merged commit 3deec36 into php-soap:main Sep 30, 2024
15 checks passed
@veewee
Copy link
Member Author

veewee commented Sep 30, 2024

Tagged ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

anyType encoder with xsi type
2 participants