From 79ae79473011c403e29ffaa1dfa51b0b8e778335 Mon Sep 17 00:00:00 2001 From: Francis Hilaire Date: Wed, 8 May 2024 01:50:59 +0200 Subject: [PATCH] Refactor to use the new getSupportedTypes on the serializer --- .github/workflows/build.yml | 16 +++- phpstan.neon.dist | 23 +---- psalm.xml | 10 -- src/Api/Fault.php | 1 - src/Command/GeneratorCommand.php | 4 +- src/HttPlug/Plugin/OdooApiErrorPlugin.php | 3 - src/Manager/ModelListManager.php | 67 ++++++++++--- src/Manager/ModelListManagerInterface.php | 29 +++++- src/Provider/ModelFieldsProvider.php | 17 +++- src/Provider/ModelFieldsProviderInterface.php | 2 + src/Serializer/Factory/SerializerFactory.php | 2 + .../NullOdooRelationDenormalizer.php | 8 ++ .../NullableDateTimeDenormalizer.php | 9 ++ src/Serializer/OdooNormalizer.php | 14 +++ src/Serializer/OdooRelationDenormalizer.php | 8 ++ src/Serializer/OdooRelationNormalizer.php | 5 + .../OdooRelationSingleDenormalizer.php | 8 ++ src/Serializer/OdooRelationsDenormalizer.php | 51 ++++++++++ src/Serializer/OdooRelationsNormalizer.php | 12 +-- tests/Manager/ModelListManagerTest.php | 7 ++ .../ExecuteKw/ExecuteKwOperationsTrait.php | 4 +- tests/Serializer/Model/Foo.php | 95 +++++++++++++++++++ .../Serializer/OdooDateTimeNormalizerTest.php | 31 ++---- 23 files changed, 344 insertions(+), 82 deletions(-) create mode 100644 src/Serializer/OdooRelationsDenormalizer.php create mode 100644 tests/Serializer/Model/Foo.php diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 52b6878d..550e0723 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -127,7 +127,21 @@ jobs: run: | bin/odoo-model-classes-generator -vvv \ "./tests/TestModel/Object" \ - "Tests\\FluxSE\\OdooApiClient\\TestModel\\Object" + "Tests\\FluxSE\\OdooApiClient\\TestModel\\Object" \ + --only-model=account.account \ + --only-model=account.journal \ + --only-model=account.move \ + --only-model=account.move.line \ + --only-model=account.payment \ + --only-model=account.payment.method \ + --only-model=account.payment.register \ + --only-model=account.tax \ + --only-model=product.category \ + --only-model=product.product \ + --only-model=product.template \ + --only-model=res.currency \ + --only-model=res.partner \ + --only-model=uom.uom # Need classes from Odoo to be generated for the tests folder - diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 8022225c..9b7d2ad0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -10,8 +10,7 @@ parameters: - tests/Manager/ModelManagerTest.php ignoreErrors: - - '/Method FluxSE\\OdooApiClient\\Manager\\ModelListManager::(find|findBy)\(\) should return (array<|\()T of FluxSE\\OdooApiClient\\Model\\BaseInterface(>|\)\|null) but returns mixed\./' - - '/Method FluxSE\\OdooApiClient\\Serializer\\(Json|Xml)Rpc\\(Json|Xml)RpcSerializerHelper::deserializeResponseBody\(\) should return T of object but returns mixed\./' + - '/Method FluxSE\\OdooApiClient\\Manager\\ModelListManager::(find|findBy|findByIds)\(\) should return (array<|\()T of FluxSE\\OdooApiClient\\Model\\BaseInterface(>|\)\|null) but returns mixed\./' - '/Method FluxSE\\OdooApiClient\\Serializer\\(Json|Xml)Rpc\\(Json|Xml)RpcSerializerHelper::decodeResponseBody\(\) should return array\|bool\|int\|string but returns mixed\./' - @@ -19,24 +18,12 @@ parameters: count: 1 path: src/Serializer/OdooNormalizer.php - - message: '/Method FluxSE\\OdooApiClient\\Serializer\\OdooNormalizer::setAttributeValue\(\) has parameter \$value with no type specified\./' + message: '/Parameter #1 \$onFulfilled of method Http\\Promise\\Promise::then\(\) expects \(callable\(mixed\): Psr\\Http\\Message\\ResponseInterface\)\|null, Closure\(Psr\\Http\\Message\\ResponseInterface\): Psr\\Http\\Message\\ResponseInterface given\./' count: 1 - path: src/Serializer/OdooNormalizer.php + path: src/HttPlug/Plugin/OdooApiErrorPlugin.php + # Symfony 5.4 + - '/Method FluxSE\\OdooApiClient\\Serializer\\(Json|Xml)Rpc\\(Json|Xml)RpcSerializerHelper::deserializeResponseBody\(\) should return T of object but returns mixed\./' - message: '/Method FluxSE\\OdooApiClient\\HttPlug\\Plugin\\OdooApiErrorPlugin::handleRequest\(\) has parameter \$(first|next) with generic interface Http\\Promise\\Promise but does not specify its types: T/' count: 2 path: src/HttPlug/Plugin/OdooApiErrorPlugin.php - - - message: '/Parameter #1 \$onFulfilled of method Http\\Promise\\Promise::then\(\) expects \(callable\(mixed\): Psr\\Http\\Message\\ResponseInterface\)\|null, Closure\(Psr\\Http\\Message\\ResponseInterface\): Psr\\Http\\Message\\ResponseInterface given\./' - count: 1 - path: src/HttPlug/Plugin/OdooApiErrorPlugin.php - # Odoo v17 - # https://github.com/odoo/odoo/issues/144841 - - - message: '/Method Tests\\FluxSE\\OdooApiClient\\TestModel\\Object\\Mail\\Alias::__construct\(\) invoked with 1 parameter, 3 required\./' - count: 1 - path: tests/TestModel/Object/Mail/Alias/Mixin.php - - - message: '/Parameter #1 \$alias_model_id of method Tests\\FluxSE\\OdooApiClient\\TestModel\\Object\\Mail\\Alias::__construct\(\) expects FluxSE\\OdooApiClient\\Model\\OdooRelation, string given\./' - count: 1 - path: tests/TestModel/Object/Mail/Alias/Mixin.php diff --git a/psalm.xml b/psalm.xml index 082fcfc5..a8047326 100644 --- a/psalm.xml +++ b/psalm.xml @@ -33,15 +33,5 @@ - - - - - - - - - - diff --git a/src/Api/Fault.php b/src/Api/Fault.php index 7a03558a..8353ee9e 100644 --- a/src/Api/Fault.php +++ b/src/Api/Fault.php @@ -10,7 +10,6 @@ public function __construct(private int $faultCode, private string $faultString) { } - public function getFaultCode(): int { return $this->faultCode; diff --git a/src/Command/GeneratorCommand.php b/src/Command/GeneratorCommand.php index 5cc7ed48..a2899095 100644 --- a/src/Command/GeneratorCommand.php +++ b/src/Command/GeneratorCommand.php @@ -39,12 +39,12 @@ protected function configure(): void ->addArgument( 'path', InputArgument::REQUIRED, - 'The path where classes will be generated (ex: ./src/OdooModel/Object)' + 'The path where classes will be generated (ex: ./src/Odoo/Model/Object)' ) ->addArgument( 'namespace', InputArgument::REQUIRED, - 'The base namespace of the generated classes (ex: "App\\OdooModel\\Object")' + 'The base namespace of the generated classes (ex: "App\\Odoo\Model\\Object")' ) ->addOption( 'host', diff --git a/src/HttPlug/Plugin/OdooApiErrorPlugin.php b/src/HttPlug/Plugin/OdooApiErrorPlugin.php index dc7aa347..54e8593d 100644 --- a/src/HttPlug/Plugin/OdooApiErrorPlugin.php +++ b/src/HttPlug/Plugin/OdooApiErrorPlugin.php @@ -22,9 +22,6 @@ public function __construct( ) { } - /** - * @return Promise - */ public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $errorNext = function (RequestInterface $request) use ($next, $first): Promise { diff --git a/src/Manager/ModelListManager.php b/src/Manager/ModelListManager.php index fee60bb4..12c49907 100644 --- a/src/Manager/ModelListManager.php +++ b/src/Manager/ModelListManager.php @@ -6,6 +6,8 @@ use FluxSE\OdooApiClient\Model\BaseInterface; use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Arguments\SearchDomainsInterface; +use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Options\ReadOptions; +use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Options\ReadOptionsInterface; use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Options\SearchReadOptions; use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Options\SearchReadOptionsInterface; use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\RecordListOperationsInterface; @@ -21,26 +23,46 @@ public function __construct( ) { } - public function find(string $className, int $id): ?BaseInterface - { - $modelName = $this->getModelNameFromClass($className); - - $results = $this->recordListOperations->read($modelName, [$id]); + public function find( + string $className, + int $id, + ?ReadOptionsInterface $readOptions = null + ): ?BaseInterface { + $results = $this->findByIds($className, [$id], $readOptions); if (count($results) === 0) { return null; } - return $this->serializer->denormalize($results[0], $className); + return $results[0]; } - public function findOneBy(string $className, ?SearchDomainsInterface $searchDomains = null): ?BaseInterface - { - $searchReadOptions = new SearchReadOptions(); + public function findByIds( + string $className, + array $ids, + ?ReadOptionsInterface $readOptions = null + ): array { + $readOptions = $readOptions ?? new ReadOptions(); + + $this->processReadOptions($className, $readOptions, [ + 'class' => __CLASS__, + 'method' => __METHOD__, + ]); + + $modelName = $this->getModelNameFromClass($className); + + $results = $this->recordListOperations->read($modelName, $ids, $readOptions); + + return $this->serializer->denormalize($results, sprintf('%s[]', $className)); + } + + public function findOneBy( + string $className, + ?SearchDomainsInterface $searchDomains = null, + ?SearchReadOptionsInterface $searchReadOptions = null + ): ?BaseInterface { + $searchReadOptions = $searchReadOptions ?? new SearchReadOptions(); $searchReadOptions->setLimit(1); - $searchReadOptions->setFields($this->modelFieldsProvider->provide($className, [ - 'searchDomains' => $searchDomains, - ])); $results = $this->findBy($className, $searchDomains, $searchReadOptions); @@ -58,6 +80,13 @@ public function findBy( ): array { $modelName = $this->getModelNameFromClass($className); + $searchReadOptions = $searchReadOptions ?? new SearchReadOptions(); + + $this->processReadOptions($className, $searchReadOptions, [ + 'class' => __CLASS__, + 'method' => __METHOD__, + ]); + $results = $this->recordListOperations->search_read( $modelName, $searchDomains, @@ -94,4 +123,18 @@ public function getSerializer(): Serializer { return $this->serializer; } + + /** + * @template T of BaseInterface + * @param class-string $className + */ + private function processReadOptions( + string $className, + ReadOptionsInterface $readOptions, + array $context = [] + ): void { + $readOptions->setFields($this->modelFieldsProvider->provide($className, $context + [ + ModelFieldsProviderInterface::FIELDS_CONTEXT => $readOptions->getFields(), + ])); + } } diff --git a/src/Manager/ModelListManagerInterface.php b/src/Manager/ModelListManagerInterface.php index 49d5dd27..296f70a0 100644 --- a/src/Manager/ModelListManagerInterface.php +++ b/src/Manager/ModelListManagerInterface.php @@ -6,6 +6,7 @@ use FluxSE\OdooApiClient\Model\BaseInterface; use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Arguments\SearchDomainsInterface; +use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Options\ReadOptionsInterface; use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Options\SearchReadOptionsInterface; use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\RecordListOperationsInterface; use Symfony\Component\Serializer\Serializer; @@ -17,14 +18,34 @@ interface ModelListManagerInterface * @param class-string $className * @return T|null */ - public function find(string $className, int $id): ?BaseInterface; + public function find( + string $className, + int $id, + ?ReadOptionsInterface $readOptions = null + ): ?BaseInterface; + + /** + * @template T of BaseInterface + * @param class-string $className + * @param int[] $ids + * @return T[] + */ + public function findByIds( + string $className, + array $ids, + ?ReadOptionsInterface $readOptions = null + ): array; /** * @template T of BaseInterface * @param class-string $className * @return T|null */ - public function findOneBy(string $className, ?SearchDomainsInterface $searchDomains = null): ?BaseInterface; + public function findOneBy( + string $className, + ?SearchDomainsInterface $searchDomains = null, + ?SearchReadOptionsInterface $searchReadOptions = null + ): ?BaseInterface; /** * @template T of BaseInterface @@ -32,8 +53,8 @@ public function findOneBy(string $className, ?SearchDomainsInterface $searchDoma * @return T[] */ public function findBy( - string $className, - ?SearchDomainsInterface $searchDomains = null, + string $className, + ?SearchDomainsInterface $searchDomains = null, ?SearchReadOptionsInterface $searchReadOptions = null ): array; diff --git a/src/Provider/ModelFieldsProvider.php b/src/Provider/ModelFieldsProvider.php index 28bbf75f..642642b3 100644 --- a/src/Provider/ModelFieldsProvider.php +++ b/src/Provider/ModelFieldsProvider.php @@ -4,16 +4,31 @@ namespace FluxSE\OdooApiClient\Provider; +use FluxSE\OdooApiClient\Operations\Object\ExecuteKw\Options\ReadOptionsInterface; use ReflectionClass; +use Webmozart\Assert\Assert; final class ModelFieldsProvider implements ModelFieldsProviderInterface { public function provide(string $className, array $context): array { $fields = []; + if (isset($context[self::FIELDS_CONTEXT])) { + /** @var string[] $fields */ + $fields = $context[self::FIELDS_CONTEXT]; + + Assert::isArray($fields, 'The field context should be an array'); + } + $reflectionClass = new ReflectionClass($className); foreach ($reflectionClass->getProperties() as $property) { - $fields[] = $property->getName(); + $propertyName = $property->getName(); + + if (in_array($propertyName, $fields, true)) { + continue; + } + + $fields[] = $propertyName; } return $fields; diff --git a/src/Provider/ModelFieldsProviderInterface.php b/src/Provider/ModelFieldsProviderInterface.php index c86154f9..b27016b0 100644 --- a/src/Provider/ModelFieldsProviderInterface.php +++ b/src/Provider/ModelFieldsProviderInterface.php @@ -8,6 +8,8 @@ interface ModelFieldsProviderInterface { + public const FIELDS_CONTEXT = 'read_options'; + /** * @template T of BaseInterface * @param class-string $className diff --git a/src/Serializer/Factory/SerializerFactory.php b/src/Serializer/Factory/SerializerFactory.php index 2b297d1a..4973722b 100644 --- a/src/Serializer/Factory/SerializerFactory.php +++ b/src/Serializer/Factory/SerializerFactory.php @@ -12,6 +12,7 @@ use FluxSE\OdooApiClient\Serializer\OdooNormalizer; use FluxSE\OdooApiClient\Serializer\OdooRelationDenormalizer; use FluxSE\OdooApiClient\Serializer\OdooRelationNormalizer; +use FluxSE\OdooApiClient\Serializer\OdooRelationsDenormalizer; use FluxSE\OdooApiClient\Serializer\OdooRelationSingleDenormalizer; use FluxSE\OdooApiClient\Serializer\OdooRelationsNormalizer; use FluxSE\OdooApiClient\Serializer\XmlRpc\XmlRpcDecoder; @@ -57,6 +58,7 @@ public function setupNormalizers(): array ]); return [ new ArrayDenormalizer(), + new OdooRelationsDenormalizer(), new NullableDateTimeDenormalizer($dateTimeNormalizer), $dateTimeNormalizer, new OdooRelationsNormalizer(), diff --git a/src/Serializer/NullOdooRelationDenormalizer.php b/src/Serializer/NullOdooRelationDenormalizer.php index 16f93705..fa146622 100644 --- a/src/Serializer/NullOdooRelationDenormalizer.php +++ b/src/Serializer/NullOdooRelationDenormalizer.php @@ -8,8 +8,16 @@ use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +/** + * false ==> null + */ final class NullOdooRelationDenormalizer implements DenormalizerInterface { + public function getSupportedTypes(?string $format): array + { + return [OdooRelation::class => false]; + } + public function supportsDenormalization($data, $type, $format = null): bool { if ($type !== OdooRelation::class) { diff --git a/src/Serializer/NullableDateTimeDenormalizer.php b/src/Serializer/NullableDateTimeDenormalizer.php index e936ccb0..e4781eef 100644 --- a/src/Serializer/NullableDateTimeDenormalizer.php +++ b/src/Serializer/NullableDateTimeDenormalizer.php @@ -12,6 +12,15 @@ public function __construct(private DenormalizerInterface $dateTimeNormalizer) { } + public function getSupportedTypes(?string $format): array + { + return [ + \DateTimeInterface::class => false, + \DateTimeImmutable::class => false, + \DateTime::class => false, + ]; + } + public function denormalize($data, string $type, string $format = null, array $context = []) { return null; diff --git a/src/Serializer/OdooNormalizer.php b/src/Serializer/OdooNormalizer.php index 178ce6a0..ba4c0dc3 100644 --- a/src/Serializer/OdooNormalizer.php +++ b/src/Serializer/OdooNormalizer.php @@ -4,6 +4,10 @@ namespace FluxSE\OdooApiClient\Serializer; +use FluxSE\OdooApiClient\Api\FaultInterface; +use FluxSE\OdooApiClient\Api\RequestBodyInterface; +use FluxSE\OdooApiClient\Model\BaseInterface; +use FluxSE\OdooApiClient\Model\Common\Version; use FluxSE\OdooApiClient\Model\OdooRelation; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; @@ -12,6 +16,16 @@ final class OdooNormalizer extends ObjectNormalizer { public const NORMALIZE_FOR_UPDATE = 'normalize_for_update'; + public function getSupportedTypes(?string $format): array + { + return [ + BaseInterface::class => true, + RequestBodyInterface::class => true, + FaultInterface::class => true, + Version::class => true, + ]; + } + protected function setAttributeValue(object $object, string $attribute, mixed $value, string $format = null, array $context = []): void { /** diff --git a/src/Serializer/OdooRelationDenormalizer.php b/src/Serializer/OdooRelationDenormalizer.php index 05dc28c1..f40f0000 100644 --- a/src/Serializer/OdooRelationDenormalizer.php +++ b/src/Serializer/OdooRelationDenormalizer.php @@ -8,8 +8,16 @@ use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +/** + * [123, "Foo"] ==> new OdooRelation(123, "Foo") + */ final class OdooRelationDenormalizer implements DenormalizerInterface { + public function getSupportedTypes(?string $format): array + { + return [OdooRelation::class => false]; + } + public function supportsDenormalization($data, $type, $format = null): bool { if ($type !== OdooRelation::class) { diff --git a/src/Serializer/OdooRelationNormalizer.php b/src/Serializer/OdooRelationNormalizer.php index 9f9060cb..df1286a5 100644 --- a/src/Serializer/OdooRelationNormalizer.php +++ b/src/Serializer/OdooRelationNormalizer.php @@ -15,6 +15,11 @@ final class OdooRelationNormalizer implements NormalizerInterface, NormalizerAwa { use NormalizerAwareTrait; + public function getSupportedTypes(?string $format): array + { + return [OdooRelation::class => true]; + } + public function supportsNormalization($data, $format = null): bool { return $data instanceof OdooRelation; diff --git a/src/Serializer/OdooRelationSingleDenormalizer.php b/src/Serializer/OdooRelationSingleDenormalizer.php index 286d061c..32b43d8c 100644 --- a/src/Serializer/OdooRelationSingleDenormalizer.php +++ b/src/Serializer/OdooRelationSingleDenormalizer.php @@ -8,8 +8,16 @@ use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +/** + * 123 ==> new OdooRelation(123) + */ final class OdooRelationSingleDenormalizer implements DenormalizerInterface { + public function getSupportedTypes(?string $format): array + { + return [OdooRelation::class => false]; + } + public function supportsDenormalization($data, $type, $format = null): bool { if ($type !== OdooRelation::class) { diff --git a/src/Serializer/OdooRelationsDenormalizer.php b/src/Serializer/OdooRelationsDenormalizer.php new file mode 100644 index 00000000..d324b248 --- /dev/null +++ b/src/Serializer/OdooRelationsDenormalizer.php @@ -0,0 +1,51 @@ + [new OdooRelation(1), new OdooRelation(4)] + */ +final class OdooRelationsDenormalizer implements DenormalizerInterface +{ + public function getSupportedTypes(?string $format): array + { + return [OdooRelation::class => false]; + } + + public function supportsDenormalization($data, $type, $format = null): bool + { + if ($type !== OdooRelation::class) { + return false; + } + + if (false === is_array($data)) { + return false; + } + + if ($data !== array_filter($data, 'is_int')) { + return false; + } + + return true; + } + + public function denormalize($data, $type, $format = null, array $context = []): array + { + if (false === is_array($data)) { + throw new InvalidArgumentException('The data should be an array !'); + } + + $relations = []; + foreach ($data as $id) { + $relations[] = new OdooRelation($id); + } + + return $relations; + } +} diff --git a/src/Serializer/OdooRelationsNormalizer.php b/src/Serializer/OdooRelationsNormalizer.php index 03efecb8..ebd66de6 100644 --- a/src/Serializer/OdooRelationsNormalizer.php +++ b/src/Serializer/OdooRelationsNormalizer.php @@ -15,6 +15,11 @@ final class OdooRelationsNormalizer implements NormalizerInterface, NormalizerAw { use NormalizerAwareTrait; + public function getSupportedTypes(?string $format): array + { + return ['native-array' => true]; + } + public function supportsNormalization($data, string $format = null, array $context = []): bool { if (false === is_array($data)) { @@ -35,9 +40,6 @@ public function supportsNormalization($data, string $format = null, array $conte return false; } - /** - * OdooRelation[] $object - */ public function normalize($object, $format = null, array $context = []): array { if (!is_array($object)) { @@ -64,10 +66,6 @@ public function normalize($object, $format = null, array $context = []): array } } - if ([] === $relations) { - return []; - } - return $relations; } } diff --git a/tests/Manager/ModelListManagerTest.php b/tests/Manager/ModelListManagerTest.php index faf3d095..af0ba984 100644 --- a/tests/Manager/ModelListManagerTest.php +++ b/tests/Manager/ModelListManagerTest.php @@ -43,6 +43,13 @@ public function testFind(): void $partner = $this->modelListManager->find(Partner::class, $results[0]['id']); $this->assertInstanceOf(Partner::class, $partner); + $this->assertEquals($results[0]['id'], $partner->getId()); + } + + public function testFindByIds(): void + { + $partners = $this->modelListManager->findByIds(Partner::class, [1]); + $this->assertContainsOnlyInstancesOf(Partner::class, $partners); } public function testFindOneBy(): void diff --git a/tests/Operations/Object/ExecuteKw/ExecuteKwOperationsTrait.php b/tests/Operations/Object/ExecuteKw/ExecuteKwOperationsTrait.php index 218a7c0e..bf35dd6f 100644 --- a/tests/Operations/Object/ExecuteKw/ExecuteKwOperationsTrait.php +++ b/tests/Operations/Object/ExecuteKw/ExecuteKwOperationsTrait.php @@ -41,11 +41,11 @@ protected function buildModelFieldsProvider(): ModelFieldsProviderInterface 'account.move.line' => [ 'compute_all_tax', // @see https://github.com/odoo/odoo/issues/164139 ], - /*'account.move' => [ + 'account.move' => [ 'needed_terms', // @see https://github.com/odoo/odoo/issues/129493 'tax_totals', // @see https://github.com/odoo/odoo/issues/129494 ], - 'product.product' => [ + /*'product.product' => [ 'product_properties', // @see https://github.com/odoo/odoo/issues/145138 ],*/ ]; diff --git a/tests/Serializer/Model/Foo.php b/tests/Serializer/Model/Foo.php new file mode 100644 index 00000000..61edd321 --- /dev/null +++ b/tests/Serializer/Model/Foo.php @@ -0,0 +1,95 @@ +date = $date; + } + + public function getDate(): ?DateTimeInterface + { + return $this->date; + } + + /** + * @return OdooRelation[]|null + */ + #[SerializedName("message_ids")] + public function getMessageIds(): ?array + { + return $this->message_ids; + } + + /** + * @param OdooRelation[]|null $message_ids + */ + public function setMessageIds(?array $message_ids): void + { + $this->message_ids = $message_ids; + } + + public function hasMessageIds(OdooRelation $item): bool + { + if (null === $this->message_ids) { + return false; + } + + return in_array($item, $this->message_ids, true); + } + + public function addMessageIds(OdooRelation $item): void + { + if ($this->hasMessageIds($item)) { + return; + } + + if (null === $this->message_ids) { + $this->message_ids = []; + } + + $this->message_ids[] = $item; + } + + public function removeMessageIds(OdooRelation $item): void + { + if (null === $this->message_ids) { + $this->message_ids = []; + } + + if ($this->hasMessageIds($item)) { + $index = array_search($item, $this->message_ids, true); + unset($this->message_ids[$index]); + } + } + + public function setExternalId(?OdooRelation $externalId): void + { + $this->externalId = $externalId; + } + + public function getExternalId(): ?OdooRelation + { + return $this->externalId; + } + + public static function getOdooModelName(): string + { + return 'foo'; + } +} diff --git a/tests/Serializer/OdooDateTimeNormalizerTest.php b/tests/Serializer/OdooDateTimeNormalizerTest.php index 33403664..0d3fa9d5 100644 --- a/tests/Serializer/OdooDateTimeNormalizerTest.php +++ b/tests/Serializer/OdooDateTimeNormalizerTest.php @@ -4,15 +4,13 @@ use DateTimeImmutable; use DateTimeInterface; -use FluxSE\OdooApiClient\Model\OdooRelation; use FluxSE\OdooApiClient\Serializer\Factory\SerializerFactory; use PHPUnit\Framework\TestCase; use Symfony\Component\Serializer\Serializer; -use Tests\FluxSE\OdooApiClient\TestModel\Object\Res\Partner; +use Tests\FluxSE\OdooApiClient\Serializer\Model\Foo; class OdooDateTimeNormalizerTest extends TestCase { - /** @var Serializer */ private Serializer $serializer; protected function setUp(): void @@ -34,35 +32,26 @@ public function testDenormalizeInObject(): void { $arr = [ 'date' => '2023-07-24', - 'property_account_payable_id' => 10, - 'property_account_receivable_id' => 11, ]; - $partner = $this->serializer->denormalize($arr, Partner::class); + $foo = $this->serializer->denormalize($arr, Foo::class); - $expectedPartner = new Partner( - new OdooRelation(10), - new OdooRelation(11), - ); - $expectedPartner->setDate(new DateTimeImmutable('2023-07-24')); - $this->assertEquals($expectedPartner, $partner); + $expectedFoo = new Foo(); + + $expectedFoo->setDate(new DateTimeImmutable('2023-07-24')); + $this->assertEquals($expectedFoo, $foo); } public function testDenormalizeInObjectWithFalse(): void { $arr = [ 'date' => false, - 'property_account_payable_id' => 10, - 'property_account_receivable_id' => 11, ]; - $partner = $this->serializer->denormalize($arr, Partner::class); + $partner = $this->serializer->denormalize($arr, Foo::class); - $expectedPartner = new Partner( - new OdooRelation(10), - new OdooRelation(11), - ); - // $expectedPartner->setDate(null); - $this->assertEquals($expectedPartner, $partner); + $expectedFoo = new Foo(); + // $expectedFoo->setDate(null); + $this->assertEquals($expectedFoo, $partner); } }