From 8b67e6f98cb583a170f522ceb5065e9dfd0a65d5 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Fri, 1 Nov 2024 11:33:16 +0100 Subject: [PATCH 1/2] Add mapping() and resolving() to supply custom (un)marshalling logic --- src/main/php/util/data/Marshalling.class.php | 33 +++++++++++++++++++ .../data/unittest/MarshallingTest.class.php | 21 ++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/main/php/util/data/Marshalling.class.php b/src/main/php/util/data/Marshalling.class.php index bddfc6d..b652c44 100755 --- a/src/main/php/util/data/Marshalling.class.php +++ b/src/main/php/util/data/Marshalling.class.php @@ -16,6 +16,31 @@ * @test util.data.unittest.ObjectsTest */ class Marshalling { + private $mappings= []; + + /** + * Maps user type marshalling + * + * @param string|lang.XPClass $type + * @param function(var): var $marshal + * @return self + */ + public function mapping($type, $marshal) { + $this->mappings[$type instanceof XPClass ? $type->literal() : $type][0]= $marshal; + return $this; + } + + /** + * Resolves user type unmarshalling + * + * @param string|lang.XPClass $type + * @param function(var, lang.XPClass): var $unmarshal + * @return self + */ + public function resolving($type, $unmarshal) { + $this->mappings[$type instanceof XPClass ? $type->literal() : $type][1]= $unmarshal; + return $this; + } /** * Applies unmarshal() to values inside an iterable @@ -44,6 +69,10 @@ public function unmarshal($value, $type= null) { $t= $type instanceof Type ? $type : Type::forName($type); if ($t instanceof XPClass) { + foreach ($this->mappings as $type => $mapping) { + if ($t->isAssignableFrom($type)) return $mapping[1]($value, $t); + } + if ($t->isInstance($value)) { return $value; } else if ($t->isEnum()) { @@ -149,6 +178,10 @@ public function marshal($value) { } else if ($value instanceof XPIterator) { return $this->iterator($value); } else if (is_object($value)) { + foreach ($this->mappings as $type => $marshal) { + if ($value instanceof $type) return $marshal[0]($value); + } + if (method_exists($value, '__serialize')) return $value->__serialize(); if (method_exists($value, '__toString')) return $value->__toString(); diff --git a/src/test/php/util/data/unittest/MarshallingTest.class.php b/src/test/php/util/data/unittest/MarshallingTest.class.php index b8a5759..dd86064 100755 --- a/src/test/php/util/data/unittest/MarshallingTest.class.php +++ b/src/test/php/util/data/unittest/MarshallingTest.class.php @@ -3,6 +3,7 @@ use lang\Type; use test\{Assert, Test, Values}; use util\data\Marshalling; +use util\data\unittest\fixtures\Person; class MarshallingTest { @@ -30,4 +31,24 @@ public function unmarshal($type) { public function unmarshal_without_type() { Assert::equals(1, (new Marshalling())->unmarshal(1)); } + + #[Test] + public function mapping() { + $marshalling= (new Marshalling())->mapping( + Person::class, + fn($person) => ['id' => $person->id()] + ); + + Assert::equals(['id' => 6100], $marshalling->marshal(new Person(6100, 'Test'))); + } + + #[Test] + public function resolving() { + $marshalling= (new Marshalling())->resolving( + Person::class, + fn($value) => new Person($value['id'], 'Test') + ); + + Assert::equals(new Person(6100, 'Test'), $marshalling->unmarshal(['id' => 6100], Person::class)); + } } \ No newline at end of file From d009bc945628f6e4c8424ee504b9101fe3f04d2a Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Fri, 1 Nov 2024 11:39:00 +0100 Subject: [PATCH 2/2] Fix PHP <= 7.4 --- src/test/php/util/data/unittest/MarshallingTest.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/php/util/data/unittest/MarshallingTest.class.php b/src/test/php/util/data/unittest/MarshallingTest.class.php index dd86064..a1ad63c 100755 --- a/src/test/php/util/data/unittest/MarshallingTest.class.php +++ b/src/test/php/util/data/unittest/MarshallingTest.class.php @@ -36,7 +36,7 @@ public function unmarshal_without_type() { public function mapping() { $marshalling= (new Marshalling())->mapping( Person::class, - fn($person) => ['id' => $person->id()] + function($person) { return ['id' => $person->id()]; } ); Assert::equals(['id' => 6100], $marshalling->marshal(new Person(6100, 'Test'))); @@ -46,7 +46,7 @@ public function mapping() { public function resolving() { $marshalling= (new Marshalling())->resolving( Person::class, - fn($value) => new Person($value['id'], 'Test') + function($value) { return new Person($value['id'], 'Test'); } ); Assert::equals(new Person(6100, 'Test'), $marshalling->unmarshal(['id' => 6100], Person::class));