From ee5aad6f7fb9a8cd6b119d04005e708d12d90e49 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Fri, 14 Jun 2024 08:29:05 +0200 Subject: [PATCH] Cache encoder detection --- src/Encoder/EncoderDetector.php | 32 ++++++++++++++++++++-- src/Encoder/ObjectEncoder.php | 2 +- src/Encoder/SimpleType/EncoderDetector.php | 8 ++++++ src/EncoderRegistry.php | 2 +- src/TypeInference/ComplexTypeBuilder.php | 8 ++++++ 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/Encoder/EncoderDetector.php b/src/Encoder/EncoderDetector.php index 64e4408..63f9e11 100644 --- a/src/Encoder/EncoderDetector.php +++ b/src/Encoder/EncoderDetector.php @@ -5,21 +5,45 @@ use Soap\Engine\Metadata\Model\XsdType; use stdClass; +use WeakMap; final class EncoderDetector { + /** + * @var WeakMap> + */ + private WeakMap $cache; + + public static function default(): self + { + /** @var self $self */ + static $self = new self(); + + return $self; + } + + private function __construct() + { + /** @var WeakMap> cache */ + $this->cache = new WeakMap(); + } + /** * @return XmlEncoder * - * @psalm-suppress InvalidReturnType, PossiblyInvalidArgument, InvalidReturnStatement - The simple type detector could return string|null, but should not be an issue here. + * @psalm-suppress InvalidArgument, InvalidReturnType, PossiblyInvalidArgument, InvalidReturnStatement - The simple type detector could return string|null, but should not be an issue here. */ public function __invoke(Context $context): XmlEncoder { $type = $context->type; + if ($cached = $this->cache[$type] ?? null) { + return $cached; + } + $meta = $type->getMeta(); $encoder = match(true) { - $meta->isSimple()->unwrapOr(false) => (new SimpleType\EncoderDetector())($context), + $meta->isSimple()->unwrapOr(false) => SimpleType\EncoderDetector::default()($context), default => $this->detectComplexTypeEncoder($type, $context), }; @@ -27,7 +51,9 @@ public function __invoke(Context $context): XmlEncoder $encoder = new RepeatingElementEncoder($encoder); } - return new ErrorHandlingEncoder($encoder); + $encoder = new ErrorHandlingEncoder($encoder); + + return $this->cache[$type] = $encoder; } /** diff --git a/src/Encoder/ObjectEncoder.php b/src/Encoder/ObjectEncoder.php index 35bda1c..bc24714 100644 --- a/src/Encoder/ObjectEncoder.php +++ b/src/Encoder/ObjectEncoder.php @@ -222,7 +222,7 @@ private function decorateLensForType(Lens $lens, TypeMeta $meta): Lens */ private function detectProperties(Context $context): array { - $type = (new ComplexTypeBuilder())($context); + $type = ComplexTypeBuilder::default()($context); return reindex( sort_by( diff --git a/src/Encoder/SimpleType/EncoderDetector.php b/src/Encoder/SimpleType/EncoderDetector.php index d4463f0..79baa61 100644 --- a/src/Encoder/SimpleType/EncoderDetector.php +++ b/src/Encoder/SimpleType/EncoderDetector.php @@ -13,6 +13,14 @@ final class EncoderDetector { + public static function default(): self + { + /** @var self $self */ + static $self = new self(); + + return $self; + } + /** * @return XmlEncoder */ diff --git a/src/EncoderRegistry.php b/src/EncoderRegistry.php index 6760e9b..1a00003 100644 --- a/src/EncoderRegistry.php +++ b/src/EncoderRegistry.php @@ -317,6 +317,6 @@ public function hasRegisteredComplexTypeForXsdType(XsdType $type): bool */ public function detectEncoderForContext(Context $context): XmlEncoder { - return (new EncoderDetector())($context); + return EncoderDetector::default()($context); } } diff --git a/src/TypeInference/ComplexTypeBuilder.php b/src/TypeInference/ComplexTypeBuilder.php index 5da4fec..06ca0b9 100644 --- a/src/TypeInference/ComplexTypeBuilder.php +++ b/src/TypeInference/ComplexTypeBuilder.php @@ -10,6 +10,14 @@ final class ComplexTypeBuilder { + public static function default(): self + { + /** @var self $self */ + static $self = new self(); + + return $self; + } + public function __invoke(Context $context): Type { $type = $context->metadata->getTypes()->fetchByNameAndXmlNamespace(