From 794b3a56c37a99b380bcd5833541ae7e3cedd6d4 Mon Sep 17 00:00:00 2001 From: Mattia Basone Date: Mon, 17 Feb 2025 16:30:02 +0100 Subject: [PATCH] Align with flix tech v2 (#7) * fixing php 8.4 deprecations (#88) Co-authored-by: mihai.leu * Bump actions/download-artifact from 2 to 4.1.7 in /.github/workflows (#85) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 2 to 4.1.7. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v2...v4.1.7) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Thomas Ploch * [PHP] Drop PHP 7.4 & 8.0 (#90) - Upgrade all dependencies - Refurbish code to pass CI tests again * [DOC] Update README.md with correct versions * add logical types and attributes support * add test and fix error on AvroSymbols * restore AvroSerDeEncoderTest.php * fix tests imports --------- Signed-off-by: dependabot[bot] Co-authored-by: mihaileu <54336101+mihaileu@users.noreply.github.com> Co-authored-by: mihai.leu Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Thomas Ploch Co-authored-by: Thomas Ploch --- .env.dist => .env | 0 .github/workflows/checks.yml | 72 ++-- .gitignore | 1 - .php-cs-fixer.dist.php | 3 +- Dockerfile | 4 +- Makefile | 19 +- README.md | 6 +- benchmarks/AvroEncodingBench.php | 104 +++-- benchmarks/bootstrap.php | 3 +- composer.json | 14 +- docker-compose.yml | 1 - examples/SchemaBuilder.php | 2 +- examples/SchemaGenerator.php | 12 +- examples/SymfonySerializer.php | 6 +- .../Symfony/Serializer/AvroSerDeEncoder.php | 5 +- .../NameConverter/AvroNameConverter.php | 36 +- .../NameConverter/PropertyNameMap.php | 4 +- phpunit.xml.dist | 17 +- src/Common.php | 17 +- .../DefaultRecordSerializerFactory.php | 2 +- src/Objects/DefaultSchemaGeneratorFactory.php | 5 +- src/Objects/Definition.php | 5 +- .../Exceptions/AvroDecodingException.php | 3 +- .../Exceptions/AvroEncodingException.php | 3 +- src/Objects/Exceptions/Exceptions.php | 7 +- src/Objects/RecordSerializer.php | 50 +-- src/Objects/Schema.php | 10 +- src/Objects/Schema/ComplexType.php | 13 +- .../Schema/Generation/AnnotationReader.php | 14 +- .../Generation/Annotations/AvroAliases.php | 10 +- .../Generation/Annotations/AvroDefault.php | 16 +- .../Schema/Generation/Annotations/AvroDoc.php | 14 +- .../Generation/Annotations/AvroItems.php | 3 - .../Generation/Annotations/AvroName.php | 14 +- .../Generation/Annotations/AvroNamespace.php | 14 +- .../Generation/Annotations/AvroOrder.php | 14 +- .../Generation/Annotations/AvroSize.php | 14 +- .../Generation/Annotations/AvroSymbols.php | 10 +- .../Annotations/AvroTargetClass.php | 5 +- .../Generation/Annotations/AvroType.php | 16 +- .../Generation/Annotations/AvroValues.php | 3 - .../Annotations/ContainsOnlyTypes.php | 7 +- .../Schema/Generation/AttributeReader.php | 3 + .../Schema/Generation/Attributes/AvroDoc.php | 2 +- .../Generation/Attributes/AvroItems.php | 2 +- .../Generation/Attributes/AvroSymbols.php | 9 +- .../Schema/Generation/Attributes/AvroType.php | 2 +- .../Schema/Generation/SchemaAttribute.php | 5 +- .../Generation/SchemaAttributeReader.php | 9 +- .../Schema/Generation/SchemaAttributes.php | 14 +- .../Schema/Generation/SchemaGenerator.php | 22 +- src/Objects/Schema/Generation/Type.php | 12 +- src/Objects/Schema/Generation/TypeMapper.php | 2 +- src/Objects/Schema/NamedType.php | 5 +- src/Objects/Schema/PrimitiveType.php | 5 +- src/Objects/Schema/Record/Field.php | 14 +- src/Objects/Schema/Record/FieldDefault.php | 5 +- src/Objects/Schema/Record/FieldOption.php | 25 +- src/Objects/Schema/RecordType.php | 2 +- src/Objects/Schema/UnionType.php | 2 +- src/Objects/SchemaResolverInterface.php | 11 +- .../SchemaResolvers/CallableResolver.php | 13 +- src/Objects/SchemaResolvers/ChainResolver.php | 7 +- .../DefinitionInterfaceResolver.php | 18 +- src/Objects/SchemaResolvers/FileResolver.php | 22 +- src/Protocol.php | 10 +- src/Serialize.php | 40 +- test/AbstractFunctionalTestCase.php | 15 +- .../Serializer/AvroNameConverterTest.php | 12 +- .../Serializer/AvroSerDeEncoderTest.php | 52 ++- .../Serializer/Fixture/SampleUserRecord.php | 2 + .../DefaultRecordSerializerFactoryTest.php | 2 +- .../RecordSerializerIntegrationTest.php | 16 +- test/Objects/RecordSerializerTest.php | 105 ++--- test/Objects/Schema/ArrayTypeTest.php | 3 +- test/Objects/Schema/EnumTypeTest.php | 6 +- test/Objects/Schema/FixedTypeTest.php | 3 +- .../Fixture/ArraysWithComplexType.php | 32 +- .../Schema/Generation/Fixture/EmptyRecord.php | 8 + .../Fixture/MapsWithComplexType.php | 31 ++ .../Generation/Fixture/PrimitiveTypes.php | 31 ++ .../Fixture/RecordWithComplexTypes.php | 54 +++ .../Fixture/RecordWithRecordType.php | 21 +- .../Generation/Fixture/SimpleRecord.php | 15 +- .../Schema/Generation/SchemaGeneratorTest.php | 375 ++++++++---------- test/Objects/Schema/LogicalTypeTest.php | 14 +- test/Objects/Schema/MapTypeTest.php | 3 +- test/Objects/Schema/PrimitiveTypeTest.php | 10 +- test/Objects/Schema/RecordTypeTest.php | 3 +- .../SchemaResolvers/CallableResolverTest.php | 4 +- .../SchemaResolvers/ChainResolverTest.php | 21 +- .../DefinitionInterfaceResolverTest.php | 30 +- .../SchemaResolvers/FileResolverTest.php | 4 +- test/ProtocolTest.php | 4 +- test/SerializeTest.php | 2 +- test/bootstrap.php | 4 +- 96 files changed, 757 insertions(+), 964 deletions(-) rename .env.dist => .env (100%) diff --git a/.env.dist b/.env similarity index 100% rename from .env.dist rename to .env diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 2219210..c0a52d3 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -6,20 +6,21 @@ on: - master jobs: build-source: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install phars run: | make install-phars - name: Upload source directory - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: source + include-hidden-files: true path: . php-xdebug-docker: needs: @@ -29,26 +30,29 @@ jobs: php: - version: '8.1' - xdebug: '3.1.5' + xdebug: '3.4.0' - version: '8.2' - xdebug: '3.2.1' + xdebug: '3.4.0' - version: '8.3' - xdebug: '3.3.1' - runs-on: ubuntu-20.04 + xdebug: '3.4.0' + - + version: '8.4' + xdebug: '3.4.0' + runs-on: ubuntu-22.04 steps: - name: Download sources - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: source - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Build - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v6 with: context: . file: ./Dockerfile @@ -67,12 +71,12 @@ jobs: docker save php-avro-serde:${{ matrix.php.version }} -o php-avro-serde-${{ matrix.php.version }}.tgz - name: Upload docker image - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: php-avro-serde-${{ matrix.php.version }} path: php-avro-serde-${{ matrix.php.version }}.tgz ci-checks: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: - php-xdebug-docker strategy: @@ -87,6 +91,9 @@ jobs: - version: '8.3' composer: --prefer-lowest + - + version: '8.4' + composer: --prefer-lowest - version: '8.1' composer: --prefer-stable @@ -94,20 +101,23 @@ jobs: version: '8.2' composer: --prefer-stable - - version: '8.2' + version: '8.3' + composer: --prefer-stable + - + version: '8.4' composer: --prefer-stable steps: - name: Download sources - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: source - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Download docker image - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: php-avro-serde-${{ matrix.php.version }} - @@ -122,41 +132,41 @@ jobs: composer update --no-interaction --no-scripts --no-ansi ${{ matrix.php.composer }} - name: Run Static analysis - if: ${{ matrix.php.version == '7.4' && matrix.php.composer == '--prefer-stable' }} + if: ${{ matrix.php.version == '8.3' && matrix.php.composer == '--prefer-stable' }} run: | chmod a+x bin/phpstan.phar bin/php-cs-fixer.phar docker run -i --rm --net=host --sig-proxy=true --pid=host \ -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:${{ matrix.php.version }} \ - bin/phpstan.phar analyse + bin/phpstan.phar analyse --memory-limit 4G docker run -i --rm --net=host --sig-proxy=true --pid=host \ -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:${{ matrix.php.version }} \ bin/php-cs-fixer.phar fix --config=.php-cs-fixer.dist.php --diff -v --dry-run --path-mode=intersection --allow-risky=yes \ src test - name: Run PHPUnit - if: ${{ !(matrix.php.version == '7.4' && matrix.php.composer == '--prefer-stable') }} + if: ${{ !(matrix.php.version == '8.3' && matrix.php.composer == '--prefer-stable') }} run: | docker run -i --rm --net=host --sig-proxy=true --pid=host \ -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:${{ matrix.php.version }} \ vendor/bin/phpunit --exclude-group integration - name: Run PHPUnit with Coverage Report - if: ${{ matrix.php.version == '7.4' && matrix.php.composer == '--prefer-stable' }} + if: ${{ matrix.php.version == '8.3' && matrix.php.composer == '--prefer-stable' }} run: | mkdir -p build docker run -i --rm --net=host --sig-proxy=true --pid=host \ -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:${{ matrix.php.version }} \ -d xdebug.mode=coverage vendor/bin/phpunit --exclude-group integration --coverage-clover=build/coverage.clover --coverage-text - name: Publish code coverage - if: ${{ matrix.php.version == '7.4' && matrix.php.composer == '--prefer-stable' && github.event_name == 'push' && github.ref == 'refs/heads/master' }} - uses: paambaati/codeclimate-action@v3.0.0 + if: ${{ matrix.php.version == '8.3' && matrix.php.composer == '--prefer-stable' && github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: paambaati/codeclimate-action@v9 env: CC_TEST_REPORTER_ID: ${{secrets.CODE_CLIMATE_REPORTER_ID}} with: coverageLocations: | ${{github.workspace}}/build/coverage.clover:clover confluent-integration: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: - php-xdebug-docker strategy: @@ -164,33 +174,31 @@ jobs: confluent: - version: latest - - - version: 4.1.4 - version: 5.5.2 steps: - name: Download sources - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: source - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Download docker image - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: - name: php-avro-serde-8.1 + name: php-avro-serde-8.3 - name: Load docker image run: | - docker load -i php-avro-serde-8.1.tgz + docker load -i php-avro-serde-8.3.tgz - name: Install vendors run: | docker run -i --rm --net=host --sig-proxy=true --pid=host \ - -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:8.1 \ + -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:8.3 \ composer update --no-interaction --no-scripts --no-ansi --prefer-stable - name: Run PHPUnit Integration @@ -200,5 +208,5 @@ jobs: chmod a+x bin/wait-for-all.sh bin/wait-for-it.sh make platform docker run -i --rm --net=host --sig-proxy=true --pid=host \ - -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:8.1 \ + -v "${GITHUB_WORKSPACE}":"${GITHUB_WORKSPACE}" -w "${GITHUB_WORKSPACE}" php-avro-serde:8.3 \ vendor/bin/phpunit --group integration diff --git a/.gitignore b/.gitignore index bcde796..ac6d8d5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ composer.lock # Custom entries .php_cs*.cache -.env variables.mk build/ ocular.phar diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 474bb52..643a21f 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -23,7 +23,8 @@ 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all', 'strict' => false], 'ordered_class_elements' => true, 'php_unit_method_casing' => false, + 'fully_qualified_strict_types' => false, ]) ->setFinder($finder) - ->setCacheFile('.php_cs.' . (string) getenv('PHP_VERSION') . '.cache') + ->setCacheFile('.php_cs.' . getenv('PHP_VERSION') . '.cache') ->setUsingCache(true); diff --git a/Dockerfile b/Dockerfile index dfa0a36..9102de1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ -ARG PHP_VERSION=8.1 +ARG PHP_VERSION=8.3 FROM php:${PHP_VERSION}-cli-alpine -ARG XDEBUG_VERSION=3.1.5 +ARG XDEBUG_VERSION=3.4.0 COPY --from=composer /usr/bin/composer /usr/bin/composer RUN composer --version diff --git a/Makefile b/Makefile index b27fb1e..97a3248 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -# no buildin rules and variables +# no builtin rules and variables MAKEFLAGS =+ -rR --warn-undefined-variables -.PHONY: composer-install composer-update phpstan cs-fixer examples docker run +.PHONY: composer-install composer-update composer-update-lowest phpstan cs-fixer examples docker run CONFLUENT_VERSION ?= latest CONFLUENT_NETWORK_SUBNET ?= 172.68.0.0/24 @@ -10,15 +10,15 @@ SCHEMA_REGISTRY_IPV4 ?= 172.68.0.103 KAFKA_BROKER_IPV4 ?= 172.68.0.102 ZOOKEEPER_IPV4 ?= 172.68.0.101 COMPOSER ?= bin/composer.phar -COMPOSER_VERSION ?= 2.3.10 +COMPOSER_VERSION ?= 2.8.4 PHP_STAN ?= bin/phpstan.phar -PHP_STAN_VERSION ?= 1.8.2 +PHP_STAN_VERSION ?= 2.0.4 PHP_CS_FIXER ?= bin/php-cs-fixer.phar -PHP_CS_FIXER_VERSION ?= 3.9.5 +PHP_CS_FIXER_VERSION ?= 3.65.0 PHPUNIT ?= vendor/bin/phpunit PHP ?= bin/php -PHP_VERSION ?= 8.1 -XDEBUG_VERSION ?= 3.1.5 +PHP_VERSION ?= 8.3 +XDEBUG_VERSION ?= 3.4.0 XDEBUG_OPTIONS ?= -d xdebug.mode=off export @@ -36,8 +36,11 @@ composer-install: composer-update: PHP_VERSION=$(PHP_VERSION) $(PHP) $(XDEBUG_OPTIONS) $(COMPOSER) update --prefer-stable --no-interaction --no-progress --no-scripts +composer-update-lowest: + PHP_VERSION=$(PHP_VERSION) $(PHP) $(XDEBUG_OPTIONS) $(COMPOSER) update --prefer-lowest --no-interaction --no-progress --no-scripts + phpstan: - PHP_VERSION=$(PHP_VERSION) $(PHP) $(XDEBUG_OPTIONS) $(PHP_STAN) analyse + PHP_VERSION=$(PHP_VERSION) $(PHP) $(XDEBUG_OPTIONS) $(PHP_STAN) analyse --memory-limit 4G cs-fixer: PHP_VERSION=$(PHP_VERSION) $(PHP) $(XDEBUG_OPTIONS) $(PHP_CS_FIXER) fix --config=.php-cs-fixer.dist.php --diff -v --dry-run \ diff --git a/README.md b/README.md index 017e875..9e6eb43 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ When serializing and deserializing messages using the [Avro](http://avro.apache. especially when integrating with the [Confluent Platform](https://docs.confluent.io/current/avro.html), you want to make sure that schemas are evolved in a way that downstream consumers are not affected. -Hence [Confluent](https://www.confluent.io/) developed the +Hence, [Confluent](https://www.confluent.io/) developed the [Schema Registry](https://docs.confluent.io/current/schema-registry/docs/index.html) which has the responsibility to validate a given schema evolution against a configurable compatibility policy. @@ -27,7 +27,7 @@ integrates FlixTech's [Schema Registry Client](https://github.com/flix-tech/sche This library is using the [composer package manager](https://getcomposer.org/) for PHP. ```bash -composer require 'flix-tech/avro-serde-php:^1.6' +composer require 'flix-tech/avro-serde-php:^2.2' ``` ## Quickstart @@ -273,7 +273,7 @@ $resolver->keySchemaFor($record); // Will resolve $fileResolver, then $callableR ## Symfony Serializer Integration -This library provides integrations with the [Symfony Serializer component](https://symfony.com/doc/master/components/serializer.html). +This library provides integrations with the [Symfony Serializer component](https://symfony.com/doc/master/components/serializer.html) from version 6.4 and above. ```php schema = \AvroSchema::parse(self::SCHEMA_JSON); + $this->schema = AvroSchema::parse(self::SCHEMA_JSON); $this->prepareTestForMode(self::ASYNC, new PromisingRegistry( new Client(['base_uri' => getenv('SCHEMA_REGISTRY_HOST')]) @@ -102,72 +105,66 @@ public function setUp(): void } /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchEncodeWithSyncRegistry(): void { $this->serializers[self::SYNC]->encodeRecord('test', $this->schema, self::TEST_RECORD); } /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchDecodeWithSyncRegistry(): void { $this->serializers[self::SYNC]->decodeMessage($this->messages[self::SYNC]); } /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchEncodeWithAsyncRegistry(): void { $this->serializers[self::ASYNC]->encodeRecord('test', $this->schema, self::TEST_RECORD); } /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchDecodeWithAsyncRegistry(): void { $this->serializers[self::ASYNC]->decodeMessage($this->messages[self::ASYNC]); } /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchEncodeWithAsyncCachedRegistry(): void { $this->serializers[self::ASYNC_CACHED]->encodeRecord('test', $this->schema, self::TEST_RECORD); } /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchDecodeWithAsyncCachedRegistry(): void { $this->serializers[self::ASYNC_CACHED]->decodeMessage($this->messages[self::ASYNC_CACHED]); @@ -175,24 +172,22 @@ public function benchDecodeWithAsyncCachedRegistry(): void /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchEncodeWithSyncCachedRegistry(): void { $this->serializers[self::SYNC_CACHED]->encodeRecord('test', $this->schema, self::TEST_RECORD); } /** - * @Revs(1000) - * @Iterations(5) - * - * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws Exception + * @throws SchemaRegistryException */ + #[\PhpBench\Attributes\Revs(1000)] + #[\PhpBench\Attributes\Iterations(5)] public function benchDecodeWithSyncCachedRegistry(): void { $this->serializers[self::SYNC_CACHED]->decodeMessage($this->messages[self::SYNC_CACHED]); @@ -200,9 +195,9 @@ public function benchDecodeWithSyncCachedRegistry(): void /** * @param string $mode - * @param \FlixTech\SchemaRegistryApi\Registry $registry + * @param Registry $registry * - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws SchemaRegistryException|AvroIOException */ private function prepareTestForMode(string $mode, Registry $registry): void { @@ -217,8 +212,7 @@ private function prepareTestForMode(string $mode, Registry $registry): void $this->schema, self::TEST_RECORD ); - } catch (\Exception $e) { - } catch (SchemaRegistryException $e) { + } catch (Exception|SchemaRegistryException $e) { } } } diff --git a/benchmarks/bootstrap.php b/benchmarks/bootstrap.php index 7382ce6..6fa6e3e 100644 --- a/benchmarks/bootstrap.php +++ b/benchmarks/bootstrap.php @@ -2,4 +2,5 @@ require __DIR__ . '/../vendor/autoload.php'; -(new \Dotenv\Dotenv(__DIR__ . '/..'))->load(); +$dotenv = Dotenv\Dotenv::createUnsafeMutable(paths: __DIR__ . DIRECTORY_SEPARATOR . '..', names: '.env.dist'); +$dotenv->load(); diff --git a/composer.json b/composer.json index 00fc411..b41eb55 100644 --- a/composer.json +++ b/composer.json @@ -31,17 +31,17 @@ "beberlei/assert": "^2.9.9|~3.0", "flix-tech/confluent-schema-registry-api": "^8.0", "guzzlehttp/promises": "^1.4.0|^2.0.0", - "flix-tech/avro-php": "^5.0", - "widmogrod/php-functional": "^6.0" + "flix-tech/avro-php": "^5.1", + "widmogrod/php-functional": "^6.0|^7.0" }, "require-dev": { "roave/security-advisories": "dev-latest", "phpunit/phpunit": "^10.5", - "phpbench/phpbench": "1.0.0-alpha2", - "vlucas/phpdotenv": "~2.4", - "symfony/serializer": "^6.4|^7.0", - "doctrine/annotations": "^1.11", - "rector/rector": "^1.2" + "phpbench/phpbench": "1.3.1", + "vlucas/phpdotenv": "^5.0", + "symfony/serializer": "^5.4|^6.4|^7.1", + "doctrine/annotations": "^2.0", + "phpoption/phpoption": "^1.8.0" }, "autoload": { "psr-4": { diff --git a/docker-compose.yml b/docker-compose.yml index 6753b4a..a2dece7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,4 @@ --- -version: '3' services: zookeeper: image: confluentinc/cp-zookeeper:${CONFLUENT_VERSION} diff --git a/examples/SchemaBuilder.php b/examples/SchemaBuilder.php index 0e6d221..694d766 100644 --- a/examples/SchemaBuilder.php +++ b/examples/SchemaBuilder.php @@ -11,7 +11,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$dotEnv = new Dotenv(__DIR__ . '/..'); +$dotEnv = Dotenv::createUnsafeMutable(paths: __DIR__ . DIRECTORY_SEPARATOR . '..'); $dotEnv->load(); $dotEnv->required('SCHEMA_REGISTRY_HOST')->notEmpty(); diff --git a/examples/SchemaGenerator.php b/examples/SchemaGenerator.php index ae4b681..112e2fb 100644 --- a/examples/SchemaGenerator.php +++ b/examples/SchemaGenerator.php @@ -15,7 +15,7 @@ require __DIR__ . '/../vendor/autoload.php'; -$dotEnv = new Dotenv(__DIR__ . '/..'); +$dotEnv = Dotenv::createUnsafeMutable(paths: __DIR__ . DIRECTORY_SEPARATOR . '..'); $dotEnv->load(); $dotEnv->required('SCHEMA_REGISTRY_HOST')->notEmpty(); @@ -29,19 +29,19 @@ class WriterUser * @SerDe\AvroType("string") * @var string */ - private $firstName; + private string $firstName; /** * @SerDe\AvroType("string") * @var string */ - private $lastName; + private string $lastName; /** * @SerDe\AvroType("int") * @var int */ - private $age; + private int $age; public function __construct(string $firstName, string $lastName, int $age) { @@ -76,13 +76,13 @@ class ReaderUser * @SerDe\AvroType("string") * @var string */ - private $firstName; + private string $firstName; /** * @SerDe\AvroType("int") * @var int */ - private $age; + private int $age; public function __construct(string $firstName, int $age) { diff --git a/examples/SymfonySerializer.php b/examples/SymfonySerializer.php index aa346c3..7f7eb73 100644 --- a/examples/SymfonySerializer.php +++ b/examples/SymfonySerializer.php @@ -15,17 +15,17 @@ require __DIR__ . '/../vendor/autoload.php'; -$dotEnv = new Dotenv(__DIR__ . '/..'); +$dotEnv = Dotenv::createUnsafeMutable(paths: __DIR__ . DIRECTORY_SEPARATOR . '..'); $dotEnv->load(); $dotEnv->required('SCHEMA_REGISTRY_HOST')->notEmpty(); class User { /** @var string */ - private $name; + private string $name; /** @var int */ - private $age; + private int $age; public function __construct(string $name, int $age) { diff --git a/integrations/Symfony/Serializer/AvroSerDeEncoder.php b/integrations/Symfony/Serializer/AvroSerDeEncoder.php index e6d1112..6764f0e 100644 --- a/integrations/Symfony/Serializer/AvroSerDeEncoder.php +++ b/integrations/Symfony/Serializer/AvroSerDeEncoder.php @@ -17,10 +17,7 @@ class AvroSerDeEncoder implements EncoderInterface, DecoderInterface public const CONTEXT_ENCODE_SUBJECT = self::FORMAT_AVRO . '.subject'; public const CONTEXT_DECODE_READERS_SCHEMA = self::FORMAT_AVRO . '.readers_schema'; - /** - * @var \FlixTech\AvroSerializer\Objects\RecordSerializer - */ - private $recordSerializer; + private RecordSerializer $recordSerializer; public function __construct(RecordSerializer $recordSerializer) { diff --git a/integrations/Symfony/Serializer/NameConverter/AvroNameConverter.php b/integrations/Symfony/Serializer/NameConverter/AvroNameConverter.php index 8e9f3f3..bf2b996 100644 --- a/integrations/Symfony/Serializer/NameConverter/AvroNameConverter.php +++ b/integrations/Symfony/Serializer/NameConverter/AvroNameConverter.php @@ -4,37 +4,30 @@ namespace FlixTech\AvroSerializer\Integrations\Symfony\Serializer\NameConverter; -use Exception; use FlixTech\AvroSerializer\Integrations\Symfony\Serializer\AvroSerDeEncoder; use FlixTech\AvroSerializer\Objects\Schema\AttributeName; use FlixTech\AvroSerializer\Objects\Schema\Generation\SchemaAttributeReader; -use ReflectionClass; -use ReflectionProperty; use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; -if (!\interface_exists(AdvancedNameConverterInterface::class)) { - throw new Exception("The advanced name converter is supported only in symfony 4 and forward"); -} - class AvroNameConverter implements AdvancedNameConverterInterface { - /** - * @var SchemaAttributeReader - */ - private $attributeReader; + private SchemaAttributeReader $attributeReader; /** * @var array */ - private $mapCache = []; + private array $mapCache = []; public function __construct(SchemaAttributeReader $attributeReader) { $this->attributeReader = $attributeReader; } + /** + * @throws \ReflectionException + */ public function normalize( - $propertyName, + string $propertyName, string $class = null, string $format = null, array $context = [] @@ -44,26 +37,32 @@ public function normalize( ->getNormalized($propertyName); } + /** + * @throws \ReflectionException + */ private function getNameMap(?string $class, ?string $format): PropertyNameMap { if (null === $class || !class_exists($class)) { return new PropertyNameMap(); } - if (null === $format || AvroSerDeEncoder::FORMAT_AVRO !== $format) { + if (AvroSerDeEncoder::FORMAT_AVRO !== $format) { return new PropertyNameMap(); } return $this->generateMap($class); } + /** + * @throws \ReflectionException + */ private function generateMap(string $class): PropertyNameMap { if (isset($this->mapCache[$class])) { return $this->mapCache[$class]; } - $reflectionClass = new ReflectionClass($class); + $reflectionClass = new \ReflectionClass($class); $map = array_reduce( $reflectionClass->getProperties(), @@ -78,7 +77,7 @@ private function generateMap(string $class): PropertyNameMap private function propertyToSchemaName( PropertyNameMap $map, - ReflectionProperty $reflectionProperty + \ReflectionProperty $reflectionProperty ): PropertyNameMap { $schemaAttributes = $this->attributeReader->readPropertyAttributes($reflectionProperty); @@ -98,8 +97,11 @@ private function propertyToSchemaName( ); } + /** + * @throws \ReflectionException + */ public function denormalize( - $propertyName, + string $propertyName, string $class = null, string $format = null, array $context = [] diff --git a/integrations/Symfony/Serializer/NameConverter/PropertyNameMap.php b/integrations/Symfony/Serializer/NameConverter/PropertyNameMap.php index 3f7bfaf..81d075c 100644 --- a/integrations/Symfony/Serializer/NameConverter/PropertyNameMap.php +++ b/integrations/Symfony/Serializer/NameConverter/PropertyNameMap.php @@ -6,8 +6,8 @@ class PropertyNameMap { - private $propertyToSchemaMap = []; - private $schemaToPropertyMap = []; + private array $propertyToSchemaMap = []; + private array $schemaToPropertyMap = []; public function add(string $propertyName, string $schemaName): self { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 21c792d..27120a2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,14 +1,19 @@ - - - - test/ - - + src/ integrations/ + + + test/ + + diff --git a/src/Common.php b/src/Common.php index 20bf43e..49d2d2c 100644 --- a/src/Common.php +++ b/src/Common.php @@ -11,10 +11,9 @@ const get = '\FlixTech\AvroSerializer\Common\get'; /** - * @param mixed $key - * @param array $array + * @param array $array */ -function get($key, array $array): Maybe +function get(string|int $key, array $array): Maybe { return isset($array[$key]) ? just($array[$key]) @@ -30,10 +29,7 @@ function getter(): callable const inflectRecord = '\FlixTech\AvroSerializer\Common\inflectRecord'; -/** - * @param mixed $record - */ -function inflectRecord($record): Maybe +function inflectRecord(mixed $record): Maybe { return \is_object($record) ? just(\str_replace('\\', '.', \get_class($record))) @@ -43,12 +39,9 @@ function inflectRecord($record): Maybe const memoize = '\FlixTech\AvroSerializer\Common\memoize'; /** - * @param array $arguments - * @param string|null $key - * - * @return mixed|null + * @param array $arguments */ -function memoize(callable $callback = null, array $arguments = [], $key = null) +function memoize(?callable $callback = null, array $arguments = [], string|int|null $key = null): mixed { static $storage = []; diff --git a/src/Objects/DefaultRecordSerializerFactory.php b/src/Objects/DefaultRecordSerializerFactory.php index c369ec7..f29e5cb 100644 --- a/src/Objects/DefaultRecordSerializerFactory.php +++ b/src/Objects/DefaultRecordSerializerFactory.php @@ -19,7 +19,7 @@ final class DefaultRecordSerializerFactory public static function get( string $schemaRegistryURL, array $guzzleClientOptions = [], - ?CacheAdapter $adapter = null + ?CacheAdapter $adapter = null, ): RecordSerializer { Assert::that($schemaRegistryURL)->url(); diff --git a/src/Objects/DefaultSchemaGeneratorFactory.php b/src/Objects/DefaultSchemaGeneratorFactory.php index 3e947bf..915b658 100644 --- a/src/Objects/DefaultSchemaGeneratorFactory.php +++ b/src/Objects/DefaultSchemaGeneratorFactory.php @@ -5,16 +5,13 @@ namespace FlixTech\AvroSerializer\Objects; use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Annotations\AnnotationRegistry; use FlixTech\AvroSerializer\Objects\Schema\Generation\SchemaGenerator; class DefaultSchemaGeneratorFactory { public static function get(): SchemaGenerator { - AnnotationRegistry::registerLoader('class_exists'); - - return new Schema\Generation\SchemaGenerator( + return new SchemaGenerator( new Schema\Generation\AnnotationReader( new AnnotationReader() ) diff --git a/src/Objects/Definition.php b/src/Objects/Definition.php index b87db57..f95a755 100644 --- a/src/Objects/Definition.php +++ b/src/Objects/Definition.php @@ -6,8 +6,5 @@ interface Definition { - /** - * @return mixed - */ - public function serialize(); + public function serialize(): mixed; } diff --git a/src/Objects/Exceptions/AvroDecodingException.php b/src/Objects/Exceptions/AvroDecodingException.php index a063dc5..c26abe4 100644 --- a/src/Objects/Exceptions/AvroDecodingException.php +++ b/src/Objects/Exceptions/AvroDecodingException.php @@ -5,8 +5,7 @@ namespace FlixTech\AvroSerializer\Objects\Exceptions; use FlixTech\AvroSerializer\Objects\AvroSerializerException; -use RuntimeException; -class AvroDecodingException extends RuntimeException implements AvroSerializerException +class AvroDecodingException extends \RuntimeException implements AvroSerializerException { } diff --git a/src/Objects/Exceptions/AvroEncodingException.php b/src/Objects/Exceptions/AvroEncodingException.php index 8a3edc6..4b456b0 100644 --- a/src/Objects/Exceptions/AvroEncodingException.php +++ b/src/Objects/Exceptions/AvroEncodingException.php @@ -5,8 +5,7 @@ namespace FlixTech\AvroSerializer\Objects\Exceptions; use FlixTech\AvroSerializer\Objects\AvroSerializerException; -use RuntimeException; -class AvroEncodingException extends RuntimeException implements AvroSerializerException +class AvroEncodingException extends \RuntimeException implements AvroSerializerException { } diff --git a/src/Objects/Exceptions/Exceptions.php b/src/Objects/Exceptions/Exceptions.php index 0b2a96b..ad63e26 100644 --- a/src/Objects/Exceptions/Exceptions.php +++ b/src/Objects/Exceptions/Exceptions.php @@ -9,10 +9,7 @@ final class Exceptions public const ERROR_ENCODING = 501; public const ERROR_DECODING = 502; - /** - * @param mixed $record - */ - public static function forEncode($record, \AvroSchema $schema, \Exception $previous = null): AvroEncodingException + public static function forEncode(mixed $record, \AvroSchema $schema, ?\Exception $previous = null): AvroEncodingException { $exportedRecord = \var_export($record, true); @@ -29,7 +26,7 @@ public static function forEncode($record, \AvroSchema $schema, \Exception $previ return new AvroEncodingException($message, self::ERROR_ENCODING, $previous); } - public static function forDecode(string $binaryMessage, \Exception $previous = null): AvroDecodingException + public static function forDecode(string $binaryMessage, ?\Exception $previous = null): AvroDecodingException { $convertedMessage = \bin2hex($binaryMessage); $message = <<avroBinaryGetter = $get(PROTOCOL_ACCESSOR_AVRO); $this->registerMissingSchemas = isset($options[self::OPTION_REGISTER_MISSING_SCHEMAS]) - ? (bool) $options[self::OPTION_REGISTER_MISSING_SCHEMAS] - : false; + && $options[self::OPTION_REGISTER_MISSING_SCHEMAS]; $this->registerNonExistingSubjects = isset($options[self::OPTION_REGISTER_MISSING_SUBJECTS]) - ? (bool) $options[self::OPTION_REGISTER_MISSING_SUBJECTS] - : false; + && $options[self::OPTION_REGISTER_MISSING_SUBJECTS]; } /** - * @param mixed $record - * * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws SchemaRegistryException */ - public function encodeRecord(string $subject, AvroSchema $schema, $record): string + public function encodeRecord(string $subject, \AvroSchema $schema, mixed $record): string { $schemaId = $this->getSchemaIdForSchema($subject, $schema); $cachedWriter = memoize($this->datumWriterFactoryFunc, [$schema], 'writer_' . $schemaId); @@ -125,16 +112,15 @@ public function encodeRecord(string $subject, AvroSchema $schema, $record): stri } /** - * @return mixed - * * @throws \InvalidArgumentException * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws SchemaRegistryException */ - public function decodeMessage(string $binaryMessage, AvroSchema $readersSchema = null) + public function decodeMessage(string $binaryMessage, ?\AvroSchema $readersSchema = null): mixed { $decoded = decode($binaryMessage); $schemaId = valueOf($decoded->bind($this->schemaIdGetter)); + /** @var \AvroSchema $writersSchema */ $writersSchema = $this->extractValueFromRegistryResponse($this->registry->schemaForId($schemaId)); $readersSchema = $readersSchema ?? $writersSchema; $cachedReader = memoize($this->datumReaderFactoryFunc, [$writersSchema], 'reader_' . $schemaId); @@ -142,7 +128,7 @@ public function decodeMessage(string $binaryMessage, AvroSchema $readersSchema = /** @var \Widmogrod\Monad\Maybe\Maybe $validated */ $validated = $decoded->bind($this->protocolValidatorFunc); - /** @var \Widmogrod\Monad\Either\Either $read */ + /** @var Either $read */ $read = $validated ->orElse(static function () { throw new \InvalidArgumentException('Could not validate message wire protocol.'); }) ->bind($this->avroBinaryGetter) @@ -153,9 +139,9 @@ public function decodeMessage(string $binaryMessage, AvroSchema $readersSchema = /** * @throws \Exception - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws SchemaRegistryException */ - private function getSchemaIdForSchema(string $subject, AvroSchema $schema): int + private function getSchemaIdForSchema(string $subject, \AvroSchema $schema): int { try { $schemaId = $this->extractValueFromRegistryResponse($this->registry->schemaId($subject, $schema)); @@ -171,11 +157,9 @@ private function getSchemaIdForSchema(string $subject, AvroSchema $schema): int /** * @param PromiseInterface|\Exception|\Psr\Http\Message\ResponseInterface $response * - * @return mixed - * * @throws \Exception */ - private function extractValueFromRegistryResponse($response) + private function extractValueFromRegistryResponse(mixed $response): mixed { if ($response instanceof PromiseInterface) { $response = $response->wait(); @@ -189,7 +173,7 @@ private function extractValueFromRegistryResponse($response) } /** - * @throws \FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException + * @throws SchemaRegistryException */ private function handleSubjectOrSchemaNotFound(SchemaRegistryException $e): void { @@ -209,7 +193,7 @@ private function handleSubjectOrSchemaNotFound(SchemaRegistryException $e): void default: // @codeCoverageIgnoreStart throw $e; - // @codeCoverageIgnoreEnd + // @codeCoverageIgnoreEnd } } } diff --git a/src/Objects/Schema.php b/src/Objects/Schema.php index a78d2a6..f56e98e 100644 --- a/src/Objects/Schema.php +++ b/src/Objects/Schema.php @@ -4,7 +4,6 @@ namespace FlixTech\AvroSerializer\Objects; -use AvroSchema; use FlixTech\AvroSerializer\Objects\Schema\ArrayType; use FlixTech\AvroSerializer\Objects\Schema\BooleanType; use FlixTech\AvroSerializer\Objects\Schema\BytesType; @@ -152,10 +151,11 @@ public static function duration(): DurationType return new DurationType(); } - final public function parse(): AvroSchema + /** + * @throws \AvroSchemaParseException + */ + final public function parse(): \AvroSchema { - $avro = $this->serialize(); - - return AvroSchema::real_parse($avro); + return \AvroSchema::real_parse($this->serialize()); } } diff --git a/src/Objects/Schema/ComplexType.php b/src/Objects/Schema/ComplexType.php index 95b5136..e3343a6 100644 --- a/src/Objects/Schema/ComplexType.php +++ b/src/Objects/Schema/ComplexType.php @@ -12,12 +12,9 @@ abstract class ComplexType extends Schema /** * @var array */ - private $attributes; + private array $attributes; - /** - * @var string - */ - private $type; + private string $type; /** * @param array $attributes @@ -29,7 +26,7 @@ public function __construct(string $type, array $attributes = []) } /** - * @return array + * @return array */ public function serialize(): array { @@ -51,11 +48,9 @@ public function serialize(): array } /** - * @param mixed $value - * * @return static */ - protected function attribute(string $name, $value): self + protected function attribute(string $name, mixed $value): self { $schema = clone $this; $schema->attributes[$name] = $value; diff --git a/src/Objects/Schema/Generation/AnnotationReader.php b/src/Objects/Schema/Generation/AnnotationReader.php index dbdbc46..d5f2f54 100644 --- a/src/Objects/Schema/Generation/AnnotationReader.php +++ b/src/Objects/Schema/Generation/AnnotationReader.php @@ -5,25 +5,17 @@ namespace FlixTech\AvroSerializer\Objects\Schema\Generation; use Doctrine\Common\Annotations\Reader as DoctrineAnnotationReader; -use ReflectionClass; -use ReflectionProperty; class AnnotationReader implements SchemaAttributeReader { - /** - * @var DoctrineAnnotationReader - */ - private $reader; + private DoctrineAnnotationReader $reader; public function __construct(DoctrineAnnotationReader $reader) { $this->reader = $reader; } - /** - * {@inheritdoc} - */ - public function readClassAttributes(ReflectionClass $class): SchemaAttributes + public function readClassAttributes(\ReflectionClass $class): SchemaAttributes { /** @var SchemaAttribute[] $annotations */ $annotations = $this->reader->getClassAnnotations($class); @@ -32,7 +24,7 @@ public function readClassAttributes(ReflectionClass $class): SchemaAttributes return new SchemaAttributes(...$attributes); } - public function readPropertyAttributes(ReflectionProperty $property): SchemaAttributes + public function readPropertyAttributes(\ReflectionProperty $property): SchemaAttributes { /** @var SchemaAttribute[] $annotations */ $annotations = $this->reader->getPropertyAnnotations($property); diff --git a/src/Objects/Schema/Generation/Annotations/AvroAliases.php b/src/Objects/Schema/Generation/Annotations/AvroAliases.php index 0fee6ed..1cb4589 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroAliases.php +++ b/src/Objects/Schema/Generation/Annotations/AvroAliases.php @@ -16,19 +16,14 @@ final class AvroAliases implements VariadicAttribute /** * @var array */ - public $value; + public array $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::ALIASES; } /** - * {@inheritdoc} - * * @return array */ public function value(): array @@ -36,9 +31,6 @@ public function value(): array return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroDefault.php b/src/Objects/Schema/Generation/Annotations/AvroDefault.php index 97029a7..a10abaa 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroDefault.php +++ b/src/Objects/Schema/Generation/Annotations/AvroDefault.php @@ -13,30 +13,18 @@ */ final class AvroDefault implements SchemaAttribute { - /** - * @var mixed - */ - public $value; + public mixed $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::DEFAULT; } - /** - * {@inheritdoc} - */ - public function value() + public function value(): mixed { return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroDoc.php b/src/Objects/Schema/Generation/Annotations/AvroDoc.php index b578381..f61927b 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroDoc.php +++ b/src/Objects/Schema/Generation/Annotations/AvroDoc.php @@ -13,30 +13,18 @@ */ final class AvroDoc implements SchemaAttribute { - /** - * @var string - */ - public $value; + public string $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::DOC; } - /** - * {@inheritdoc} - */ public function value(): string { return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroItems.php b/src/Objects/Schema/Generation/Annotations/AvroItems.php index 2ebd5f6..22ffc01 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroItems.php +++ b/src/Objects/Schema/Generation/Annotations/AvroItems.php @@ -14,9 +14,6 @@ final class AvroItems implements TypeOnlyAttribute { use ContainsOnlyTypes; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::ITEMS; diff --git a/src/Objects/Schema/Generation/Annotations/AvroName.php b/src/Objects/Schema/Generation/Annotations/AvroName.php index 840f540..d4e9695 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroName.php +++ b/src/Objects/Schema/Generation/Annotations/AvroName.php @@ -13,30 +13,18 @@ */ class AvroName implements SchemaAttribute { - /** - * @var string - */ - public $value; + public string $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::NAME; } - /** - * {@inheritdoc} - */ public function value(): string { return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroNamespace.php b/src/Objects/Schema/Generation/Annotations/AvroNamespace.php index 669abe9..a23c8e5 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroNamespace.php +++ b/src/Objects/Schema/Generation/Annotations/AvroNamespace.php @@ -13,30 +13,18 @@ */ class AvroNamespace implements SchemaAttribute { - /** - * @var string - */ - public $value; + public string $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::NAMESPACE; } - /** - * {@inheritdoc} - */ public function value(): string { return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroOrder.php b/src/Objects/Schema/Generation/Annotations/AvroOrder.php index f4e940b..14a3e0a 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroOrder.php +++ b/src/Objects/Schema/Generation/Annotations/AvroOrder.php @@ -13,30 +13,18 @@ */ final class AvroOrder implements SchemaAttribute { - /** - * @var string - */ - public $value; + public string $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::ORDER; } - /** - * {@inheritdoc} - */ public function value(): string { return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroSize.php b/src/Objects/Schema/Generation/Annotations/AvroSize.php index 99902bd..027fd9c 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroSize.php +++ b/src/Objects/Schema/Generation/Annotations/AvroSize.php @@ -13,30 +13,18 @@ */ final class AvroSize implements SchemaAttribute { - /** - * @var int - */ - public $value; + public int $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::SIZE; } - /** - * {@inheritdoc} - */ public function value(): int { return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroSymbols.php b/src/Objects/Schema/Generation/Annotations/AvroSymbols.php index 752819b..f36e702 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroSymbols.php +++ b/src/Objects/Schema/Generation/Annotations/AvroSymbols.php @@ -16,19 +16,14 @@ final class AvroSymbols implements VariadicAttribute /** * @var array */ - public $value; + public array $value; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::SYMBOLS; } /** - * {@inheritdoc} - * * @return array */ public function value(): array @@ -36,9 +31,6 @@ public function value(): array return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/Annotations/AvroTargetClass.php b/src/Objects/Schema/Generation/Annotations/AvroTargetClass.php index 8e68f56..51c1ec6 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroTargetClass.php +++ b/src/Objects/Schema/Generation/Annotations/AvroTargetClass.php @@ -13,10 +13,7 @@ */ final class AvroTargetClass implements SchemaAttribute { - /** - * @var string - */ - public $value; + public string $value; public function name(): string { diff --git a/src/Objects/Schema/Generation/Annotations/AvroType.php b/src/Objects/Schema/Generation/Annotations/AvroType.php index 3de4d94..36442da 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroType.php +++ b/src/Objects/Schema/Generation/Annotations/AvroType.php @@ -13,15 +13,12 @@ */ final class AvroType implements SchemaAttribute { - /** - * @var string - */ - public $value; + public string $value; /** * @var array<\FlixTech\AvroSerializer\Objects\Schema\Generation\SchemaAttribute> */ - public $attributes = []; + public array $attributes = []; public static function create(string $typeName, SchemaAttribute ...$attributes): self { @@ -33,25 +30,16 @@ public static function create(string $typeName, SchemaAttribute ...$attributes): return $avroType; } - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::TYPE; } - /** - * {@inheritdoc} - */ public function value(): string { return $this->value; } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(...$this->attributes); diff --git a/src/Objects/Schema/Generation/Annotations/AvroValues.php b/src/Objects/Schema/Generation/Annotations/AvroValues.php index 581d580..11d6157 100644 --- a/src/Objects/Schema/Generation/Annotations/AvroValues.php +++ b/src/Objects/Schema/Generation/Annotations/AvroValues.php @@ -14,9 +14,6 @@ final class AvroValues implements TypeOnlyAttribute { use ContainsOnlyTypes; - /** - * {@inheritdoc} - */ public function name(): string { return AttributeName::VALUES; diff --git a/src/Objects/Schema/Generation/Annotations/ContainsOnlyTypes.php b/src/Objects/Schema/Generation/Annotations/ContainsOnlyTypes.php index 8340848..1c2b5e5 100644 --- a/src/Objects/Schema/Generation/Annotations/ContainsOnlyTypes.php +++ b/src/Objects/Schema/Generation/Annotations/ContainsOnlyTypes.php @@ -12,11 +12,9 @@ trait ContainsOnlyTypes /** * @phpstan-var string|AvroType|array */ - public $value; + public string|array|AvroType $value; /** - * {@inheritdoc} - * * @return array */ public function value(): array @@ -28,9 +26,6 @@ public function value(): array return \array_map([$this, 'valueToType'], $this->value); } - /** - * {@inheritdoc} - */ public function attributes(): SchemaAttributes { return new SchemaAttributes(...$this->value()); diff --git a/src/Objects/Schema/Generation/AttributeReader.php b/src/Objects/Schema/Generation/AttributeReader.php index b549a28..145ba33 100644 --- a/src/Objects/Schema/Generation/AttributeReader.php +++ b/src/Objects/Schema/Generation/AttributeReader.php @@ -20,6 +20,9 @@ public function readPropertyAttributes(\ReflectionProperty $property): SchemaAtt return $this->getSchemaAttributes(...$attributes); } + /** + * @param \ReflectionAttribute ...$attributes + */ private function getSchemaAttributes(\ReflectionAttribute ...$attributes): SchemaAttributes { $attributes = array_map(fn ($attr) => $attr->newInstance(), $attributes); diff --git a/src/Objects/Schema/Generation/Attributes/AvroDoc.php b/src/Objects/Schema/Generation/Attributes/AvroDoc.php index 477432c..601be62 100644 --- a/src/Objects/Schema/Generation/Attributes/AvroDoc.php +++ b/src/Objects/Schema/Generation/Attributes/AvroDoc.php @@ -12,7 +12,7 @@ final class AvroDoc implements SchemaAttribute { public function __construct( - public string $value + public string $value, ) { } diff --git a/src/Objects/Schema/Generation/Attributes/AvroItems.php b/src/Objects/Schema/Generation/Attributes/AvroItems.php index f4fcf39..188cd94 100644 --- a/src/Objects/Schema/Generation/Attributes/AvroItems.php +++ b/src/Objects/Schema/Generation/Attributes/AvroItems.php @@ -18,7 +18,7 @@ final class AvroItems implements TypeOnlyAttribute public function __construct(Type|AvroType ...$types) { - $this->types = array_map(function ($type) { + $this->types = array_map(static function ($type) { if ($type instanceof AvroType) { return $type; } diff --git a/src/Objects/Schema/Generation/Attributes/AvroSymbols.php b/src/Objects/Schema/Generation/Attributes/AvroSymbols.php index 2a6ce96..84367e0 100644 --- a/src/Objects/Schema/Generation/Attributes/AvroSymbols.php +++ b/src/Objects/Schema/Generation/Attributes/AvroSymbols.php @@ -12,13 +12,16 @@ final class AvroSymbols implements VariadicAttribute { /** - * @var array + * @var non-empty-array */ private array $symbols; - public function __construct(callable $symbols) + /** + * @param non-empty-array $symbols + */ + public function __construct(array $symbols) { - $this->symbols = $symbols(); + $this->symbols = $symbols; } public function name(): string diff --git a/src/Objects/Schema/Generation/Attributes/AvroType.php b/src/Objects/Schema/Generation/Attributes/AvroType.php index 354923c..f7d084b 100644 --- a/src/Objects/Schema/Generation/Attributes/AvroType.php +++ b/src/Objects/Schema/Generation/Attributes/AvroType.php @@ -20,7 +20,7 @@ class AvroType implements SchemaAttribute public function __construct( Type|string $value, - SchemaAttribute ...$attributes + SchemaAttribute ...$attributes, ) { $this->value = \is_string($value) ? $value : $value->value; diff --git a/src/Objects/Schema/Generation/SchemaAttribute.php b/src/Objects/Schema/Generation/SchemaAttribute.php index 72fc4b3..41d90e9 100644 --- a/src/Objects/Schema/Generation/SchemaAttribute.php +++ b/src/Objects/Schema/Generation/SchemaAttribute.php @@ -8,10 +8,7 @@ interface SchemaAttribute { public function name(): string; - /** - * @return mixed - */ - public function value(); + public function value(): mixed; public function attributes(): SchemaAttributes; } diff --git a/src/Objects/Schema/Generation/SchemaAttributeReader.php b/src/Objects/Schema/Generation/SchemaAttributeReader.php index 7b585e5..c10ec55 100644 --- a/src/Objects/Schema/Generation/SchemaAttributeReader.php +++ b/src/Objects/Schema/Generation/SchemaAttributeReader.php @@ -4,15 +4,12 @@ namespace FlixTech\AvroSerializer\Objects\Schema\Generation; -use ReflectionClass; -use ReflectionProperty; - interface SchemaAttributeReader { /** - * @param ReflectionClass $class + * @param \ReflectionClass $class */ - public function readClassAttributes(ReflectionClass $class): SchemaAttributes; + public function readClassAttributes(\ReflectionClass $class): SchemaAttributes; - public function readPropertyAttributes(ReflectionProperty $property): SchemaAttributes; + public function readPropertyAttributes(\ReflectionProperty $property): SchemaAttributes; } diff --git a/src/Objects/Schema/Generation/SchemaAttributes.php b/src/Objects/Schema/Generation/SchemaAttributes.php index 1f75dcc..8fb1560 100644 --- a/src/Objects/Schema/Generation/SchemaAttributes.php +++ b/src/Objects/Schema/Generation/SchemaAttributes.php @@ -11,12 +11,12 @@ class SchemaAttributes implements \Countable /** * @var array> */ - private $attributes = []; + private array $attributes = []; /** * @var array */ - private $optionAttributes = []; + private array $optionAttributes = []; public function __construct(SchemaAttribute ...$attributes) { @@ -30,7 +30,7 @@ public function __construct(SchemaAttribute ...$attributes) */ public function types(): array { - return \array_map(function (SchemaAttribute $schemaAttribute) { + return \array_map(static function (SchemaAttribute $schemaAttribute) { return new Type( $schemaAttribute->value(), $schemaAttribute->attributes() @@ -51,17 +51,11 @@ public function has(string $name): bool return isset($this->attributes[$name]); } - /** - * @return mixed - */ - public function get(string $name) + public function get(string $name): mixed { return $this->attributes[$name][0]->value(); } - /** - * {@inheritdoc} - */ public function count(): int { return \count($this->attributes); diff --git a/src/Objects/Schema/Generation/SchemaGenerator.php b/src/Objects/Schema/Generation/SchemaGenerator.php index 46d0219..994cc01 100644 --- a/src/Objects/Schema/Generation/SchemaGenerator.php +++ b/src/Objects/Schema/Generation/SchemaGenerator.php @@ -8,20 +8,12 @@ use FlixTech\AvroSerializer\Objects\Schema\AttributeName; use FlixTech\AvroSerializer\Objects\Schema\Record\FieldOrder; use FlixTech\AvroSerializer\Objects\Schema\TypeName; -use ReflectionClass; -use ReflectionProperty; class SchemaGenerator { - /** - * @var SchemaAttributeReader - */ - private $reader; + private SchemaAttributeReader $reader; - /** - * @var TypeMapper - */ - private $typeMapper; + private TypeMapper $typeMapper; public function __construct(SchemaAttributeReader $reader) { @@ -31,19 +23,21 @@ public function __construct(SchemaAttributeReader $reader) /** * @param class-string $className + * + * @throws \ReflectionException */ public function generate(string $className): Schema { - $class = new ReflectionClass($className); + $class = new \ReflectionClass($className); $attributes = $this->reader->readClassAttributes($class); return $this->generateFromClass($class, new Type(TypeName::RECORD, $attributes)); } /** - * @param ReflectionClass $class + * @param \ReflectionClass $class */ - private function generateFromClass(ReflectionClass $class, Type $type): Schema + private function generateFromClass(\ReflectionClass $class, Type $type): Schema { $schema = $this->schemaFromType($type); @@ -78,7 +72,7 @@ private function schemaFromType(Type $type): Schema ); } - private function parseField(ReflectionProperty $property, Schema\RecordType $rootSchema): Schema + private function parseField(\ReflectionProperty $property, Schema\RecordType $rootSchema): Schema { $attributes = $this->reader->readPropertyAttributes($property); diff --git a/src/Objects/Schema/Generation/Type.php b/src/Objects/Schema/Generation/Type.php index 75a6035..1df15ba 100644 --- a/src/Objects/Schema/Generation/Type.php +++ b/src/Objects/Schema/Generation/Type.php @@ -6,17 +6,11 @@ class Type { - /** - * @var string - */ - private $typeName; + private string $typeName; - /** - * @var SchemaAttributes - */ - private $attributes; + private SchemaAttributes $attributes; - public function __construct(string $typeName, SchemaAttributes $attributes = null) + public function __construct(string $typeName, ?SchemaAttributes $attributes = null) { $this->typeName = $typeName; $this->attributes = $attributes ?? new SchemaAttributes(); diff --git a/src/Objects/Schema/Generation/TypeMapper.php b/src/Objects/Schema/Generation/TypeMapper.php index 2ef82b2..8d8cda0 100644 --- a/src/Objects/Schema/Generation/TypeMapper.php +++ b/src/Objects/Schema/Generation/TypeMapper.php @@ -13,7 +13,7 @@ final class TypeMapper /** * @var array */ - private $mappers; + private array $mappers; public function __construct(SchemaGenerator $generator) { diff --git a/src/Objects/Schema/NamedType.php b/src/Objects/Schema/NamedType.php index 8a4a14b..0cd52bc 100644 --- a/src/Objects/Schema/NamedType.php +++ b/src/Objects/Schema/NamedType.php @@ -8,10 +8,7 @@ class NamedType extends Schema { - /** - * @var string - */ - private $name; + private string $name; public function __construct(string $name) { diff --git a/src/Objects/Schema/PrimitiveType.php b/src/Objects/Schema/PrimitiveType.php index 1b385b4..8906c09 100644 --- a/src/Objects/Schema/PrimitiveType.php +++ b/src/Objects/Schema/PrimitiveType.php @@ -8,10 +8,7 @@ abstract class PrimitiveType extends Schema { - /** - * @var string - */ - private $type; + private string $type; public function __construct(string $type) { diff --git a/src/Objects/Schema/Record/Field.php b/src/Objects/Schema/Record/Field.php index d5686d4..e0827fc 100644 --- a/src/Objects/Schema/Record/Field.php +++ b/src/Objects/Schema/Record/Field.php @@ -9,25 +9,19 @@ class Field implements Definition { - /** - * @var string - */ - private $name; + private string $name; - /** - * @var Schema - */ - private $type; + private Schema $type; /** * @var array */ - private $options; + private array $options; public function __construct( string $name, Schema $type, - FieldOption ...$options + FieldOption ...$options, ) { $this->name = $name; $this->type = $type; diff --git a/src/Objects/Schema/Record/FieldDefault.php b/src/Objects/Schema/Record/FieldDefault.php index 273d34f..0f77ae9 100644 --- a/src/Objects/Schema/Record/FieldDefault.php +++ b/src/Objects/Schema/Record/FieldDefault.php @@ -6,10 +6,7 @@ class FieldDefault extends FieldOption { - /** - * @param mixed $default - */ - public function __construct($default) + public function __construct(mixed $default) { parent::__construct('default', $default); } diff --git a/src/Objects/Schema/Record/FieldOption.php b/src/Objects/Schema/Record/FieldOption.php index cf6e273..65375ac 100644 --- a/src/Objects/Schema/Record/FieldOption.php +++ b/src/Objects/Schema/Record/FieldOption.php @@ -6,19 +6,10 @@ abstract class FieldOption { - /** - * @var string - */ - private $name; - /** - * @var mixed - */ - private $value; + private string $name; + private mixed $value; - /** - * @param mixed $value - */ - public function __construct(string $name, $value) + public function __construct(string $name, mixed $value) { $this->name = $name; $this->value = $value; @@ -29,10 +20,7 @@ public static function doc(string $doc): FieldDoc return new FieldDoc($doc); } - /** - * @param mixed $default - */ - public static function default($default): FieldDefault + public static function default(mixed $default): FieldDefault { return new FieldDefault($default); } @@ -62,10 +50,7 @@ public function getName(): string return $this->name; } - /** - * @return mixed - */ - public function getValue() + public function getValue(): mixed { return $this->value; } diff --git a/src/Objects/Schema/RecordType.php b/src/Objects/Schema/RecordType.php index f9b7faf..f92506c 100644 --- a/src/Objects/Schema/RecordType.php +++ b/src/Objects/Schema/RecordType.php @@ -13,7 +13,7 @@ class RecordType extends ComplexType /** * @var array */ - private $fields = []; + private array $fields = []; public function __construct() { diff --git a/src/Objects/Schema/UnionType.php b/src/Objects/Schema/UnionType.php index 8b2d895..c9e2c8a 100644 --- a/src/Objects/Schema/UnionType.php +++ b/src/Objects/Schema/UnionType.php @@ -11,7 +11,7 @@ class UnionType extends Schema /** * @var array */ - private $types; + private array $types; public function __construct(Schema $type, Schema ...$types) { diff --git a/src/Objects/SchemaResolverInterface.php b/src/Objects/SchemaResolverInterface.php index b44bf4b..6c79a98 100644 --- a/src/Objects/SchemaResolverInterface.php +++ b/src/Objects/SchemaResolverInterface.php @@ -4,25 +4,18 @@ namespace FlixTech\AvroSerializer\Objects; -use AvroSchema; - /** * Resolves value and/or key schemas for a given record. */ interface SchemaResolverInterface { - /** - * @param mixed $record - */ - public function valueSchemaFor($record): AvroSchema; + public function valueSchemaFor(mixed $record): \AvroSchema; /** * This method should resolve the Avro key schema for a given record. * * The method should return `NULL` *only* when the record is not supposed to have a key schema. * If the key schema cannot be resolved otherwise, this method should throw an `CannotResolveSchemaException`. - * - * @param mixed $record */ - public function keySchemaFor($record): ?AvroSchema; + public function keySchemaFor(mixed $record): ?\AvroSchema; } diff --git a/src/Objects/SchemaResolvers/CallableResolver.php b/src/Objects/SchemaResolvers/CallableResolver.php index 5a8ecc0..b05b6f8 100644 --- a/src/Objects/SchemaResolvers/CallableResolver.php +++ b/src/Objects/SchemaResolvers/CallableResolver.php @@ -4,7 +4,6 @@ namespace FlixTech\AvroSerializer\Objects\SchemaResolvers; -use AvroSchema; use FlixTech\AvroSerializer\Objects\SchemaResolverInterface; class CallableResolver implements SchemaResolverInterface @@ -26,26 +25,22 @@ public function __construct(callable $valueSchemaResolverCallable, ?callable $ke } /** - * {@inheritdoc} - * * @throws \AvroSchemaParseException */ - public function valueSchemaFor($record): AvroSchema + public function valueSchemaFor(mixed $record): \AvroSchema { - return AvroSchema::parse(\call_user_func($this->valueSchemaResolverCallable, $record)); + return \AvroSchema::parse(\call_user_func($this->valueSchemaResolverCallable, $record)); } /** - * {@inheritdoc} - * * @throws \AvroSchemaParseException */ - public function keySchemaFor($record): ?AvroSchema + public function keySchemaFor(mixed $record): ?\AvroSchema { if (!$this->keySchemaResolverCallable) { return null; } - return AvroSchema::parse(\call_user_func($this->keySchemaResolverCallable, $record)); + return \AvroSchema::parse(\call_user_func($this->keySchemaResolverCallable, $record)); } } diff --git a/src/Objects/SchemaResolvers/ChainResolver.php b/src/Objects/SchemaResolvers/ChainResolver.php index a3351e8..4fdd7af 100644 --- a/src/Objects/SchemaResolvers/ChainResolver.php +++ b/src/Objects/SchemaResolvers/ChainResolver.php @@ -4,7 +4,6 @@ namespace FlixTech\AvroSerializer\Objects\SchemaResolvers; -use AvroSchema; use FlixTech\AvroSerializer\Objects\SchemaResolverInterface; class ChainResolver implements SchemaResolverInterface @@ -12,14 +11,14 @@ class ChainResolver implements SchemaResolverInterface /** * @var SchemaResolverInterface[] */ - private $chain; + private array $chain; public function __construct(SchemaResolverInterface ...$chain) { $this->chain = $chain; } - public function valueSchemaFor($record): AvroSchema + public function valueSchemaFor(mixed $record): \AvroSchema { foreach ($this->chain as $schemaResolver) { try { @@ -32,7 +31,7 @@ public function valueSchemaFor($record): AvroSchema throw new \InvalidArgumentException('No schema resolver in the chain is able to resolve the schema for the record'); } - public function keySchemaFor($record): ?AvroSchema + public function keySchemaFor(mixed $record): ?\AvroSchema { $keySchema = null; diff --git a/src/Objects/SchemaResolvers/DefinitionInterfaceResolver.php b/src/Objects/SchemaResolvers/DefinitionInterfaceResolver.php index d569147..3a7b817 100644 --- a/src/Objects/SchemaResolvers/DefinitionInterfaceResolver.php +++ b/src/Objects/SchemaResolvers/DefinitionInterfaceResolver.php @@ -5,31 +5,26 @@ namespace FlixTech\AvroSerializer\Objects\SchemaResolvers; use Assert\Assert; -use AvroSchema; use FlixTech\AvroSerializer\Objects\HasSchemaDefinitionInterface; use FlixTech\AvroSerializer\Objects\SchemaResolverInterface; class DefinitionInterfaceResolver implements SchemaResolverInterface { /** - * @param mixed $record - * * @throws \AvroSchemaParseException */ - public function valueSchemaFor($record): AvroSchema + public function valueSchemaFor(mixed $record): \AvroSchema { /** @var HasSchemaDefinitionInterface $record */ $this->guardRecordHasDefinition($record); - return AvroSchema::parse($record::valueSchemaJson()); + return \AvroSchema::parse($record::valueSchemaJson()); } /** - * @param mixed $record - * * @throws \AvroSchemaParseException */ - public function keySchemaFor($record): ?AvroSchema + public function keySchemaFor(mixed $record): ?\AvroSchema { $this->guardRecordHasDefinition($record); @@ -39,13 +34,10 @@ public function keySchemaFor($record): ?AvroSchema return null; } - return AvroSchema::parse($keySchemaJson); + return \AvroSchema::parse($keySchemaJson); } - /** - * @param mixed $record - */ - private function guardRecordHasDefinition($record): void + private function guardRecordHasDefinition(mixed $record): void { Assert::that($record) ->isObject() diff --git a/src/Objects/SchemaResolvers/FileResolver.php b/src/Objects/SchemaResolvers/FileResolver.php index 7879527..8a4bd34 100644 --- a/src/Objects/SchemaResolvers/FileResolver.php +++ b/src/Objects/SchemaResolvers/FileResolver.php @@ -5,15 +5,11 @@ namespace FlixTech\AvroSerializer\Objects\SchemaResolvers; use Assert\Assert; -use AvroSchema; use FlixTech\AvroSerializer\Objects\SchemaResolverInterface; class FileResolver implements SchemaResolverInterface { - /** - * @var string - */ - private $baseDir; + private string $baseDir; /** * @var callable @@ -27,11 +23,9 @@ public function __construct(string $baseDir, callable $inflector) } /** - * {@inheritdoc} - * * @throws \AvroSchemaParseException */ - public function valueSchemaFor($record): AvroSchema + public function valueSchemaFor(mixed $record): \AvroSchema { $inflectedFileName = \call_user_func($this->inflector, $record, false); Assert::that($inflectedFileName)->string()->notEmpty(); @@ -40,15 +34,13 @@ public function valueSchemaFor($record): AvroSchema Assert::that($filePath)->string()->file(); - return AvroSchema::parse((string) @\file_get_contents($filePath)); + return \AvroSchema::parse((string) @\file_get_contents($filePath)); } /** - * {@inheritdoc} - * * @throws \AvroSchemaParseException */ - public function keySchemaFor($record): ?AvroSchema + public function keySchemaFor(mixed $record): ?\AvroSchema { $inflectedFileName = \call_user_func($this->inflector, $record, true); Assert::that($inflectedFileName)->string()->notEmpty(); @@ -59,16 +51,14 @@ public function keySchemaFor($record): ?AvroSchema return null; } - return AvroSchema::parse($fileContents); + return \AvroSchema::parse($fileContents); } private function getFilePath(string $inflectedFileName): string { - $filePath = \sprintf('%s/%s', + return \sprintf('%s/%s', $this->baseDir, $inflectedFileName ); - - return $filePath; } } diff --git a/src/Protocol.php b/src/Protocol.php index 79513df..f4bbd71 100644 --- a/src/Protocol.php +++ b/src/Protocol.php @@ -30,9 +30,14 @@ function version(): int function encode(int $protocolVersion, int $schemaId, string $avroEncodedBinaryString): Either { - /** @var bool|string $packed */ + /** + * @var bool|string $packed + * + * @phpstan-ignore varTag.nativeType + */ $packed = @\pack('CNa*', $protocolVersion, $schemaId, $avroEncodedBinaryString); + /** @phpstan-ignore return.type */ return false !== $packed ? Right::of($packed) // @codeCoverageIgnoreStart @@ -65,12 +70,13 @@ function decode(string $binaryString): Either PROTOCOL_ACCESSOR_AVRO ); - /** @var array|bool $unpacked */ + /** @var array|false $unpacked */ $unpacked = @\unpack( $packedFormat, $binaryString ); + /** @phpstan-ignore return.type */ return false !== $unpacked ? Right::of($unpacked) : Left::of( diff --git a/src/Serialize.php b/src/Serialize.php index 772b224..62f247f 100644 --- a/src/Serialize.php +++ b/src/Serialize.php @@ -2,12 +2,6 @@ namespace FlixTech\AvroSerializer\Serialize; -use AvroIOBinaryDecoder; -use AvroIOBinaryEncoder; -use AvroIODatumReader; -use AvroIODatumWriter; -use AvroSchema; -use AvroStringIO; use FlixTech\AvroSerializer\Objects\Exceptions\Exceptions; use Widmogrod\Monad\Either\Either; use Widmogrod\Monad\Either\Left; @@ -21,23 +15,23 @@ /** * @throws \AvroIOException */ -function avroStringIo(string $contents): AvroStringIO +function avroStringIo(string $contents): \AvroStringIO { - return new AvroStringIO($contents); + return new \AvroStringIO($contents); } const avroBinaryEncoder = '\FlixTech\AvroSerializer\Serialize\avroBinaryEncoder'; -function avroBinaryEncoder(AvroStringIO $io): AvroIOBinaryEncoder +function avroBinaryEncoder(\AvroStringIO $io): \AvroIOBinaryEncoder { - return new AvroIOBinaryEncoder($io); + return new \AvroIOBinaryEncoder($io); } const avroBinaryDecoder = '\FlixTech\AvroSerializer\Serialize\avroBinaryDecoder'; -function avroBinaryDecoder(AvroStringIO $io): AvroIOBinaryDecoder +function avroBinaryDecoder(\AvroStringIO $io): \AvroIOBinaryDecoder { - return new AvroIOBinaryDecoder($io); + return new \AvroIOBinaryDecoder($io); } const avroDatumWriter = '\FlixTech\AvroSerializer\Serialize\avroDatumWriter'; @@ -47,7 +41,7 @@ function avroBinaryDecoder(AvroStringIO $io): AvroIOBinaryDecoder */ function avroDatumWriter(): callable { - $writer = new AvroIODatumWriter(); + $writer = new \AvroIODatumWriter(); $io = avroStringIo(''); return curryN(4, writeDatum)($writer)($io); @@ -55,10 +49,7 @@ function avroDatumWriter(): callable const writeDatum = '\FlixTech\AvroSerializer\Serialize\writeDatum'; -/** - * @param mixed $record - */ -function writeDatum(AvroIODatumWriter $writer, AvroStringIO $io, AvroSchema $schema, $record): Either +function writeDatum(\AvroIODatumWriter $writer, \AvroStringIO $io, \AvroSchema $schema, mixed $record): Either { return tryCatch( static function ($record) use ($schema, $writer, $io) { @@ -83,7 +74,7 @@ static function (\AvroException $e) use ($record, $schema) { */ function avroDatumReader(): callable { - $reader = new AvroIODatumReader(); + $reader = new \AvroIODatumReader(); $io = avroStringIo(''); return curryN(5, readDatum)($reader)($io); @@ -91,15 +82,12 @@ function avroDatumReader(): callable const readDatum = '\FlixTech\AvroSerializer\Serialize\readDatum'; -/** - * @param mixed $data - */ function readDatum( - AvroIODatumReader $reader, - AvroStringIO $io, - AvroSchema $writersSchema, - AvroSchema $readersSchema, - $data + \AvroIODatumReader $reader, + \AvroStringIO $io, + \AvroSchema $writersSchema, + \AvroSchema $readersSchema, + mixed $data, ): Either { return tryCatch( static function ($data) use ($writersSchema, $readersSchema, $reader, $io) { diff --git a/test/AbstractFunctionalTestCase.php b/test/AbstractFunctionalTestCase.php index 0073058..1996d49 100644 --- a/test/AbstractFunctionalTestCase.php +++ b/test/AbstractFunctionalTestCase.php @@ -52,11 +52,20 @@ abstract class AbstractFunctionalTestCase extends TestCase public const INVALID_AVRO_ENCODED_RECORD_HEX_BIN = '0c54615f6d608348'; public const INVALID_BIN_WRONG_VERSION = '44686f6d617348'; - protected ?\AvroSchema $avroSchema; + /** + * @var \AvroSchema + */ + protected \AvroSchema|\AvroFixedSchema|\AvroMapSchema|\AvroArraySchema|\AvroEnumSchema|\AvroPrimitiveSchema|\AvroRecordSchema|\AvroUnionSchema $avroSchema; - protected ?\AvroSchema $readersSchema; + /** + * @var \AvroSchema + */ + protected \AvroSchema|\AvroFixedSchema|\AvroMapSchema|\AvroArraySchema|\AvroEnumSchema|\AvroPrimitiveSchema|\AvroUnionSchema|\AvroRecordSchema $readersSchema; - protected ?\AvroSchema $invalidSchema; + /** + * @var \AvroSchema + */ + protected \AvroSchema|\AvroFixedSchema|\AvroMapSchema|\AvroArraySchema|\AvroEnumSchema|\AvroPrimitiveSchema|\AvroUnionSchema|\AvroRecordSchema $invalidSchema; /** * @throws \AvroSchemaParseException diff --git a/test/Integrations/Symfony/Serializer/AvroNameConverterTest.php b/test/Integrations/Symfony/Serializer/AvroNameConverterTest.php index bf3f71f..2321a2d 100644 --- a/test/Integrations/Symfony/Serializer/AvroNameConverterTest.php +++ b/test/Integrations/Symfony/Serializer/AvroNameConverterTest.php @@ -4,28 +4,20 @@ namespace FlixTech\AvroSerializer\Test\Integrations\Symfony\Serializer; -use PHPUnit\Framework\Attributes\Test; use Doctrine\Common\Annotations\AnnotationReader as DoctrineAnnotationReader; use FlixTech\AvroSerializer\Integrations\Symfony\Serializer\AvroSerDeEncoder; use FlixTech\AvroSerializer\Integrations\Symfony\Serializer\NameConverter\AvroNameConverter; use FlixTech\AvroSerializer\Objects\Schema\Generation\AnnotationReader; use FlixTech\AvroSerializer\Test\Integrations\Symfony\Serializer\Fixture\SampleUserRecord; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; -use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; class AvroNameConverterTest extends TestCase { - /** - * @var AvroNameConverter - */ - private $nameConverter; + private AvroNameConverter $nameConverter; protected function setUp(): void { - if (!\interface_exists(AdvancedNameConverterInterface::class)) { - $this->markTestSkipped('The advanced name converter is supported only in symfony 4 and forward'); - } - $this->nameConverter = new AvroNameConverter( new AnnotationReader(new DoctrineAnnotationReader()) ); diff --git a/test/Integrations/Symfony/Serializer/AvroSerDeEncoderTest.php b/test/Integrations/Symfony/Serializer/AvroSerDeEncoderTest.php index 9675eb2..edfc2ac 100644 --- a/test/Integrations/Symfony/Serializer/AvroSerDeEncoderTest.php +++ b/test/Integrations/Symfony/Serializer/AvroSerDeEncoderTest.php @@ -4,25 +4,19 @@ namespace FlixTech\AvroSerializer\Test\Integrations\Symfony\Serializer; -use PHPUnit\Framework\Attributes\Test; -use PHPUnit\Framework\Attributes\DataProvider; use FlixTech\AvroSerializer\Integrations\Symfony\Serializer\AvroSerDeEncoder; use FlixTech\AvroSerializer\Objects\RecordSerializer; use FlixTech\AvroSerializer\Test\AbstractFunctionalTestCase; -use InvalidArgumentException; +use FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; class AvroSerDeEncoderTest extends AbstractFunctionalTestCase { - /** - * @var RecordSerializer|MockObject - */ - private $recordSerializerMock; + private RecordSerializer|MockObject $recordSerializerMock; - /** - * @var AvroSerDeEncoder - */ - private $avroSerDeEncoder; + private AvroSerDeEncoder $avroSerDeEncoder; protected function setUp(): void { @@ -49,6 +43,10 @@ public function it_should_only_support_decoding_Avro_format(): void $this->assertFalse($this->avroSerDeEncoder->supportsDecoding('any')); } + /** + * @throws \AvroSchemaParseException + * @throws SchemaRegistryException + */ #[Test] public function it_should_encode_with_valid_encode_context(): void { @@ -71,24 +69,15 @@ public function it_should_encode_with_valid_encode_context(): void $this->assertSame('success', $result); } + /** + * @throws SchemaRegistryException + */ #[Test] public function it_should_decode_with_valid_decode_context(): void { - $matcher = $this->exactly(2); - $this->recordSerializerMock->expects($matcher) + $this->recordSerializerMock->expects($this->exactly(2)) ->method('decodeMessage') - ->willReturnCallback( - function (...$parameters) use ($matcher) { - match ($matcher->numberOfInvocations()) { - 1 => self::assertEquals([AbstractFunctionalTestCase::AVRO_ENCODED_RECORD_HEX_BIN, null], $parameters), - 2 => self::assertEquals([AbstractFunctionalTestCase::AVRO_ENCODED_RECORD_HEX_BIN, $this->readersSchema], $parameters), - }; - return match ($matcher->numberOfInvocations()) { - 1 => 'success-1', - 2 => 'success-2', - }; - } - ); + ->willReturnOnConsecutiveCalls('success-1', 'success-2'); $result = $this->avroSerDeEncoder->decode( AbstractFunctionalTestCase::AVRO_ENCODED_RECORD_HEX_BIN, @@ -108,11 +97,15 @@ function (...$parameters) use ($matcher) { $this->assertSame('success-2', $result); } - #[DataProvider('encodeContextValidationDataProvider')] + /** + * @throws SchemaRegistryException + * @throws \AvroSchemaParseException + */ #[Test] + #[DataProvider('encodeContextValidationDataProvider')] public function it_should_validate_encode_context(array $context): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(\InvalidArgumentException::class); $this->recordSerializerMock->expects($this->never()) ->method('encodeRecord'); @@ -123,7 +116,10 @@ public function it_should_validate_encode_context(array $context): void ); } - public static function encodeContextValidationDataProvider(): \Generator + /** + * @throws \AvroSchemaParseException + */ + public static function encodeContextValidationDataProvider(): ?\Generator { yield 'Invalid writer\'s schema in encode context' => [ [ diff --git a/test/Integrations/Symfony/Serializer/Fixture/SampleUserRecord.php b/test/Integrations/Symfony/Serializer/Fixture/SampleUserRecord.php index f4e7d6e..d35efc6 100644 --- a/test/Integrations/Symfony/Serializer/Fixture/SampleUserRecord.php +++ b/test/Integrations/Symfony/Serializer/Fixture/SampleUserRecord.php @@ -8,12 +8,14 @@ /** * @SerDe\AvroType("record") + * * @SerDe\AvroName("SampleUserRecord") */ class SampleUserRecord { /** * @SerDe\AvroName("Name") + * * @SerDe\AvroType("string") */ private $name; diff --git a/test/Objects/DefaultRecordSerializerFactoryTest.php b/test/Objects/DefaultRecordSerializerFactoryTest.php index 6d3e6af..57de466 100644 --- a/test/Objects/DefaultRecordSerializerFactoryTest.php +++ b/test/Objects/DefaultRecordSerializerFactoryTest.php @@ -4,8 +4,8 @@ namespace FlixTech\AvroSerializer\Test\Objects; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\DefaultRecordSerializerFactory; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class DefaultRecordSerializerFactoryTest extends TestCase diff --git a/test/Objects/RecordSerializerIntegrationTest.php b/test/Objects/RecordSerializerIntegrationTest.php index 8f16970..8449992 100644 --- a/test/Objects/RecordSerializerIntegrationTest.php +++ b/test/Objects/RecordSerializerIntegrationTest.php @@ -4,14 +4,14 @@ namespace FlixTech\AvroSerializer\Test\Objects; -use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\Attributes\Test; -use PHPUnit\Framework\Attributes\Depends; -use FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException; use FlixTech\AvroSerializer\Objects\DefaultRecordSerializerFactory; use FlixTech\AvroSerializer\Objects\RecordSerializer; use FlixTech\AvroSerializer\Test\AbstractFunctionalTestCase; use FlixTech\SchemaRegistryApi\Exception\IncompatibleAvroSchemaException; +use FlixTech\SchemaRegistryApi\Exception\SchemaRegistryException; +use PHPUnit\Framework\Attributes\Depends; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\Test; #[Group('integration')] class RecordSerializerIntegrationTest extends AbstractFunctionalTestCase @@ -32,12 +32,10 @@ public function it_encodes_valid_records(): RecordSerializer } /** - * - * * @throws SchemaRegistryException */ - #[Depends('it_encodes_valid_records')] #[Test] + #[Depends('it_encodes_valid_records')] public function it_cannot_evolve_incompatible_schema(RecordSerializer $serializer): void { $this->expectException(IncompatibleAvroSchemaException::class); @@ -45,12 +43,10 @@ public function it_cannot_evolve_incompatible_schema(RecordSerializer $serialize } /** - * - * * @throws SchemaRegistryException */ - #[Depends('it_encodes_valid_records')] #[Test] + #[Depends('it_encodes_valid_records')] public function it_decodes_with_readers_schema(RecordSerializer $serializer): RecordSerializer { $encoded = $serializer->encodeRecord('test-value', $this->avroSchema, self::TEST_RECORD); diff --git a/test/Objects/RecordSerializerTest.php b/test/Objects/RecordSerializerTest.php index fddf154..f39bfb9 100644 --- a/test/Objects/RecordSerializerTest.php +++ b/test/Objects/RecordSerializerTest.php @@ -4,7 +4,6 @@ namespace FlixTech\AvroSerializer\Test\Objects; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Exceptions\AvroEncodingException; use FlixTech\AvroSerializer\Objects\RecordSerializer; use FlixTech\AvroSerializer\Test\AbstractFunctionalTestCase; @@ -13,31 +12,28 @@ use FlixTech\SchemaRegistryApi\Exception\SubjectNotFoundException; use FlixTech\SchemaRegistryApi\Registry; use GuzzleHttp\Promise\FulfilledPromise; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use function FlixTech\AvroSerializer\Common\memoize; class RecordSerializerTest extends AbstractFunctionalTestCase { - /** - * @var Registry|MockObject - */ - private $registryMock; + private Registry|MockObject $registryMock; - /** - * @var RecordSerializer - */ - private $recordSerializer; + private RecordSerializer $recordSerializer; /** - * @throws \ReflectionException * @throws \AvroSchemaParseException + * @throws \AvroIOException + * @throws Exception */ protected function setUp(): void { parent::setUp(); - $this->registryMock = $this->getMockForAbstractClass(Registry::class); + $this->registryMock = $this->getMockBuilder(Registry::class)->getMock(); $this->recordSerializer = new RecordSerializer($this->registryMock); } @@ -53,23 +49,10 @@ protected function tearDown(): void #[Test] public function it_should_encode_a_record_with_schema_and_subject(): void { - $matcher = $this->exactly(2); $this->registryMock - ->expects($matcher) + ->expects($this->exactly(2)) ->method('schemaId') - ->willReturnCallback( - function (...$parameters) use ($matcher) { - match ($matcher->numberOfInvocations()) { - 1 => self::assertEquals(['test', $this->avroSchema], $parameters), - 2 => self::assertEquals(['test', $this->avroSchema], $parameters), - }; - - return match ($matcher->numberOfInvocations()) { - 1 => self::SCHEMA_ID, - 2 => new FulfilledPromise(self::SCHEMA_ID), - }; - } - ); + ->willReturnOnConsecutiveCalls(self::SCHEMA_ID, new FulfilledPromise(self::SCHEMA_ID)); $this->assertSame( self::HEX_BIN, @@ -121,9 +104,11 @@ public function it_should_not_register_new_schemas_by_default(): void } /** + * @test + * * @throws SchemaRegistryException + * @throws \AvroIOException */ - #[Test] public function it_should_register_new_schemas_when_configured(): void { $recordSerializer = new RecordSerializer($this->registryMock, ['register_missing_schemas' => true]); @@ -134,22 +119,10 @@ public function it_should_register_new_schemas_when_configured(): void ->with('test', $this->avroSchema) ->willThrowException(new SchemaNotFoundException()); - $returns = [ - [['test', $this->avroSchema], self::SCHEMA_ID], - [['test', $this->avroSchema], new FulfilledPromise(self::SCHEMA_ID)] - ]; - $this->registryMock ->expects($this->exactly(2)) ->method('register') - ->willReturnCallback( - function (...$args) use (&$returns){ - [$expectedArgs, $return] = array_shift($returns); - - self::assertEquals($expectedArgs, $args); - return $return; - } - ); + ->willReturn(self::SCHEMA_ID, new FulfilledPromise(self::SCHEMA_ID)); $this->assertSame( self::HEX_BIN, @@ -185,6 +158,7 @@ public function it_should_fail_when_the_subject_is_not_found(): void /** * @throws SchemaRegistryException + * @throws \AvroIOException */ #[Test] public function it_should_register_new_subject_when_configured(): void @@ -196,23 +170,11 @@ public function it_should_register_new_subject_when_configured(): void ->method('schemaId') ->with('test', $this->avroSchema) ->willThrowException(new SubjectNotFoundException()); - $matcher = $this->exactly(2); $this->registryMock - ->expects($matcher) + ->expects($this->exactly(2)) ->method('register') - ->willReturnCallback( - function (...$parameters) use ($matcher) { - match ($matcher->numberOfInvocations()) { - 1 => self::assertEquals(['test', $this->avroSchema], $parameters), - 2 => self::assertEquals(['test', $this->avroSchema], $parameters), - }; - return match ($matcher->numberOfInvocations()) { - 1 => self::SCHEMA_ID, - 2 => new FulfilledPromise(self::SCHEMA_ID), - }; - } - ); + ->willReturnOnConsecutiveCalls(self::SCHEMA_ID, new FulfilledPromise(self::SCHEMA_ID)); $this->assertSame( self::HEX_BIN, @@ -246,6 +208,9 @@ public function it_should_fail_when_the_subject_is_not_found_via_promise(): void $this->recordSerializer->encodeRecord('test', $this->avroSchema, self::TEST_RECORD); } + /** + * @throws SchemaRegistryException + */ #[Test] public function it_should_fail_when_an_unexpected_exception_is_wrapped_in_a_promise(): void { @@ -269,22 +234,10 @@ public function it_should_fail_when_an_unexpected_exception_is_wrapped_in_a_prom #[Test] public function it_should_decode_wire_protocol_messages_correctly(): void { - $matcher = $this->exactly(2); $this->registryMock - ->expects($matcher) + ->expects($this->exactly(2)) ->method('schemaForId') - ->willReturnCallback( - function (...$parameters) use ($matcher) { - match ($matcher->numberOfInvocations()) { - 1 => self::assertEquals([self::SCHEMA_ID], $parameters), - 2 => self::assertEquals([self::SCHEMA_ID], $parameters), - }; - return match ($matcher->numberOfInvocations()) { - 1 => $this->avroSchema, - 2 => new FulfilledPromise($this->avroSchema), - }; - } - ); + ->willReturnOnConsecutiveCalls($this->avroSchema, new FulfilledPromise($this->avroSchema)); $this->assertSame( self::TEST_RECORD, @@ -304,22 +257,10 @@ function (...$parameters) use ($matcher) { #[Test] public function it_should_decode_with_readers_schema(): void { - $matcher = $this->exactly(2); $this->registryMock - ->expects($matcher) + ->expects($this->exactly(2)) ->method('schemaForId') - ->willReturnCallback( - function (...$parameters) use ($matcher) { - match ($matcher->numberOfInvocations()) { - 1 => self::assertEquals([self::SCHEMA_ID], $parameters), - 2 => self::assertEquals([self::SCHEMA_ID], $parameters), - }; - return match ($matcher->numberOfInvocations()) { - 1 => $this->avroSchema, - 2 => new FulfilledPromise($this->avroSchema), - }; - } - ); + ->willReturnOnConsecutiveCalls($this->avroSchema, new FulfilledPromise($this->avroSchema)); $this->assertSame( self::READERS_TEST_RECORD, diff --git a/test/Objects/Schema/ArrayTypeTest.php b/test/Objects/Schema/ArrayTypeTest.php index 2182cfb..7460551 100644 --- a/test/Objects/Schema/ArrayTypeTest.php +++ b/test/Objects/Schema/ArrayTypeTest.php @@ -4,8 +4,8 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Schema; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class ArrayTypeTest extends TestCase @@ -35,7 +35,6 @@ public function it_should_parse_array_types(): void ->default(['foo', 'bar']) ->parse(); - $this->assertInstanceOf(\AvroSchema::class, $parsedSchema); $this->assertEquals('array', $parsedSchema->type()); } } diff --git a/test/Objects/Schema/EnumTypeTest.php b/test/Objects/Schema/EnumTypeTest.php index db776b5..2e8da28 100644 --- a/test/Objects/Schema/EnumTypeTest.php +++ b/test/Objects/Schema/EnumTypeTest.php @@ -4,8 +4,8 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Schema; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class EnumTypeTest extends TestCase @@ -43,10 +43,10 @@ public function it_should_parse_enum_types(): void ->namespace('com.org.acme') ->aliases('outfit', 'elegant') ->doc('Suit up!') - ->symbols(...['SPADES', 'HEARTS', 'DIAMONDS', 'CLUBS']) + ->symbols('SPADES', 'HEARTS', 'DIAMONDS', 'CLUBS') ->default('SPADES') ->parse(); - $this->assertInstanceOf(\AvroSchema::class, $parsedSchema); + $this->assertEquals('enum', $parsedSchema->type()); } } diff --git a/test/Objects/Schema/FixedTypeTest.php b/test/Objects/Schema/FixedTypeTest.php index 01b08e1..db9c956 100644 --- a/test/Objects/Schema/FixedTypeTest.php +++ b/test/Objects/Schema/FixedTypeTest.php @@ -4,8 +4,8 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Schema; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class FixedTypeTest extends TestCase @@ -41,7 +41,6 @@ public function it_should_parse_fixed_types(): void ->aliases('hash', 'fileHash') ->parse(); - $this->assertInstanceOf(\AvroSchema::class, $parsedSchema); $this->assertEquals('fixed', $parsedSchema->type()); } } diff --git a/test/Objects/Schema/Generation/Fixture/ArraysWithComplexType.php b/test/Objects/Schema/Generation/Fixture/ArraysWithComplexType.php index ff552e3..aed36ec 100644 --- a/test/Objects/Schema/Generation/Fixture/ArraysWithComplexType.php +++ b/test/Objects/Schema/Generation/Fixture/ArraysWithComplexType.php @@ -5,29 +5,57 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture; use FlixTech\AvroSerializer\Objects\Schema\Generation\Annotations as SerDe; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroItems; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroName; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroType; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroValues; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\Type; /** * @SerDe\AvroType("record") + * * @SerDe\AvroName("ArraysWithComplexType") */ +#[AvroType('record')] +#[AvroName('ArraysWithComplexType')] class ArraysWithComplexType { /** * @SerDe\AvroType("array", attributes={ + * * @SerDe\AvroItems({ * "string", + * * @SerDe\AvroType("array", attributes={@SerDe\AvroItems(@SerDe\AvroType("string"))}) * }) * }) */ - private $arrayWithUnion; + #[AvroType( + 'array', + attributes: new AvroItems( + new AvroType(Type::STRING), + new AvroType(Type::ARRAY, new AvroItems(new AvroType(Type::STRING))), + ) + )] + private array $arrayWithUnion; /** * @SerDe\AvroType("array", attributes={ + * * @SerDe\AvroItems( + * * @SerDe\AvroType("map", attributes={@SerDe\AvroValues(@SerDe\AvroType("string"))}) * ) * }) */ - private $arrayWithMap; + #[AvroType( + Type::ARRAY, + attributes: new AvroItems( + new AvroType( + Type::MAP, + new AvroValues(new AvroType(Type::STRING)) + ), + ) + )] + private array $arrayWithMap; } diff --git a/test/Objects/Schema/Generation/Fixture/EmptyRecord.php b/test/Objects/Schema/Generation/Fixture/EmptyRecord.php index 0825882..6ca4dc4 100644 --- a/test/Objects/Schema/Generation/Fixture/EmptyRecord.php +++ b/test/Objects/Schema/Generation/Fixture/EmptyRecord.php @@ -5,12 +5,20 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture; use FlixTech\AvroSerializer\Objects\Schema\Generation\Annotations as SerDe; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroName; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroNamespace; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroType; /** * @SerDe\AvroName("EmptyRecord") + * * @SerDe\AvroNamespace("org.acme") + * * @SerDe\AvroType("record") */ +#[AvroName('EmptyRecord')] +#[AvroNamespace('org.acme')] +#[AvroType('record')] class EmptyRecord { } diff --git a/test/Objects/Schema/Generation/Fixture/MapsWithComplexType.php b/test/Objects/Schema/Generation/Fixture/MapsWithComplexType.php index cc178a7..1438c84 100644 --- a/test/Objects/Schema/Generation/Fixture/MapsWithComplexType.php +++ b/test/Objects/Schema/Generation/Fixture/MapsWithComplexType.php @@ -5,29 +5,60 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture; use FlixTech\AvroSerializer\Objects\Schema\Generation\Annotations as SerDe; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroItems; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroName; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroType; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroValues; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\Type; /** * @SerDe\AvroType("record") + * * @SerDe\AvroName("MapsWithComplexType") */ +#[AvroType(Type::RECORD)] +#[AvroName('MapsWithComplexType')] class MapsWithComplexType { /** * @SerDe\AvroType("map", attributes={ + * * @SerDe\AvroValues({ * "string", + * * @SerDe\AvroType("array", attributes={@SerDe\AvroItems("string")}) * }) * }) */ + #[AvroType( + Type::MAP, + new AvroValues( + Type::STRING, + new AvroType( + Type::ARRAY, + new AvroItems(Type::STRING) + ) + ) + )] private $mapWithUnion; /** * @SerDe\AvroType("map", attributes={ + * * @SerDe\AvroValues( + * * @SerDe\AvroType("array", attributes={@SerDe\AvroItems("string")}) * ) * }) */ + #[AvroType( + Type::MAP, + new AvroValues( + new AvroType( + Type::ARRAY, + new AvroItems(Type::STRING) + ) + ) + )] private $mapWithArray; } diff --git a/test/Objects/Schema/Generation/Fixture/PrimitiveTypes.php b/test/Objects/Schema/Generation/Fixture/PrimitiveTypes.php index efadf45..1dffba9 100644 --- a/test/Objects/Schema/Generation/Fixture/PrimitiveTypes.php +++ b/test/Objects/Schema/Generation/Fixture/PrimitiveTypes.php @@ -5,56 +5,87 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture; use FlixTech\AvroSerializer\Objects\Schema\Generation\Annotations as SerDe; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroAliases; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroDefault; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroDoc; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroName; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroNamespace; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroOrder; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroType; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\Order; /** * @SerDe\AvroName("PrimitiveTypes") + * * @SerDe\AvroNamespace("org.acme") + * * @SerDe\AvroType("record") */ +#[AvroName('PrimitiveTypes')] +#[AvroNamespace('org.acme')] +#[AvroType('record')] class PrimitiveTypes { /** * @SerDe\AvroDoc("null type") + * * @SerDe\AvroType("null") */ + #[AvroDoc('null type')] + #[AvroType('null')] private $nullType; /** * @SerDe\AvroName("isItTrue") + * * @SerDe\AvroDefault(false) + * * @SerDe\AvroType("boolean") */ + #[AvroName('isItTrue')] + #[AvroDefault(false)] + #[AvroType('boolean')] private $booleanType; /** * @SerDe\AvroType("int") */ + #[AvroType('int')] private $intType; /** * @SerDe\AvroType("long") + * * @SerDe\AvroOrder("ascending") */ + #[AvroType('long')] + #[AvroOrder(Order::ASC)] private $longType; /** * @SerDe\AvroType("float") + * * @SerDe\AvroAliases({"foo", "bar"}) */ + #[AvroType('float')] + #[AvroAliases('foo', 'bar')] private $floatType; /** * @SerDe\AvroType("double") */ + #[AvroType('double')] private $doubleType; /** * @SerDe\AvroType("bytes") */ + #[AvroType('bytes')] private $bytesType; /** * @SerDe\AvroType("string") */ + #[AvroType('string')] private $stringType; } diff --git a/test/Objects/Schema/Generation/Fixture/RecordWithComplexTypes.php b/test/Objects/Schema/Generation/Fixture/RecordWithComplexTypes.php index 59cd395..5280126 100644 --- a/test/Objects/Schema/Generation/Fixture/RecordWithComplexTypes.php +++ b/test/Objects/Schema/Generation/Fixture/RecordWithComplexTypes.php @@ -5,54 +5,108 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture; use FlixTech\AvroSerializer\Objects\Schema\Generation\Annotations as SerDe; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroAliases; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroDefault; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroItems; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroName; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroNamespace; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroOrder; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroSize; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroSymbols; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroType; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\AvroValues; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\Order; +use FlixTech\AvroSerializer\Objects\Schema\Generation\Attributes\Type; /** * @SerDe\AvroType("record") + * * @SerDe\AvroName("RecordWithComplexTypes") */ +#[AvroType('record')] +#[AvroName('RecordWithComplexTypes')] class RecordWithComplexTypes { /** * @SerDe\AvroType("array", attributes={ + * * @SerDe\AvroItems("string"), + * * @SerDe\AvroDefault({"foo", "bar"}), * }) */ + #[AvroType( + 'array', + new AvroItems(Type::STRING), new AvroDefault(['foo', 'bar']) + )] private $array; /** * @SerDe\AvroType("map", attributes={ + * * @SerDe\AvroValues("int"), + * * @SerDe\AvroDefault({"foo": 42, "bar": 42}), * }) */ + #[AvroType( + 'map', + new AvroValues(Type::INT), new AvroDefault(['foo' => 42, 'bar' => 42]) + )] private $map; /** * @SerDe\AvroOrder("ascending") + * * @SerDe\AvroType("enum", attributes={ + * * @SerDe\AvroName("Suit"), + * * @SerDe\AvroSymbols({"SPADES", "HEARTS", "DIAMONDS", "CLUBS"}) * }) */ + #[AvroOrder(Order::ASC)] + #[AvroType( + Type::ENUM, + new AvroName('Suit'), + new AvroSymbols(['SPADES', 'HEARTS', 'DIAMONDS', 'CLUBS']) + )] private $enum; /** * @SerDe\AvroType("fixed", attributes={ + * * @SerDe\AvroName("md5"), + * * @SerDe\AvroNamespace("org.acme"), + * * @SerDe\AvroAliases({"foo", "bar"}), + * * @SerDe\AvroSize(16) * }) */ + #[AvroType( + Type::FIXED, + new AvroName('md5'), + new AvroNamespace('org.acme'), + new AvroAliases('foo', 'bar'), + new AvroSize(16) + )] private $fixed; /** * @SerDe\AvroType("string") * @SerDe\AvroType("int") * @SerDe\AvroType("array", attributes={ + * * @SerDe\AvroItems("string"), * }) */ + #[AvroType(Type::STRING)] + #[AvroType(Type::INT)] + #[AvroType( + Type::ARRAY, + new AvroItems(Type::STRING) + )] private $union; } diff --git a/test/Objects/Schema/Generation/Fixture/RecordWithRecordType.php b/test/Objects/Schema/Generation/Fixture/RecordWithRecordType.php index 0197ce1..2a90288 100644 --- a/test/Objects/Schema/Generation/Fixture/RecordWithRecordType.php +++ b/test/Objects/Schema/Generation/Fixture/RecordWithRecordType.php @@ -12,33 +12,38 @@ /** * @SerDe\AvroType("record") + * * @SerDe\AvroName("RecordWithRecordType") */ -#[AvroType("record")] -#[AvroName("RecordWithRecordType")] +#[AvroType('record')] +#[AvroName('RecordWithRecordType')] class RecordWithRecordType { /** * @SerDe\AvroName("simpleField") + * * @SerDe\AvroType("record", attributes={ + * * @SerDe\AvroTargetClass("\FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\SimpleRecord"), + * * @SerDe\AvroDoc("This a simple record for testing purposes") * }) */ - #[AvroName("simpleField")] - #[AvroType("record", + #[AvroName('simpleField')] + #[AvroType('record', new AvroTargetClass(SimpleRecord::class), - new AvroDoc("This a simple record for testing purposes") + new AvroDoc('This a simple record for testing purposes') )] private SimpleRecord $simpleRecord; /** * @SerDe\AvroName("unionField") + * * @SerDe\AvroType("null") * @SerDe\AvroType("org.acme.SimpleRecord") */ - #[AvroName("unionField")] - #[AvroType("null")] - #[AvroType("org.acme.SimpleRecord")] + #[AvroName('unionField')] + #[AvroType('null')] + #[AvroType('org.acme.SimpleRecord')] private ?SimpleRecord $unionRecord; } diff --git a/test/Objects/Schema/Generation/Fixture/SimpleRecord.php b/test/Objects/Schema/Generation/Fixture/SimpleRecord.php index 114044e..148d402 100644 --- a/test/Objects/Schema/Generation/Fixture/SimpleRecord.php +++ b/test/Objects/Schema/Generation/Fixture/SimpleRecord.php @@ -12,31 +12,34 @@ /** * @SerDe\AvroName("SimpleRecord") + * * @SerDe\AvroNamespace("org.acme") + * * @SerDe\AvroType("record") */ -#[AvroName("SimpleRecord")] -#[AvroNamespace("org.acme")] -#[AvroType("record")] +#[AvroName('SimpleRecord')] +#[AvroNamespace('org.acme')] +#[AvroType('record')] class SimpleRecord { /** * @SerDe\AvroType("int") + * * @SerDe\AvroDefault(42) */ - #[AvroType("int")] + #[AvroType('int')] #[AvroDefault(42)] private $intType; /** * @SerDe\AvroType("uuid") */ - #[AvroType("uuid")] + #[AvroType('uuid')] private $uuidType; /** * @SerDe\AvroType("timestamp-millis") */ - #[AvroType("timestamp-millis")] + #[AvroType('timestamp-millis')] private $timestampMillisType; } diff --git a/test/Objects/Schema/Generation/SchemaGeneratorTest.php b/test/Objects/Schema/Generation/SchemaGeneratorTest.php index e909d29..a9ef7a5 100644 --- a/test/Objects/Schema/Generation/SchemaGeneratorTest.php +++ b/test/Objects/Schema/Generation/SchemaGeneratorTest.php @@ -4,26 +4,25 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema\Generation; -use FlixTech\AvroSerializer\Objects\Schema\Generation\SchemaGenerator; -use FlixTech\AvroSerializer\Objects\Schema\Generation\AttributeReader; -use PHPUnit\Framework\Attributes\Test; -use FlixTech\AvroSerializer\Objects\Schema\Record\FieldOption; -use FlixTech\AvroSerializer\Objects\Schema\Record\FieldOrder; use Doctrine\Common\Annotations\AnnotationReader; use FlixTech\AvroSerializer\Objects\Schema; +use FlixTech\AvroSerializer\Objects\Schema\Generation\AttributeReader; +use FlixTech\AvroSerializer\Objects\Schema\Generation\SchemaGenerator; use FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\ArraysWithComplexType; use FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\EmptyRecord; use FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\MapsWithComplexType; use FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\PrimitiveTypes; use FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\RecordWithComplexTypes; use FlixTech\AvroSerializer\Test\Objects\Schema\Generation\Fixture\RecordWithRecordType; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class SchemaGeneratorTest extends TestCase { - private ?SchemaGenerator $generatorDoctrineAnnotations; + private SchemaGenerator $generatorDoctrineAnnotations; - private ?SchemaGenerator $generatorAttributes; + private SchemaGenerator $generatorAttributes; protected function setUp(): void { @@ -38,235 +37,193 @@ protected function setUp(): void ); } + /** + * @throws \ReflectionException + */ #[Test] - public function it_should_generate_an_empty_record() - { - $schema = $this->generatorDoctrineAnnotations->generate(EmptyRecord::class); - - $expected = Schema::record() - ->name('EmptyRecord') - ->namespace('org.acme'); - - $this->assertEquals($expected, $schema); - } - - #[Test] - public function it_should_generate_a_record_schema_with_primitive_types() + #[DataProvider('schemaDataProvider')] + public function it_should_generate_schema_using_doctrine_annotations(string $class, Schema $expectedSchema): void { - $schema = $this->generatorDoctrineAnnotations->generate(PrimitiveTypes::class); - - $expected = Schema::record() - ->name('PrimitiveTypes') - ->namespace('org.acme') - ->field( - 'nullType', - Schema::null(), - FieldOption::doc('null type') - ) - ->field( - 'isItTrue', - Schema::boolean(), - FieldOption::default(false) - ) - ->field( - 'intType', - Schema::int() - ) - ->field( - 'longType', - Schema::long(), - FieldOption::orderAsc() - ) - ->field( - 'floatType', - Schema::float(), - FieldOption::aliases('foo', 'bar') - ) - ->field( - 'doubleType', - Schema::double() - ) - ->field( - 'bytesType', - Schema::bytes() - ) - ->field( - 'stringType', - Schema::string() - ); + $actualSchema = $this->generatorDoctrineAnnotations->generate($class); - $this->assertEquals($expected, $schema); + self::assertEquals($expectedSchema, $actualSchema); } + /** + * @throws \ReflectionException + */ #[Test] - public function it_should_generate_a_schema_record_with_complex_types() + #[DataProvider('schemaDataProvider')] + public function it_should_generate_schema_using_attributes(string $class, Schema $expectedSchema): void { - $schema = $this->generatorDoctrineAnnotations->generate(RecordWithComplexTypes::class); + $actualSchema = $this->generatorAttributes->generate($class); - $expected = Schema::record() - ->name('RecordWithComplexTypes') - ->field( - 'array', - Schema::array() - ->items(Schema::string()) - ->default(['foo', 'bar']) - ) - ->field( - 'map', - Schema::map() - ->values(Schema::int()) - ->default(['foo' => 42, 'bar' => 42]) - ) - ->field( - 'enum', - Schema::enum() - ->name('Suit') - ->symbols('SPADES', 'HEARTS', 'DIAMONDS', 'CLUBS'), - FieldOrder::asc() - ) - ->field( - 'fixed', - Schema::fixed() - ->name('md5') - ->namespace('org.acme') - ->aliases('foo', 'bar') - ->size(16) - ) - ->field( - 'union', - Schema::union(Schema::string(), Schema::int(), Schema::array()->items(Schema::string())) - ); - - $this->assertEquals($expected, $schema); + self::assertEquals($expectedSchema, $actualSchema); } - #[Test] - public function it_should_generate_records_containing_records() + public static function schemaDataProvider(): array { - $schema = $this->generatorDoctrineAnnotations->generate(RecordWithRecordType::class); - - $expected = Schema::record() - ->name('RecordWithRecordType') - ->field( - 'simpleField', - Schema::record() - ->name('SimpleRecord') + return [ + 'empty record' => [ + 'class' => EmptyRecord::class, + 'expectedSchema' => Schema::record() + ->name('EmptyRecord') + ->namespace('org.acme'), + ], + 'primitive types' => [ + 'class' => PrimitiveTypes::class, + 'expectedSchema' => Schema::record() + ->name('PrimitiveTypes') ->namespace('org.acme') - ->doc('This a simple record for testing purposes') + ->field( + 'nullType', + Schema::null(), + Schema\Record\FieldOption::doc('null type') + ) + ->field( + 'isItTrue', + Schema::boolean(), + Schema\Record\FieldOption::default(false) + ) ->field( 'intType', - Schema::int(), - FieldOption::default(42) + Schema::int() ) ->field( - 'uuidType', - Schema::uuid() + 'longType', + Schema::long(), + Schema\Record\FieldOption::orderAsc() ) ->field( - 'timestampMillisType', - Schema::timestampMillis() - ), - ) - ->field( - 'unionField', - Schema::union( - Schema::null(), - Schema::named('org.acme.SimpleRecord') - ) - ); - - $this->assertEquals($expected, $schema); - } - - public function test_it_should_generate_records_containing_records_using_attributes(): void - { - $schema = $this->generatorAttributes->generate(RecordWithRecordType::class); - - $expected = Schema::record() - ->name('RecordWithRecordType') - ->field( - 'simpleField', - Schema::record() - ->name('SimpleRecord') - ->namespace('org.acme') - ->doc('This a simple record for testing purposes') + 'floatType', + Schema::float(), + Schema\Record\FieldOption::aliases('foo', 'bar') + ) ->field( - 'intType', - Schema::int(), - FieldOption::default(42) - )->field( - 'uuidType', - Schema::uuid() + 'doubleType', + Schema::double() ) ->field( - 'timestampMillisType', - Schema::timestampMillis() + 'bytesType', + Schema::bytes() + ) + ->field( + 'stringType', + Schema::string() ), - ) - ->field( - 'unionField', - Schema::union( - Schema::null(), - Schema::named('org.acme.SimpleRecord') - ) - ); - - $this->assertEquals($expected, $schema); - } - - #[Test] - public function it_should_generate_a_record_schema_with_arrays_containing_complex_types() - { - $schema = $this->generatorDoctrineAnnotations->generate(ArraysWithComplexType::class); - - $expected = Schema::record() - ->name('ArraysWithComplexType') - ->field( - 'arrayWithUnion', - Schema::array() - ->items( - Schema::union( - Schema::string(), - Schema::array()->items(Schema::string()) - ) + ], + 'record with complex types' => [ + 'class' => RecordWithComplexTypes::class, + 'expectedSchema' => Schema::record() + ->name('RecordWithComplexTypes') + ->field( + 'array', + Schema::array() + ->items(Schema::string()) + ->default(['foo', 'bar']) ) - ) - ->field( - 'arrayWithMap', - Schema::array() - ->items( - Schema::map()->values(Schema::string()) + ->field( + 'map', + Schema::map() + ->values(Schema::int()) + ->default(['foo' => 42, 'bar' => 42]) ) - ); - - $this->assertEquals($expected, $schema); - } - - #[Test] - public function it_should_generate_a_record_schema_with_maps_containing_complex_types() - { - $schema = $this->generatorDoctrineAnnotations->generate(MapsWithComplexType::class); - - $expected = Schema::record() - ->name('MapsWithComplexType') - ->field( - 'mapWithUnion', - Schema::map() - ->values( + ->field( + 'enum', + Schema::enum() + ->name('Suit') + ->symbols('SPADES', 'HEARTS', 'DIAMONDS', 'CLUBS'), + Schema\Record\FieldOrder::asc() + ) + ->field( + 'fixed', + Schema::fixed() + ->name('md5') + ->namespace('org.acme') + ->aliases('foo', 'bar') + ->size(16) + ) + ->field( + 'union', + Schema::union(Schema::string(), Schema::int(), Schema::array()->items(Schema::string())) + ), + ], + 'record with record type' => [ + 'class' => RecordWithRecordType::class, + 'expectedSchema' => Schema::record() + ->name('RecordWithRecordType') + ->field( + 'simpleField', + Schema::record() + ->name('SimpleRecord') + ->namespace('org.acme') + ->doc('This a simple record for testing purposes') + ->field( + 'intType', + Schema::int(), + Schema\Record\FieldOption::default(42) + ) + ->field( + 'uuidType', + Schema::uuid() + ) + ->field( + 'timestampMillisType', + Schema::timestampMillis() + ), + ) + ->field( + 'unionField', Schema::union( - Schema::string(), - Schema::array()->items(Schema::string()) + Schema::null(), + Schema::named('org.acme.SimpleRecord') ) + ), + ], + 'arrays with complex type' => [ + 'class' => ArraysWithComplexType::class, + 'expectedSchema' => Schema::record() + ->name('ArraysWithComplexType') + ->field( + 'arrayWithUnion', + Schema::array() + ->items( + Schema::union( + Schema::string(), + Schema::array()->items(Schema::string()) + ) + ) ) - ) - ->field( - 'mapWithArray', - Schema::map() - ->values( - Schema::array()->items(Schema::string()) + ->field( + 'arrayWithMap', + Schema::array() + ->items( + Schema::map()->values(Schema::string()) + ) + ), + ], + 'maps with complex type' => [ + 'class' => MapsWithComplexType::class, + 'expectedSchema' => Schema::record() + ->name('MapsWithComplexType') + ->field( + 'mapWithUnion', + Schema::map() + ->values( + Schema::union( + Schema::string(), + Schema::array()->items(Schema::string()) + ) + ) ) - ); - - $this->assertEquals($expected, $schema); + ->field( + 'mapWithArray', + Schema::map() + ->values( + Schema::array()->items(Schema::string()) + ) + ), + ], + ]; } } diff --git a/test/Objects/Schema/LogicalTypeTest.php b/test/Objects/Schema/LogicalTypeTest.php index bc93c95..bbcdb73 100644 --- a/test/Objects/Schema/LogicalTypeTest.php +++ b/test/Objects/Schema/LogicalTypeTest.php @@ -4,16 +4,16 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema; +use FlixTech\AvroSerializer\Objects\Schema; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; -use FlixTech\AvroSerializer\Objects\Schema; use PHPUnit\Framework\TestCase; class LogicalTypeTest extends TestCase { - #[DataProvider('provideLogicalTypes')] #[Test] - public function it_should_serialize_simple_logical_types(Schema $type, string $expectedAnnotatedType, string $expectedLogicalType) + #[DataProvider('provideLogicalTypes')] + public function it_should_serialize_simple_logical_types(Schema $type, string $expectedAnnotatedType, string $expectedLogicalType): void { $expectedSchema = [ 'type' => $expectedAnnotatedType, @@ -23,9 +23,9 @@ public function it_should_serialize_simple_logical_types(Schema $type, string $e $this->assertEquals($expectedSchema, $type->serialize()); } - #[DataProvider('provideLogicalTypes')] #[Test] - public function it_should_parse_simple_logical_types(Schema $type, string $expectedType, string $expectedLogicalType) + #[DataProvider('provideLogicalTypes')] + public function it_should_parse_simple_logical_types(Schema $type, string $expectedType, string $expectedLogicalType): void { $parsedSchema = $type->parse(); $this->assertEquals($expectedType, $parsedSchema->type()); @@ -33,7 +33,7 @@ public function it_should_parse_simple_logical_types(Schema $type, string $expec } #[Test] - public function it_should_serialize_duration_types() + public function it_should_serialize_duration_types(): void { $schema = Schema::duration() ->name('User') @@ -54,7 +54,7 @@ public function it_should_serialize_duration_types() } #[Test] - public function it_should_parse_duration_types() + public function it_should_parse_duration_types(): void { $parsedSchema = Schema::duration() ->name('User') diff --git a/test/Objects/Schema/MapTypeTest.php b/test/Objects/Schema/MapTypeTest.php index 0ba9669..a24c8c8 100644 --- a/test/Objects/Schema/MapTypeTest.php +++ b/test/Objects/Schema/MapTypeTest.php @@ -4,8 +4,8 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Schema; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class MapTypeTest extends TestCase @@ -37,7 +37,6 @@ public function it_should_parse_map_types(): void ->default(['answer' => 42]) ->parse(); - $this->assertInstanceOf(\AvroSchema::class, $parsedSchema); $this->assertEquals('map', $parsedSchema->type()); } } diff --git a/test/Objects/Schema/PrimitiveTypeTest.php b/test/Objects/Schema/PrimitiveTypeTest.php index 2b2878d..611ba26 100644 --- a/test/Objects/Schema/PrimitiveTypeTest.php +++ b/test/Objects/Schema/PrimitiveTypeTest.php @@ -4,32 +4,28 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema; +use FlixTech\AvroSerializer\Objects\Schema; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; -use FlixTech\AvroSerializer\Objects\Schema; use PHPUnit\Framework\TestCase; class PrimitiveTypeTest extends TestCase { - #[DataProvider('providePrimitiveTypes')] #[Test] + #[DataProvider('providePrimitiveTypes')] public function it_should_serialize_primitive_types(Schema $type, string $expectedName): void { $this->assertEquals($expectedName, $type->serialize()); } - #[DataProvider('providePrimitiveTypes')] #[Test] + #[DataProvider('providePrimitiveTypes')] public function it_should_parse_primitive_types(Schema $type, string $expectedName): void { $parsedSchema = $type->parse(); - $this->assertInstanceOf(\AvroSchema::class, $parsedSchema); $this->assertEquals($expectedName, $parsedSchema->type()); } - /** - * @return array - */ public static function providePrimitiveTypes(): array { return [ diff --git a/test/Objects/Schema/RecordTypeTest.php b/test/Objects/Schema/RecordTypeTest.php index 3d4e146..61fb2f9 100644 --- a/test/Objects/Schema/RecordTypeTest.php +++ b/test/Objects/Schema/RecordTypeTest.php @@ -2,9 +2,9 @@ namespace FlixTech\AvroSerializer\Test\Objects\Schema; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Schema; use FlixTech\AvroSerializer\Objects\Schema\Record\FieldOption; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class RecordTypeTest extends TestCase @@ -66,7 +66,6 @@ public function it_should_parse_record_types(): void ->field('ignore', Schema::boolean(), FieldOption::orderIgnore()) ->parse(); - $this->assertInstanceOf(\AvroSchema::class, $parsedSchema); $this->assertEquals('record', $parsedSchema->type()); } } diff --git a/test/Objects/SchemaResolvers/CallableResolverTest.php b/test/Objects/SchemaResolvers/CallableResolverTest.php index beade06..0a19cc3 100644 --- a/test/Objects/SchemaResolvers/CallableResolverTest.php +++ b/test/Objects/SchemaResolvers/CallableResolverTest.php @@ -4,17 +4,15 @@ namespace FlixTech\AvroSerializer\Test\Objects\SchemaResolvers; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\SchemaResolvers\CallableResolver; use FlixTech\AvroSerializer\Test\AbstractFunctionalTestCase; +use PHPUnit\Framework\Attributes\Test; use function Widmogrod\Functional\constt; class CallableResolverTest extends AbstractFunctionalTestCase { /** - * - * @throws \AvroSchemaParseException * @throws \AvroSchemaParseException */ #[Test] diff --git a/test/Objects/SchemaResolvers/ChainResolverTest.php b/test/Objects/SchemaResolvers/ChainResolverTest.php index f344713..2ade5af 100644 --- a/test/Objects/SchemaResolvers/ChainResolverTest.php +++ b/test/Objects/SchemaResolvers/ChainResolverTest.php @@ -2,36 +2,27 @@ namespace FlixTech\AvroSerializer\Test\Objects\SchemaResolvers; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\SchemaResolverInterface; use FlixTech\AvroSerializer\Objects\SchemaResolvers\ChainResolver; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; class ChainResolverTest extends TestCase { - /** - * @var MockObject|SchemaResolverInterface - */ - private $chainOne; + private SchemaResolverInterface|MockObject $chainOne; - /** - * @var MockObject|SchemaResolverInterface - */ - private $chainTwo; + private SchemaResolverInterface|MockObject $chainTwo; - /** - * @var ChainResolver - */ - private $chain; + private ChainResolver $chain; /** * @throws \ReflectionException */ protected function setUp(): void { - $this->chainOne = $this->getMockForAbstractClass(SchemaResolverInterface::class); - $this->chainTwo = $this->getMockForAbstractClass(SchemaResolverInterface::class); + $this->chainOne = $this->getMockBuilder(SchemaResolverInterface::class)->getMock(); + $this->chainTwo = $this->getMockBuilder(SchemaResolverInterface::class)->getMock(); $this->chain = new ChainResolver($this->chainOne, $this->chainTwo); } diff --git a/test/Objects/SchemaResolvers/DefinitionInterfaceResolverTest.php b/test/Objects/SchemaResolvers/DefinitionInterfaceResolverTest.php index 6658bdd..a28816a 100644 --- a/test/Objects/SchemaResolvers/DefinitionInterfaceResolverTest.php +++ b/test/Objects/SchemaResolvers/DefinitionInterfaceResolverTest.php @@ -2,9 +2,9 @@ namespace FlixTech\AvroSerializer\Test\Objects\SchemaResolvers; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\HasSchemaDefinitionInterface; use FlixTech\AvroSerializer\Objects\SchemaResolvers\DefinitionInterfaceResolver; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; class DefinitionInterfaceResolverTest extends TestCase @@ -12,13 +12,10 @@ class DefinitionInterfaceResolverTest extends TestCase /** * @throws \AvroSchemaParseException */ - #[Test] public function it_should_allow_correct_interfaces(): void { $definitionInterfaceResolver = new DefinitionInterfaceResolver(); - $definitionClass = $this->createAnonymousDefinitionInterface( - '{"type": "string"}' - ); + $definitionClass = $this->createAnonymousDefinitionInterface(); $this->assertEquals( \AvroSchema::parse('{"type": "string"}'), @@ -28,7 +25,6 @@ public function it_should_allow_correct_interfaces(): void $this->assertNull($definitionInterfaceResolver->keySchemaFor($definitionClass)); $definitionClass = $this->createAnonymousDefinitionInterface( - '{"type": "string"}', '{"type": "int"}' ); @@ -43,6 +39,9 @@ public function it_should_allow_correct_interfaces(): void ); } + /** + * @throws \AvroSchemaParseException + */ #[Test] public function it_should_fail_for_records_not_implementing_the_interface_for_value_schema(): void { @@ -52,6 +51,9 @@ public function it_should_fail_for_records_not_implementing_the_interface_for_va $definitionInterfaceResolver->valueSchemaFor([]); } + /** + * @throws \AvroSchemaParseException + */ #[Test] public function it_should_fail_for_records_not_implementing_the_interface_for_key_schema(): void { @@ -61,18 +63,12 @@ public function it_should_fail_for_records_not_implementing_the_interface_for_ke $definitionInterfaceResolver->keySchemaFor([]); } - private function createAnonymousDefinitionInterface(string $valueSchema, string $keySchema = null): HasSchemaDefinitionInterface + private function createAnonymousDefinitionInterface(?string $keySchema = null): HasSchemaDefinitionInterface { - $class = new class() implements HasSchemaDefinitionInterface { - /** - * @var string - */ - public static $valueSchema; + $class = new class implements HasSchemaDefinitionInterface { + public static string $valueSchema; - /** - * @var string|null - */ - public static $keySchema; + public static ?string $keySchema; public static function valueSchemaJson(): string { @@ -85,7 +81,7 @@ public static function keySchemaJson(): ?string } }; - $class::$valueSchema = $valueSchema; + $class::$valueSchema = '{"type": "string"}'; $class::$keySchema = $keySchema; return $class; diff --git a/test/Objects/SchemaResolvers/FileResolverTest.php b/test/Objects/SchemaResolvers/FileResolverTest.php index d561814..e99b839 100644 --- a/test/Objects/SchemaResolvers/FileResolverTest.php +++ b/test/Objects/SchemaResolvers/FileResolverTest.php @@ -4,10 +4,10 @@ namespace FlixTech\AvroSerializer\Test\Objects\SchemaResolvers; -use PHPUnit\Framework\Attributes\Test; -use Widmogrod\Common\ValueOfInterface; use FlixTech\AvroSerializer\Objects\SchemaResolvers\FileResolver; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; +use Widmogrod\Common\ValueOfInterface; use function FlixTech\AvroSerializer\Common\inflectRecord; diff --git a/test/ProtocolTest.php b/test/ProtocolTest.php index 2fbd4c6..0bcc793 100644 --- a/test/ProtocolTest.php +++ b/test/ProtocolTest.php @@ -2,8 +2,8 @@ namespace FlixTech\AvroSerializer\Test; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Exceptions\AvroDecodingException; +use PHPUnit\Framework\Attributes\Test; use Widmogrod\Monad\Either\Left; use Widmogrod\Monad\Either\Right; use Widmogrod\Monad\Maybe\Just; @@ -65,7 +65,7 @@ public function protocol_decoder_should_decode_correctly(): void $unpacked = $decoded->extract(); - $this->assertTrue(\is_array($unpacked)); + $this->assertIsArray($unpacked); $this->assertSame(WIRE_FORMAT_PROTOCOL_VERSION, $unpacked[PROTOCOL_ACCESSOR_VERSION]); $this->assertSame(self::SCHEMA_ID, $unpacked[PROTOCOL_ACCESSOR_SCHEMA_ID]); $this->assertSame(self::AVRO_ENCODED_RECORD_HEX_BIN, \bin2hex($unpacked[PROTOCOL_ACCESSOR_AVRO])); diff --git a/test/SerializeTest.php b/test/SerializeTest.php index 82351ae..bc25aea 100644 --- a/test/SerializeTest.php +++ b/test/SerializeTest.php @@ -2,9 +2,9 @@ namespace FlixTech\AvroSerializer\Test; -use PHPUnit\Framework\Attributes\Test; use FlixTech\AvroSerializer\Objects\Exceptions\AvroDecodingException; use FlixTech\AvroSerializer\Objects\Exceptions\AvroEncodingException; +use PHPUnit\Framework\Attributes\Test; use Widmogrod\Monad\Either\Left; use Widmogrod\Monad\Either\Right; diff --git a/test/bootstrap.php b/test/bootstrap.php index e8f34e0..b20f95b 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -1,6 +1,6 @@ load(); +$dotenv = Dotenv\Dotenv::createUnsafeMutable(paths: __DIR__ . DIRECTORY_SEPARATOR . '..'); +$dotenv->load();