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 a XsiTypeCalculator feature that can enhance xsi:type calculation from the encoder #22

Merged
merged 1 commit into from
Aug 30, 2024

Conversation

veewee
Copy link
Member

@veewee veewee commented Aug 21, 2024

Q A
Type feature
BC Break no
Fixed issues

Summary

Provides an alternative solution for #21

use Soap\Encoding\Encoder\Context;
use Soap\Encoding\Encoder\Feature\ElementContextEnhancer;
use Soap\Encoding\Encoder\Feature\XsiTypeCalculator;
use Soap\Encoding\Encoder\SimpleType\ScalarTypeEncoder;
use Soap\Encoding\Encoder\XmlEncoder;
use Soap\Encoding\EncoderRegistry;
use Soap\Encoding\Xml\Writer\ElementValueBuilder;
use Soap\WsdlReader\Model\Definitions\BindingUse;
use VeeWee\Reflecta\Iso\Iso;

/**
 * This encoder can add xsi:type information to the XML element on xsd:anyType simpleTypes on literal encoded documents.
 *
 * <xsd:element minOccurs="0" maxOccurs="1" name="value" type="xsd:anyType" />
 *
 * Will Result in for example:
 *
 * <value
 *   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 *   xsi:type="xsds:int"
 *   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 * >
 *  789
 * </value>
 */

EncoderRegistry::default()
    ->addSimpleTypeConverter(
        'http://www.w3.org/2001/XMLSchema',
        'anyType',
        new class implements
            ElementContextEnhancer,
            XmlEncoder,
            XsiTypeCalculator {
            public function iso(Context $context): Iso
            {
                return (new ScalarTypeEncoder())->iso($context);
            }

            /**
             * This method allows to change the context on the wrapping elementEncoder.
             * By forcing the bindingUse to `ENCODED`, we can make sure the xsi:type attribute is added.
             */
            public function enhanceElementContext(Context $context): Context
            {
                return $context->withBindingUse(BindingUse::ENCODED);
            }

            /**
             * Can be used to fine-tune the xsi:type element.
             * For example, xsi:type="xsd:date" when dealing with value's like `DateTimeImmutable`.
             *
             * A default fallback function is provided in the ElementValueBuilder class.
             */
            public function resolveXsiTypeForValue(Context $context, mixed $value): string
            {
                return match (true) {
                    $value instanceof \DateTime => 'xsd:datetime',
                    $value instanceof \Date => 'xsd:date',
                    default => ElementValueBuilder::resolveXsiTypeForValue($context, $value),
                };
            }

            /**
             * Determines if the xmlns of the xsi:type prefix should be imported.
             * For example: xsd:date will import xmlns:xsd="...".
             *
             * A default fallback function is provided in the ElementValueBuilder class.
             */
            public function shouldIncludeXsiTargetNamespace(Context $context): bool
            {
                return ElementValueBuilder::shouldIncludeXsiTargetNamespace($context);
            }
        }
    );

@veewee veewee mentioned this pull request Aug 21, 2024
@veewee veewee force-pushed the alternate-resolveXsiType branch from f52864a to a7aa57d Compare August 30, 2024 06:42
@veewee veewee merged commit 0d1de01 into php-soap:main Aug 30, 2024
15 checks passed
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.

1 participant