diff --git a/.github/workflows/test-monorepo.yml b/.github/workflows/test-monorepo.yml index e45409836..27ecd3ebe 100644 --- a/.github/workflows/test-monorepo.yml +++ b/.github/workflows/test-monorepo.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: operating-system: [ ubuntu-latest ] - php-versions: [ '8.1', '8.2', '8.3' ] + php-versions: [ '8.0', '8.3' ] stability: [prefer-lowest, prefer-stable] services: rabbitmq: diff --git a/packages/Dbal/src/Attribute/DbalQueryBusinessMethod.php b/packages/Dbal/src/Attribute/DbalQuery.php similarity index 96% rename from packages/Dbal/src/Attribute/DbalQueryBusinessMethod.php rename to packages/Dbal/src/Attribute/DbalQuery.php index c9a921504..869ca7d09 100644 --- a/packages/Dbal/src/Attribute/DbalQueryBusinessMethod.php +++ b/packages/Dbal/src/Attribute/DbalQuery.php @@ -9,7 +9,7 @@ use Enqueue\Dbal\DbalConnectionFactory; #[Attribute(Attribute::TARGET_METHOD)] -class DbalQueryBusinessMethod +class DbalQuery { public function __construct( private string $sql, diff --git a/packages/Dbal/src/Attribute/DbalWriteBusinessMethod.php b/packages/Dbal/src/Attribute/DbalWrite.php similarity index 94% rename from packages/Dbal/src/Attribute/DbalWriteBusinessMethod.php rename to packages/Dbal/src/Attribute/DbalWrite.php index d7937a18d..9c19575e0 100644 --- a/packages/Dbal/src/Attribute/DbalWriteBusinessMethod.php +++ b/packages/Dbal/src/Attribute/DbalWrite.php @@ -8,7 +8,7 @@ use Enqueue\Dbal\DbalConnectionFactory; #[Attribute(Attribute::TARGET_METHOD)] -class DbalWriteBusinessMethod +class DbalWrite { public function __construct( private string $sql, diff --git a/packages/Dbal/src/DbaBusinessMethod/DbaBusinessMethodModule.php b/packages/Dbal/src/DbaBusinessMethod/DbaBusinessMethodModule.php index d4b877db4..3c7532f15 100644 --- a/packages/Dbal/src/DbaBusinessMethod/DbaBusinessMethodModule.php +++ b/packages/Dbal/src/DbaBusinessMethod/DbaBusinessMethodModule.php @@ -7,8 +7,8 @@ use Ecotone\AnnotationFinder\AnnotatedMethod; use Ecotone\AnnotationFinder\AnnotationFinder; use Ecotone\Dbal\Attribute\DbalParameter; -use Ecotone\Dbal\Attribute\DbalQueryBusinessMethod; -use Ecotone\Dbal\Attribute\DbalWriteBusinessMethod; +use Ecotone\Dbal\Attribute\DbalQuery; +use Ecotone\Dbal\Attribute\DbalWrite; use Ecotone\Messaging\Attribute\ModuleAnnotation; use Ecotone\Messaging\Config\Annotation\AnnotatedDefinitionReference; use Ecotone\Messaging\Config\Annotation\AnnotationModule; @@ -62,8 +62,8 @@ public static function create(AnnotationFinder $annotationRegistrationService, I { $connectionReferences = []; $gatewayProxyBuilders = []; - foreach ($annotationRegistrationService->findAnnotatedMethods(DbalWriteBusinessMethod::class) as $businessMethod) { - /** @var DbalWriteBusinessMethod $attribute */ + foreach ($annotationRegistrationService->findAnnotatedMethods(DbalWrite::class) as $businessMethod) { + /** @var DbalWrite $attribute */ $attribute = $businessMethod->getAnnotationForMethod(); $gateway = self::getGateway($businessMethod, $attribute); @@ -77,8 +77,8 @@ public static function create(AnnotationFinder $annotationRegistrationService, I $connectionReferences[] = $attribute->getConnectionReferenceName(); } - foreach ($annotationRegistrationService->findAnnotatedMethods(DbalQueryBusinessMethod::class) as $businessMethod) { - /** @var DbalQueryBusinessMethod $attribute */ + foreach ($annotationRegistrationService->findAnnotatedMethods(DbalQuery::class) as $businessMethod) { + /** @var DbalQuery $attribute */ $attribute = $businessMethod->getAnnotationForMethod(); $gateway = self::getGateway($businessMethod, $attribute); @@ -171,19 +171,19 @@ public function canHandle($extensionObject): bool return false; } - private static function getGateway(AnnotatedMethod $businessMethod, DbalWriteBusinessMethod|DbalQueryBusinessMethod $attribute): GatewayProxyBuilder + private static function getGateway(AnnotatedMethod $businessMethod, DbalWrite|DbalQuery $attribute): GatewayProxyBuilder { return GatewayProxyBuilder::create( AnnotatedDefinitionReference::getReferenceFor($businessMethod), $businessMethod->getClassName(), $businessMethod->getMethodName(), - $attribute instanceof DbalWriteBusinessMethod + $attribute instanceof DbalWrite ? self::getWriteRequestChannelName($attribute->getConnectionReferenceName()) : self::getQueryRequestChannelName($attribute->getConnectionReferenceName()) ); } - private static function getParameterConverters(DbalWriteBusinessMethod|DbalQueryBusinessMethod $attribute, InterfaceToCall $interface): array + private static function getParameterConverters(DbalWrite|DbalQuery $attribute, InterfaceToCall $interface): array { $parameterConverters = [ GatewayHeaderValueBuilder::create( diff --git a/packages/Dbal/src/DbaBusinessMethod/DbalBusinessMethodHandler.php b/packages/Dbal/src/DbaBusinessMethod/DbalBusinessMethodHandler.php index 555be3433..7dcdec4f6 100644 --- a/packages/Dbal/src/DbaBusinessMethod/DbalBusinessMethodHandler.php +++ b/packages/Dbal/src/DbaBusinessMethod/DbalBusinessMethodHandler.php @@ -11,6 +11,7 @@ use Ecotone\Messaging\Conversion\MediaType; use Ecotone\Messaging\Handler\ExpressionEvaluationService; use Ecotone\Messaging\Handler\TypeDescriptor; +use Ecotone\Messaging\Handler\UnionTypeDescriptor; use Ecotone\Messaging\Message; use Ecotone\Messaging\Support\MessageBuilder; use Enqueue\Dbal\DbalContext; @@ -110,7 +111,7 @@ private function getParameters(array $headers): array } } - $preparedParameters[$parameterName] = $parameterValue; + $preparedParameters[$parameterName] = $this->getParameterValueWithDefaultConversion($parameterValue); } /** Class/Method leve DbalParameters */ @@ -153,7 +154,7 @@ private function getParameterValue(DbalParameter $dbalParameter, array $context, ); } - return $parameterValue; + return $this->getParameterValueWithDefaultConversion($parameterValue); } private function autoResolveTypesIfNeeded(array $preparedParameters, array $preparedParameterTypes): array @@ -188,4 +189,33 @@ private function prepareGenerator(\Doctrine\DBAL\Result $query): Generator yield $row; } } + + private function getParameterValueWithDefaultConversion(mixed $parameterValue): mixed + { + $type = TypeDescriptor::createFromVariable($parameterValue); + if ($type->isClassOrInterface() && $this->conversionService->canConvert( + $type, + MediaType::createApplicationXPHP(), + UnionTypeDescriptor::createWith([TypeDescriptor::createStringType(), TypeDescriptor::createIntegerType()]), + MediaType::createApplicationXPHP() + )) { + return $this->conversionService->convert( + $parameterValue, + $type, + MediaType::createApplicationXPHP(), + UnionTypeDescriptor::createWith([TypeDescriptor::createStringType(), TypeDescriptor::createIntegerType()]), + MediaType::createApplicationXPHP(), + ); + } + + if ($parameterValue instanceof \DateTimeInterface) { + return $parameterValue->format('Y-m-d H:i:s.u'); + } + + if ($type->isClassOrInterface() && method_exists($parameterValue, '__toString')) { + return (string) $parameterValue; + } + + return $parameterValue; + } } diff --git a/packages/Dbal/tests/DbalMessagingTestCase.php b/packages/Dbal/tests/DbalMessagingTestCase.php index ca1530285..a988971ce 100644 --- a/packages/Dbal/tests/DbalMessagingTestCase.php +++ b/packages/Dbal/tests/DbalMessagingTestCase.php @@ -62,6 +62,7 @@ public function setUp(): void $this->deleteTable(DbalDocumentStore::ECOTONE_DOCUMENT_STORE, $connection); $this->deleteTable(DeduplicationInterceptor::DEFAULT_DEDUPLICATION_TABLE, $connection); $this->deleteTable('persons', $connection); + $this->deleteTable('activities', $connection); } protected function checkIfTableExists(Connection $connection, string $table): bool @@ -92,4 +93,17 @@ protected function setupUserTable(): void SQL); } } + + protected function setupActivityTable(): void + { + if (! $this->checkIfTableExists($this->getConnection(), 'activities')) { + $this->getConnection()->executeStatement(<<= :atOrAfter', + fetchMode: FetchMode::FIRST_COLUMN + )] + public function findAfterOrAt(string $activity, \DateTimeImmutable $atOrAfter): array; + + /** + * @return string[] + */ + #[DbalQuery( + 'SELECT person_id FROM activities WHERE type = :activity AND occurred_at < :atOrAfter', + fetchMode: FetchMode::FIRST_COLUMN + )] + public function findBefore(string $activity, \DateTimeImmutable $atOrAfter): array; + + #[DbalWrite('INSERT INTO activities VALUES (:personId, :activity, :time)')] + public function store(PersonId $personId, string $activity, \DateTimeImmutable $time): void; +} \ No newline at end of file diff --git a/packages/Dbal/tests/Fixture/DbalBusinessInterface/ClassLevelDbalParameterWriteApi.php b/packages/Dbal/tests/Fixture/DbalBusinessInterface/ClassLevelDbalParameterWriteApi.php index 161635bfa..2ff37af39 100644 --- a/packages/Dbal/tests/Fixture/DbalBusinessInterface/ClassLevelDbalParameterWriteApi.php +++ b/packages/Dbal/tests/Fixture/DbalBusinessInterface/ClassLevelDbalParameterWriteApi.php @@ -5,12 +5,12 @@ namespace Test\Ecotone\Dbal\Fixture\DbalBusinessInterface; use Ecotone\Dbal\Attribute\DbalParameter; -use Ecotone\Dbal\Attribute\DbalWriteBusinessMethod; +use Ecotone\Dbal\Attribute\DbalWrite; use Ecotone\Messaging\Conversion\MediaType; #[DbalParameter(name: 'roles', expression: "name === 'Johny' ? ['ROLE_ADMIN'] : []", convertToMediaType: MediaType::APPLICATION_JSON)] interface ClassLevelDbalParameterWriteApi { - #[DbalWriteBusinessMethod('INSERT INTO persons VALUES (:personId, :name, :roles)')] + #[DbalWrite('INSERT INTO persons VALUES (:personId, :name, :roles)')] public function registerUsingMethodParameters(int $personId, string $name): void; } diff --git a/packages/Dbal/tests/Fixture/DbalBusinessInterface/DateTimeToDayStringConverter.php b/packages/Dbal/tests/Fixture/DbalBusinessInterface/DateTimeToDayStringConverter.php new file mode 100644 index 000000000..cf5f48f9f --- /dev/null +++ b/packages/Dbal/tests/Fixture/DbalBusinessInterface/DateTimeToDayStringConverter.php @@ -0,0 +1,16 @@ +format('Y-m-d'); + } +} \ No newline at end of file diff --git a/packages/Dbal/tests/Fixture/DbalBusinessInterface/ParameterDbalTypeConversion.php b/packages/Dbal/tests/Fixture/DbalBusinessInterface/ParameterDbalTypeConversion.php index 3e3818cda..8ef6a14fa 100644 --- a/packages/Dbal/tests/Fixture/DbalBusinessInterface/ParameterDbalTypeConversion.php +++ b/packages/Dbal/tests/Fixture/DbalBusinessInterface/ParameterDbalTypeConversion.php @@ -6,25 +6,25 @@ use Doctrine\DBAL\Connection; use Ecotone\Dbal\Attribute\DbalParameter; -use Ecotone\Dbal\Attribute\DbalQueryBusinessMethod; +use Ecotone\Dbal\Attribute\DbalQuery; interface ParameterDbalTypeConversion { - #[DbalQueryBusinessMethod('SELECT person_id, name FROM persons WHERE person_id IN (:personIds)')] + #[DbalQuery('SELECT person_id, name FROM persons WHERE person_id IN (:personIds)')] public function getPersonsWith( #[DbalParameter(type: Connection::PARAM_INT_ARRAY)] array $personIds ): array; - #[DbalQueryBusinessMethod('SELECT person_id, name FROM persons WHERE person_id IN (:personIds)')] + #[DbalQuery('SELECT person_id, name FROM persons WHERE person_id IN (:personIds)')] #[DbalParameter('personIds', type: Connection::PARAM_INT_ARRAY, expression: '[1]')] public function getPersonsWithWithMethodLevelParameter(): array; - #[DbalQueryBusinessMethod('SELECT person_id, name FROM persons WHERE person_id IN (:personIds)')] + #[DbalQuery('SELECT person_id, name FROM persons WHERE person_id IN (:personIds)')] public function getPersonsWithAutoresolve( array $personIds ): array; - #[DbalQueryBusinessMethod('SELECT person_id, name FROM persons WHERE name IN (:names)')] + #[DbalQuery('SELECT person_id, name FROM persons WHERE name IN (:names)')] #[DbalParameter('names', expression: "['John']")] public function getPersonsWithMethodLevelParameterAndAutoresolve( array $names diff --git a/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonId.php b/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonId.php new file mode 100644 index 000000000..6e772952a --- /dev/null +++ b/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonId.php @@ -0,0 +1,18 @@ +id; + } +} \ No newline at end of file diff --git a/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonNameDTOConverter.php b/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonNameDTOConverter.php index 22c0ca1df..f64b68545 100644 --- a/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonNameDTOConverter.php +++ b/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonNameDTOConverter.php @@ -1,7 +1,5 @@ */ - #[DbalQueryBusinessMethod('SELECT person_id FROM persons ORDER BY person_id ASC LIMIT :limit OFFSET :offset')] + #[DbalQuery('SELECT person_id FROM persons ORDER BY person_id ASC LIMIT :limit OFFSET :offset')] public function getPersonIds(int $limit, int $offset): array; /** * @return int[] */ - #[DbalQueryBusinessMethod( + #[DbalQuery( 'SELECT person_id FROM persons ORDER BY person_id ASC LIMIT :limit OFFSET :offset', fetchMode: FetchMode::FIRST_COLUMN )] public function getExtractedPersonIds(int $limit, int $offset): array; - #[DbalQueryBusinessMethod( + #[DbalQuery( 'SELECT COUNT(*) FROM persons', fetchMode: FetchMode::FIRST_COLUMN_OF_FIRST_ROW )] public function countPersons(): int; - #[DbalQueryBusinessMethod('SELECT person_id, name FROM persons LIMIT :limit OFFSET :offset')] + #[DbalQuery('SELECT person_id, name FROM persons LIMIT :limit OFFSET :offset')] public function getNameList(int $limit, int $offset): array; - #[DbalQueryBusinessMethod( + #[DbalQuery( 'SELECT person_id, name FROM persons WHERE person_id = :personId', fetchMode: FetchMode::FIRST_ROW )] public function getNameDTO(int $personId): PersonNameDTO; - #[DbalQueryBusinessMethod( + #[DbalQuery( 'SELECT person_id, name FROM persons WHERE person_id = :personId', fetchMode: FetchMode::FIRST_ROW, replyContentType: MediaType::APPLICATION_JSON )] public function getNameDTOInJson(int $personId): string; - #[DbalQueryBusinessMethod( + #[DbalQuery( 'SELECT person_id, name FROM persons WHERE person_id = :personId', fetchMode: FetchMode::FIRST_ROW )] public function getNameDTOOrNull(int $personId): PersonNameDTO|null; - #[DbalQueryBusinessMethod( + #[DbalQuery( 'SELECT person_id, name FROM persons WHERE person_id = :personId', fetchMode: FetchMode::FIRST_ROW )] @@ -62,13 +62,13 @@ public function getNameDTOOrFalse(int $personId): PersonNameDTO|false; /** * @return PersonNameDTO[] */ - #[DbalQueryBusinessMethod('SELECT person_id, name FROM persons LIMIT :limit OFFSET :offset')] + #[DbalQuery('SELECT person_id, name FROM persons LIMIT :limit OFFSET :offset')] public function getNameListDTO(int $limit, int $offset): array; /** * @return iterable */ - #[DbalQueryBusinessMethod( + #[DbalQuery( 'SELECT person_id, name FROM persons ORDER BY person_id ASC', fetchMode: FetchMode::ITERATE )] diff --git a/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonWriteApi.php b/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonService.php similarity index 64% rename from packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonWriteApi.php rename to packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonService.php index 32a9b95ea..65ce5bcec 100644 --- a/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonWriteApi.php +++ b/packages/Dbal/tests/Fixture/DbalBusinessInterface/PersonService.php @@ -5,27 +5,27 @@ namespace Test\Ecotone\Dbal\Fixture\DbalBusinessInterface; use Ecotone\Dbal\Attribute\DbalParameter; -use Ecotone\Dbal\Attribute\DbalWriteBusinessMethod; +use Ecotone\Dbal\Attribute\DbalWrite; use Ecotone\Messaging\Conversion\MediaType; -interface PersonWriteApi +interface PersonService { - #[DbalWriteBusinessMethod('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] + #[DbalWrite('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] public function insert(int $personId, string $name): void; - #[DbalWriteBusinessMethod('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] + #[DbalWrite('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] public function insertWithParameterName( #[DbalParameter(name: 'personId')] int $id, string $name ): void; - #[DbalWriteBusinessMethod('UPDATE persons SET name = :name WHERE person_id = :personId')] + #[DbalWrite('UPDATE persons SET name = :name WHERE person_id = :personId')] public function changeName(int $personId, string $name): int; /** * @param string[] $roles */ - #[DbalWriteBusinessMethod('UPDATE persons SET roles = :roles WHERE person_id = :personId')] + #[DbalWrite('UPDATE persons SET roles = :roles WHERE person_id = :personId')] public function changeRoles( int $personId, #[DbalParameter(convertToMediaType: MediaType::APPLICATION_JSON)] array $roles @@ -34,29 +34,29 @@ public function changeRoles( /** * @param PersonRole[] $roles */ - #[DbalWriteBusinessMethod('UPDATE persons SET roles = :roles WHERE person_id = :personId')] + #[DbalWrite('UPDATE persons SET roles = :roles WHERE person_id = :personId')] public function changeRolesWithValueObjects( int $personId, #[DbalParameter(convertToMediaType: MediaType::APPLICATION_JSON)] array $roles ): void; - #[DbalWriteBusinessMethod('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] + #[DbalWrite('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] public function insertWithExpression( int $personId, #[DbalParameter(expression: 'payload.toLowerCase()')] PersonName $name ): void; - #[DbalWriteBusinessMethod('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] + #[DbalWrite('INSERT INTO persons VALUES (:personId, :name, DEFAULT)')] public function insertWithServiceExpression( int $personId, #[DbalParameter(expression: "reference('converter').normalize(payload)")] PersonName $name ): void; - #[DbalWriteBusinessMethod('INSERT INTO persons VALUES (:personId, :name, :roles)')] + #[DbalWrite('INSERT INTO persons VALUES (:personId, :name, :roles)')] #[DbalParameter(name: 'roles', expression: "['ROLE_ADMIN']", convertToMediaType: MediaType::APPLICATION_JSON)] public function registerAdmin(int $personId, string $name): void; - #[DbalWriteBusinessMethod('INSERT INTO persons VALUES (:personId, :name, :roles)')] + #[DbalWrite('INSERT INTO persons VALUES (:personId, :name, :roles)')] #[DbalParameter(name: 'roles', expression: "name === 'Johny' ? ['ROLE_ADMIN'] : []", convertToMediaType: MediaType::APPLICATION_JSON)] public function registerUsingMethodParameters(int $personId, string $name): void; } diff --git a/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalParameterTypeTest.php b/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalParameterTypeTest.php index 88f70de80..f10d13f98 100644 --- a/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalParameterTypeTest.php +++ b/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalParameterTypeTest.php @@ -11,10 +11,11 @@ use Ecotone\Messaging\Config\ServiceConfiguration; use Enqueue\Dbal\DbalConnectionFactory; use Test\Ecotone\Dbal\DbalMessagingTestCase; +use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\DateTimeToDayStringConverter; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\ParameterDbalTypeConversion; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonNameDTOConverter; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonRoleConverter; -use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonWriteApi; +use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonService; use Test\Ecotone\Dbal\Fixture\ORM\Person\Person; /** @@ -25,16 +26,16 @@ final class DbalParameterTypeTest extends DbalMessagingTestCase public function test_using_predefined_parameter_type() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(ParameterDbalTypeConversion::class); - $this->assertSame( + $this->assertEquals( [], $personQueryGateway->getPersonsWith([2]) ); - $this->assertSame( + $this->assertEquals( [['person_id' => 1, 'name' => 'John']], $personQueryGateway->getPersonsWith([1]) ); @@ -43,16 +44,16 @@ public function test_using_predefined_parameter_type() public function test_using_auto_resolved_parameter_type() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(ParameterDbalTypeConversion::class); - $this->assertSame( + $this->assertEquals( [], $personQueryGateway->getPersonsWithAutoresolve([2]) ); - $this->assertSame( + $this->assertEquals( [['person_id' => 1, 'name' => 'John']], $personQueryGateway->getPersonsWithAutoresolve([1]) ); @@ -61,12 +62,12 @@ public function test_using_auto_resolved_parameter_type() public function test_using_predefined_parameter_type_on_method_level_attribute() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(ParameterDbalTypeConversion::class); - $this->assertSame( + $this->assertEquals( [['person_id' => 1, 'name' => 'John']], $personQueryGateway->getPersonsWithWithMethodLevelParameter() ); @@ -75,12 +76,12 @@ public function test_using_predefined_parameter_type_on_method_level_attribute() public function test_using_predefined_parameter_type_on_method_level_attribute_and_autoresolve() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(ParameterDbalTypeConversion::class); - $this->assertSame( + $this->assertEquals( [['person_id' => 1, 'name' => 'John']], $personQueryGateway->getPersonsWithMethodLevelParameterAndAutoresolve(['John']) ); @@ -96,6 +97,7 @@ private function bootstrapEcotone(): FlowTestSupport DbalConnectionFactory::class => $this->getORMConnectionFactory([__DIR__.'/../Fixture/ORM/Person']), PersonRoleConverter::class => new PersonRoleConverter(), PersonNameDTOConverter::class => new PersonNameDTOConverter(), + DateTimeToDayStringConverter::class => new DateTimeToDayStringConverter(), ], ), configuration: ServiceConfiguration::createWithDefaults() diff --git a/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalQueryBusinessMethodTest.php b/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalQueryBusinessMethodTest.php index e77533cd1..de55ca19f 100644 --- a/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalQueryBusinessMethodTest.php +++ b/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalQueryBusinessMethodTest.php @@ -11,11 +11,12 @@ use Ecotone\Messaging\Config\ServiceConfiguration; use Enqueue\Dbal\DbalConnectionFactory; use Test\Ecotone\Dbal\DbalMessagingTestCase; +use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\DateTimeToDayStringConverter; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonNameDTO; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonNameDTOConverter; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonQueryApi; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonRoleConverter; -use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonWriteApi; +use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonService; use Test\Ecotone\Dbal\Fixture\ORM\Person\Person; /** @@ -23,20 +24,15 @@ */ final class DbalQueryBusinessMethodTest extends DbalMessagingTestCase { - /** - * - automatic paramter binding based on type - */ - - public function test_fetching_data_from_database() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(PersonQueryApi::class); - $this->assertSame( + $this->assertEquals( [['person_id' => 1, 'name' => 'John']], $personQueryGateway->getNameList(1, 0) ); @@ -45,13 +41,13 @@ public function test_fetching_data_from_database() public function test_fetching_list_of_scalar_types() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personWriteGateway->insert(2, 'Marco'); $personQueryGateway = $ecotoneLite->getGateway(PersonQueryApi::class); - $this->assertSame( + $this->assertEquals( [['person_id' => 1], ['person_id' => 2]], $personQueryGateway->getPersonIds(2, 0) ); @@ -60,13 +56,13 @@ public function test_fetching_list_of_scalar_types() public function test_fetching_using_first_column_mode() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personWriteGateway->insert(2, 'Marco'); $personQueryGateway = $ecotoneLite->getGateway(PersonQueryApi::class); - $this->assertSame( + $this->assertEquals( [1, 2], $personQueryGateway->getExtractedPersonIds(2, 0) ); @@ -75,13 +71,13 @@ public function test_fetching_using_first_column_mode() public function test_fetching_using_first_column_mode_of_first_row() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personWriteGateway->insert(2, 'Marco'); $personQueryGateway = $ecotoneLite->getGateway(PersonQueryApi::class); - $this->assertSame( + $this->assertEquals( 2, $personQueryGateway->countPersons() ); @@ -90,8 +86,8 @@ public function test_fetching_using_first_column_mode_of_first_row() public function test_fetching_using_single_row_result() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(PersonQueryApi::class); @@ -120,8 +116,8 @@ public function test_fetching_using_single_row_result_allowing_false() public function test_fetching_and_converting_list_to_dtos() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(PersonQueryApi::class); @@ -134,22 +130,22 @@ public function test_fetching_and_converting_list_to_dtos() public function test_fetching_to_specific_format() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personWriteGateway->insert(1, 'John'); $personQueryGateway = $ecotoneLite->getGateway(PersonQueryApi::class); $this->assertEquals( - '{"person_id":1,"name":"John"}', - $personQueryGateway->getNameDTOInJson(1) + \json_decode('{"person_id":1,"name":"John"}', true), + \json_decode($personQueryGateway->getNameDTOInJson(1), true) ); } public function test_using_iterator_to_fetch_results() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personWriteGateway */ - $personWriteGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personWriteGateway */ + $personWriteGateway = $ecotoneLite->getGateway(PersonService::class); $personDTOs = [new PersonNameDTO(1, 'John1'), new PersonNameDTO(2, 'John2')]; ; $personWriteGateway->insert(1, 'John1'); @@ -174,6 +170,7 @@ private function bootstrapEcotone(): FlowTestSupport DbalConnectionFactory::class => $this->getORMConnectionFactory([__DIR__.'/../Fixture/ORM/Person']), PersonRoleConverter::class => new PersonRoleConverter(), PersonNameDTOConverter::class => new PersonNameDTOConverter(), + DateTimeToDayStringConverter::class => new DateTimeToDayStringConverter(), ], ), configuration: ServiceConfiguration::createWithDefaults() diff --git a/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalWriteBusinessMethodTest.php b/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalWriteBusinessMethodTest.php index b0e0a619f..a50cfdf38 100644 --- a/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalWriteBusinessMethodTest.php +++ b/packages/Dbal/tests/Integration/DbalBusinessMethod/DbalWriteBusinessMethodTest.php @@ -12,12 +12,13 @@ use Enqueue\Dbal\DbalConnectionFactory; use Test\Ecotone\Dbal\DbalMessagingTestCase; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\ClassLevelDbalParameterWriteApi; +use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\DateTimeToDayStringConverter; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonName; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonNameDTOConverter; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonNameNormalizer; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonRole; use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonRoleConverter; -use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonWriteApi; +use Test\Ecotone\Dbal\Fixture\DbalBusinessInterface\PersonService; use Test\Ecotone\Dbal\Fixture\ORM\Person\Person; /** @@ -28,8 +29,8 @@ final class DbalWriteBusinessMethodTest extends DbalMessagingTestCase public function test_write_statement_with_no_return_and_automatic_parameter_binding() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->insert(1, 'John'); @@ -42,8 +43,8 @@ public function test_write_statement_with_no_return_and_automatic_parameter_bind public function test_write_statement_with_no_return_and_manual_parameter_binding() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->insertWithParameterName(1, 'John'); @@ -56,8 +57,8 @@ public function test_write_statement_with_no_return_and_manual_parameter_binding public function test_write_statement_with_return_of_amount_of_changed_rows() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->insert(1, 'John'); $this->assertSame( @@ -75,8 +76,8 @@ public function test_write_statement_with_return_of_amount_of_changed_rows() public function test_using_custom_dbal_parameter_conversion_media_type() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->insert(1, 'John'); $personGateway->changeRoles(1, ['ROLE_ADMIN']); @@ -91,8 +92,8 @@ public function test_using_custom_dbal_parameter_conversion_media_type() public function test_using_custom_dbal_parameter_conversion_media_type_with_value_objects() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->insert(1, 'John'); $personGateway->changeRolesWithValueObjects(1, [new PersonRole('ROLE_ADMIN')]); @@ -106,8 +107,8 @@ public function test_using_custom_dbal_parameter_conversion_media_type_with_valu public function test_using_expression_language_on_parameter_value() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->insertWithExpression(1, new PersonName('John')); @@ -120,8 +121,8 @@ public function test_using_expression_language_on_parameter_value() public function test_using_expression_language_using_service() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->insertWithServiceExpression(1, new PersonName('John')); @@ -134,8 +135,8 @@ public function test_using_expression_language_using_service() public function test_using_expression_language_with_method_level_dbal_parameter() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->registerAdmin(1, 'John'); @@ -148,8 +149,8 @@ public function test_using_expression_language_with_method_level_dbal_parameter( public function test_using_expression_language_with_method_level_dbal_parameter_and_parameters_in_expression() { $ecotoneLite = $this->bootstrapEcotone(); - /** @var PersonWriteApi $personGateway */ - $personGateway = $ecotoneLite->getGateway(PersonWriteApi::class); + /** @var PersonService $personGateway */ + $personGateway = $ecotoneLite->getGateway(PersonService::class); $personGateway->registerUsingMethodParameters(1, 'Johny'); $this->assertSame( @@ -194,6 +195,7 @@ private function bootstrapEcotone(): FlowTestSupport PersonRoleConverter::class => new PersonRoleConverter(), PersonNameDTOConverter::class => new PersonNameDTOConverter(), 'converter' => new PersonNameNormalizer(), + DateTimeToDayStringConverter::class => new DateTimeToDayStringConverter(), ], ), configuration: ServiceConfiguration::createWithDefaults() diff --git a/packages/Dbal/tests/Integration/DbalBusinessMethod/InbuiltConvertersTest.php b/packages/Dbal/tests/Integration/DbalBusinessMethod/InbuiltConvertersTest.php new file mode 100644 index 000000000..f4aac281c --- /dev/null +++ b/packages/Dbal/tests/Integration/DbalBusinessMethod/InbuiltConvertersTest.php @@ -0,0 +1,106 @@ +bootstrapEcotone(); + /** @var ActivityService $activityGateway */ + $activityGateway = $ecotoneLite->getGateway(ActivityService::class); + $activityGateway->add('1', 'registered_at', new \DateTimeImmutable('2020-01-01 10:00:00')); + + $this->assertEquals( + [], + $activityGateway->findAfterOrAt('registered_at', new \DateTimeImmutable('2020-01-01 10:00:01')) + ); + + $this->assertEquals( + ['1'], + $activityGateway->findAfterOrAt('registered_at', new \DateTimeImmutable('2020-01-01 10:00:00')) + ); + } + + public function test_using_defined_converter_over_default_one() + { + $ecotoneLite = $this->bootstrapEcotone([ + DateTimeToDayStringConverter::class => new DateTimeToDayStringConverter() + ]); + /** @var ActivityService $activityGateway */ + $activityGateway = $ecotoneLite->getGateway(ActivityService::class); + /** This will be converted to 2020-01-02 00:00:00 */ + $activityGateway->add('1', 'registered_at', new \DateTimeImmutable('2020-01-02 01:00:00')); + + $this->assertEquals( + [], + /** This will be converted to 2020-01-02 00:00:00 */ + $activityGateway->findBefore('registered_at', new \DateTimeImmutable('2020-01-02 23:59:59')) + ); + + $this->assertEquals( + ['1'], + /** This will be converted to 2020-01-03 00:00:00 */ + $activityGateway->findBefore('registered_at', new \DateTimeImmutable('2020-01-03 00:00:00')) + ); + } + + public function test_using_to_string_method_for_object_conversion_if_available() + { + $ecotoneLite = $this->bootstrapEcotone(); + /** @var ActivityService $activityGateway */ + $activityGateway = $ecotoneLite->getGateway(ActivityService::class); + $activityGateway->store(new PersonId('1'), 'registered_at', new \DateTimeImmutable('2020-01-01 10:00:00')); + + $this->assertEquals( + [], + $activityGateway->findAfterOrAt('registered_at', new \DateTimeImmutable('2020-01-01 10:00:01')) + ); + + $this->assertEquals( + ['1'], + $activityGateway->findAfterOrAt('registered_at', new \DateTimeImmutable('2020-01-01 10:00:00')) + ); + } + + private function bootstrapEcotone(array $services = []): FlowTestSupport + { + $this->setupActivityTable(); + + return EcotoneLite::bootstrapFlowTesting( + array_merge([ActivityService::class], array_keys($services)), + array_merge( + [ + DbalConnectionFactory::class => DbalConnection::create($this->getConnection()), + ], + $services + ), + configuration: ServiceConfiguration::createWithDefaults() + ->withSkippedModulePackageNames(ModulePackageList::allPackagesExcept([ModulePackageList::DBAL_PACKAGE, ModulePackageList::JMS_CONVERTER_PACKAGE])), + pathToRootCatalog: __DIR__ . '/../../', + addInMemoryStateStoredRepository: false + ); + } +}