From 3624c2f8efc81ece97203d18291e0930d0a5df25 Mon Sep 17 00:00:00 2001 From: remorhaz Date: Fri, 16 Jun 2023 14:38:43 +0300 Subject: [PATCH 1/8] Dropped PHP 7, arbitrary objects allowed as encode input --- .github/workflows/build.yml | 67 +++++++++++++++++++ .travis.yml | 27 -------- CHANGELOG.md | 6 ++ README.md | 2 +- composer.json | 30 ++++++--- docker-compose.yml | 10 +-- infection.json.dist | 5 +- php-8.0.Dockerfile | 2 +- php-7.4.Dockerfile => php-8.1.Dockerfile | 4 +- php-7.3.Dockerfile => php-8.2.Dockerfile | 6 +- psalm.xml.dist | 22 ++++++ src/Comparator/ComparatorInterface.php | 1 - src/Comparator/ContainsValueComparator.php | 8 ++- src/Comparator/EqualValueComparator.php | 14 ++-- src/Comparator/GreaterValueComparator.php | 18 ++--- src/Event/AfterArrayEvent.php | 9 +-- src/Event/AfterElementEvent.php | 13 ++-- src/Event/AfterObjectEvent.php | 9 +-- src/Event/AfterPropertyEvent.php | 13 ++-- src/Event/BeforeArrayEvent.php | 9 +-- src/Event/BeforeElementEvent.php | 14 ++-- src/Event/BeforeObjectEvent.php | 9 +-- src/Event/BeforePropertyEvent.php | 13 ++-- src/Event/ElementEventInterface.php | 1 - src/Event/EventInterface.php | 1 - .../Exception/InvalidScalarDataException.php | 12 ++-- src/Event/PropertyEventInterface.php | 1 - src/Event/ScalarEvent.php | 25 ++++--- src/Event/ScalarEventInterface.php | 3 +- src/Export/EventDecoder.php | 14 ++-- src/Export/EventExporterInterface.php | 7 +- .../Exception/EncodingFailedException.php | 12 ++-- .../Exception/NoValueToExportException.php | 3 +- .../Exception/UnexpectedValueException.php | 10 ++- .../Exception/UnknownEventException.php | 10 ++- src/Export/ValueDecoder.php | 41 ++++++------ src/Export/ValueEncoder.php | 12 ++-- src/Export/ValueEncoderInterface.php | 1 - src/Export/ValueExporterInterface.php | 3 +- .../Exception/ParentNotFoundException.php | 10 ++- src/Path/Path.php | 22 +++--- src/Path/PathAwareInterface.php | 1 - src/Path/PathInterface.php | 4 +- src/Value/ArrayValueInterface.php | 6 ++ src/Value/DataAwareInterface.php | 3 +- .../Exception/InvalidElementKeyException.php | 16 ++--- .../Exception/InvalidNodeDataException.php | 16 ++--- src/Value/DecodedJson/NodeArrayValue.php | 24 +++---- src/Value/DecodedJson/NodeObjectValue.php | 28 +++----- src/Value/DecodedJson/NodeScalarValue.php | 25 ++++--- src/Value/DecodedJson/NodeValueFactory.php | 34 +++------- .../DecodedJson/NodeValueFactoryInterface.php | 8 +-- .../Exception/JsonNotDecodedException.php | 10 ++- src/Value/EncodedJson/NodeValueFactory.php | 15 ++--- .../EncodedJson/NodeValueFactoryInterface.php | 1 - src/Value/ObjectValueInterface.php | 6 ++ src/Value/ScalarValueInterface.php | 1 + src/Value/StructValueInterface.php | 4 +- src/Walker/EventGenerator.php | 53 ++++++++++----- .../Exception/UnexpectedEntityException.php | 12 ++-- src/Walker/MutationInterface.php | 9 ++- src/Walker/ValueWalker.php | 15 ++++- src/Walker/ValueWalkerInterface.php | 1 - .../ContainsValueComparatorTest.php | 11 ++- tests/Comparator/EqualValueComparatorTest.php | 3 +- .../Comparator/GreaterValueComparatorTest.php | 1 - tests/Event/AfterArrayEventTest.php | 1 - tests/Event/AfterElementEventTest.php | 1 - tests/Event/AfterObjectEventTest.php | 1 - tests/Event/AfterPropertyEventTest.php | 1 - tests/Event/BeforeArrayEventTest.php | 1 - tests/Event/BeforeElementEventTest.php | 1 - tests/Event/BeforeObjectEventTest.php | 1 - tests/Event/BeforePropertyEventTest.php | 1 - .../InvalidScalarDataExceptionTest.php | 1 - tests/Event/ScalarEventTest.php | 10 +-- .../Exception/EncodingFailedExceptionTest.php | 1 - .../NoValueToExportExceptionTest.php | 1 - .../UnexpectedValueExceptionTest.php | 1 - .../Exception/UnknownEventExceptionTest.php | 1 - .../Exception/ParentNotFoundExceptionTest.php | 10 +-- tests/Path/PathTest.php | 37 ++++++---- .../InvalidElementKeyExceptionTest.php | 28 +++++--- .../InvalidNodeDataExceptionTest.php | 12 ++-- .../Value/DecodedJson/NodeArrayValueTest.php | 26 ++++--- .../Value/DecodedJson/NodeObjectValueTest.php | 30 +++++---- .../Value/DecodedJson/NodeScalarValueTest.php | 9 +-- .../DecodedJson/NodeValueFactoryTest.php | 26 +++---- .../Exception/JsonNotDecodedExceptionTest.php | 1 - .../EncodedJson/NodeValueFactoryTest.php | 1 - .../UnexpectedEntityExceptionTest.php | 1 - 91 files changed, 530 insertions(+), 480 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml rename php-7.4.Dockerfile => php-8.1.Dockerfile (87%) rename php-7.3.Dockerfile => php-8.2.Dockerfile (78%) create mode 100644 psalm.xml.dist diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..34962d6 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,67 @@ +name: Build + +on: + pull_request: + branches: + - '*' + push: + branches: + - 'master' + +jobs: + tests: + runs-on: ubuntu-latest + strategy: + matrix: + platform-reqs: + - use-platform-reqs + php-version: + - "8.0" + - "8.1" + - "8.2" + dependencies: + - lowest + - highest + + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + + - name: Install lowest dependencies + if: ${{ matrix.dependencies == 'lowest' && matrix.platform-reqs == 'use-platform-reqs' }} + run: composer update --no-interaction --prefer-lowest + + - name: Install lowest dependencies (ignore platform reqs) + if: ${{ matrix.dependencies == 'lowest' && matrix.platform-reqs == 'ignore-platform-reqs' }} + run: composer update --no-interaction --prefer-lowest --ignore-platform-reqs + + - name: Install highest dependencies + if: ${{ matrix.dependencies == 'highest' && matrix.platform-reqs == 'use-platform-reqs' }} + run: composer update --no-interaction + + - name: Install highest dependencies (ignore platform reqs) + if: ${{ matrix.dependencies == 'highest' && matrix.platform-reqs == 'ignore-platform-reqs' }} + run: composer update --no-interaction --ignore-platform-reqs + + - name: Run tests + run: composer test + + - name: Run infection + run: composer infection + env: + INFECTION_DASHBOARD_API_KEY: ${{ secrets.INFECTION_DASHBOARD_API_KEY }} + + - name: Upload coverage to Codecov.io + run: bash <(curl -s https://codecov.io/bash -s "build/logs") + continue-on-error: true + + - name: Upload coverage to Scrutinizer + uses: sudo-bot/action-scrutinizer@latest + with: + cli-args: --format=php-clover build/logs/clover.xml + continue-on-error: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 47ac2e3..0000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: php - -env: - global: - - XDEBUG=YES - - XDEBUG_MODE=coverage - -matrix: - include: - - php: '7.3' - - php: '7.4' - - php: '8.0' - -install: - - mkdir -p ./build/logs - - composer self-update - - composer install --prefer-source --no-interaction - -script: - - vendor/bin/phpcs -sp --report-junit=build/logs/phpcs.xml - - if [ "$XDEBUG" == "YES" ]; then vendor/bin/phpunit --coverage-clover=build/logs/clover.xml --coverage-xml=build/logs/coverage-xml --log-junit=build/logs/junit.xml; else vendor/bin/phpunit; fi - - if [ "$XDEBUG" == "YES" ]; then vendor/bin/infection --coverage=build/logs --threads=4 --no-progress --skip-initial-tests; fi - -after_success: - - if [ "$XDEBUG" == "YES" ]; then bash <(curl -s https://codecov.io/bash -s "build/logs"); fi - - if [ "$XDEBUG" == "YES" ]; then wget https://scrutinizer-ci.com/ocular.phar; fi - - if [ "$XDEBUG" == "YES" ]; then php ocular.phar code-coverage:upload --access-token=$SCRUTINIZER_TOKEN --format=php-clover build/logs/clover.xml; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index f1e4a84..ea12f16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Changed +- JSON source structure may contain arbitrary objects, not only `stdClass`. +### Removed +- Dropped PHP 7 support. + ## [0.5.3] - 2021-01-14 ### Added - PHP 8.0 support. diff --git a/README.md b/README.md index ad3d9fd..eab63d1 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This library provides infrastructure for JSON documents processing. ## Requirements -- PHP 7.3+ +- PHP 8 - [Internationalization functions](https://www.php.net/manual/en/book.intl.php) (ext-intl) - to compare Unicode strings. - [JSON extension](https://www.php.net/manual/en/book.json.php) (ext-json) - to encode and decode JSON documents. diff --git a/composer.json b/composer.json index 0190d6d..f90ca93 100644 --- a/composer.json +++ b/composer.json @@ -14,14 +14,16 @@ } ], "require": { - "php": "^7.3 | ^8", + "php": "~8.0.0 || ~8.1.0 || ~8.2.0", "ext-json": "*", "ext-intl": "*" }, "require-dev": { - "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "^3.5", - "infection/infection": "^0.18" + "infection/infection": "^0.26 || ^0.27", + "phpunit/phpunit": "^9.5 || ^10", + "psalm/plugin-phpunit": "^0.18.1", + "squizlabs/php_codesniffer": "^3.7.2", + "vimeo/psalm": "^5.12" }, "autoload": { "psr-4": { @@ -30,7 +32,7 @@ }, "autoload-dev": { "psr-4": { - "Remorhaz\\JSON\\Test\\Data\\": "tests/" + "Remorhaz\\JSON\\Data\\Test\\": "tests/" } }, "scripts": { @@ -38,16 +40,26 @@ "vendor/bin/phpcs -sp" ], "test-unit": [ - "vendor/bin/phpunit --coverage-xml=build/log/coverage-xml --log-junit=build/log/junit.xml" + "vendor/bin/phpunit --coverage-xml=build/log/coverage-xml --coverage-clover=build/log/clover.xml --log-junit=build/log/junit.xml" ], + "test-psalm": "vendor/bin/psalm --threads=4 --shepherd", "test": [ - "@test-sp", - "@test-unit" + "@test-cs", + "@test-unit", + "@test-psalm" ], "infection": [ - "@test-unit", "mkdir -p build/log/infection", "vendor/bin/infection --threads=4 --coverage=build/log --no-progress --skip-initial-tests" + ], + "test-infection": [ + "@test-unit", + "@infection" ] + }, + "config": { + "allow-plugins": { + "infection/extension-installer": true + } } } diff --git a/docker-compose.yml b/docker-compose.yml index fe68e84..92abc6e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,21 +4,21 @@ services: php: build: context: . - dockerfile: php-7.3.Dockerfile + dockerfile: php-8.0.Dockerfile volumes: - .:/app working_dir: /app - php7.4: + php8.1: build: context: . - dockerfile: php-7.4.Dockerfile + dockerfile: php-8.1.Dockerfile volumes: - .:/app working_dir: /app - php8.0: + php8.2: build: context: . - dockerfile: php-8.0.Dockerfile + dockerfile: php-8.2.Dockerfile volumes: - .:/app working_dir: /app diff --git a/infection.json.dist b/infection.json.dist index b9398ec..ab00190 100644 --- a/infection.json.dist +++ b/infection.json.dist @@ -9,8 +9,9 @@ "text": "build/logs/infection/infection.log", "summary": "build/logs/infection/summary.log", "perMutator": "build/logs/infection/per-mutator.md", - "badge": { - "branch": "master" + "github": true, + "stryker": { + "badge": "/^master$/" } } } \ No newline at end of file diff --git a/php-8.0.Dockerfile b/php-8.0.Dockerfile index 8dc4ed3..b0ce733 100644 --- a/php-8.0.Dockerfile +++ b/php-8.0.Dockerfile @@ -5,7 +5,7 @@ RUN apt-get update && apt-get install -y \ git \ libicu-dev && \ docker-php-ext-configure intl --enable-intl && \ - docker-php-ext-install intl && \ + docker-php-ext-install intl pcntl && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ diff --git a/php-7.4.Dockerfile b/php-8.1.Dockerfile similarity index 87% rename from php-7.4.Dockerfile rename to php-8.1.Dockerfile index 5d769fa..b0ce733 100644 --- a/php-7.4.Dockerfile +++ b/php-8.1.Dockerfile @@ -1,11 +1,11 @@ -FROM php:7.4-cli +FROM php:8.0-cli RUN apt-get update && apt-get install -y \ zip \ git \ libicu-dev && \ docker-php-ext-configure intl --enable-intl && \ - docker-php-ext-install intl && \ + docker-php-ext-install intl pcntl && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ diff --git a/php-7.3.Dockerfile b/php-8.2.Dockerfile similarity index 78% rename from php-7.3.Dockerfile rename to php-8.2.Dockerfile index d0837cb..b0ce733 100644 --- a/php-7.3.Dockerfile +++ b/php-8.2.Dockerfile @@ -1,13 +1,11 @@ -FROM php:7.3-cli +FROM php:8.0-cli RUN apt-get update && apt-get install -y \ zip \ git \ libicu-dev && \ - pecl install xdebug && \ - docker-php-ext-enable xdebug && \ docker-php-ext-configure intl --enable-intl && \ - docker-php-ext-install intl && \ + docker-php-ext-install intl pcntl && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ diff --git a/psalm.xml.dist b/psalm.xml.dist new file mode 100644 index 0000000..ab09605 --- /dev/null +++ b/psalm.xml.dist @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/src/Comparator/ComparatorInterface.php b/src/Comparator/ComparatorInterface.php index c285afc..5810d64 100644 --- a/src/Comparator/ComparatorInterface.php +++ b/src/Comparator/ComparatorInterface.php @@ -8,6 +8,5 @@ interface ComparatorInterface { - public function compare(ValueInterface $leftValue, ValueInterface $rightValue): bool; } diff --git a/src/Comparator/ContainsValueComparator.php b/src/Comparator/ContainsValueComparator.php index acc5b1a..a54d8f1 100644 --- a/src/Comparator/ContainsValueComparator.php +++ b/src/Comparator/ContainsValueComparator.php @@ -7,14 +7,14 @@ use Collator; use Iterator; use Remorhaz\JSON\Data\Value\ArrayValueInterface; +use Remorhaz\JSON\Data\Value\NodeValueInterface; use Remorhaz\JSON\Data\Value\ObjectValueInterface; use Remorhaz\JSON\Data\Value\ScalarValueInterface; use Remorhaz\JSON\Data\Value\ValueInterface; final class ContainsValueComparator implements ComparatorInterface { - - private $equalComparator; + private EqualValueComparator $equalComparator; public function __construct(Collator $collator) { @@ -58,6 +58,10 @@ private function objectContains(ObjectValueInterface $leftValue, ObjectValueInte return true; } + /** + * @param Iterator $valueIterator + * @return null|array + */ private function getPropertiesWithoutDuplicates(Iterator $valueIterator): ?array { $valuesByProperty = []; diff --git a/src/Comparator/EqualValueComparator.php b/src/Comparator/EqualValueComparator.php index 850fbe6..4115338 100644 --- a/src/Comparator/EqualValueComparator.php +++ b/src/Comparator/EqualValueComparator.php @@ -7,6 +7,7 @@ use Collator; use Iterator; use Remorhaz\JSON\Data\Value\ArrayValueInterface; +use Remorhaz\JSON\Data\Value\NodeValueInterface; use Remorhaz\JSON\Data\Value\ObjectValueInterface; use Remorhaz\JSON\Data\Value\ScalarValueInterface; use Remorhaz\JSON\Data\Value\ValueInterface; @@ -15,12 +16,9 @@ final class EqualValueComparator implements ComparatorInterface { - - private $collator; - - public function __construct(Collator $collator) - { - $this->collator = $collator; + public function __construct( + private Collator $collator, + ) { } public function compare(ValueInterface $leftValue, ValueInterface $rightValue): bool @@ -94,6 +92,10 @@ private function isObjectEqual(ObjectValueInterface $leftValue, ObjectValueInter return empty($leftProperties); } + /** + * @param Iterator $valueIterator + * @return null|array + */ private function getPropertiesWithoutDuplicates(Iterator $valueIterator): ?array { $valuesByProperty = []; diff --git a/src/Comparator/GreaterValueComparator.php b/src/Comparator/GreaterValueComparator.php index e24f50f..20a2910 100644 --- a/src/Comparator/GreaterValueComparator.php +++ b/src/Comparator/GreaterValueComparator.php @@ -14,21 +14,17 @@ final class GreaterValueComparator implements ComparatorInterface { - - private $collator; - - public function __construct(Collator $collator) - { - $this->collator = $collator; + public function __construct( + private Collator $collator, + ) { } public function compare(ValueInterface $leftValue, ValueInterface $rightValue): bool { - if ($leftValue instanceof ScalarValueInterface && $rightValue instanceof ScalarValueInterface) { - return $this->isScalarGreater($leftValue, $rightValue); - } - - return false; + return + $leftValue instanceof ScalarValueInterface && + $rightValue instanceof ScalarValueInterface && + $this->isScalarGreater($leftValue, $rightValue); } private function isScalarGreater(ScalarValueInterface $leftValue, ScalarValueInterface $rightValue): bool diff --git a/src/Event/AfterArrayEvent.php b/src/Event/AfterArrayEvent.php index 37aef89..690ffe1 100644 --- a/src/Event/AfterArrayEvent.php +++ b/src/Event/AfterArrayEvent.php @@ -8,12 +8,9 @@ final class AfterArrayEvent implements AfterArrayEventInterface { - - private $path; - - public function __construct(PathInterface $path) - { - $this->path = $path; + public function __construct( + private PathInterface $path, + ) { } public function getPath(): PathInterface diff --git a/src/Event/AfterElementEvent.php b/src/Event/AfterElementEvent.php index f5e1a7c..062730a 100644 --- a/src/Event/AfterElementEvent.php +++ b/src/Event/AfterElementEvent.php @@ -8,15 +8,10 @@ final class AfterElementEvent implements AfterElementEventInterface { - - private $index; - - private $path; - - public function __construct(int $index, PathInterface $path) - { - $this->index = $index; - $this->path = $path; + public function __construct( + private int $index, + private PathInterface $path, + ) { } public function getPath(): PathInterface diff --git a/src/Event/AfterObjectEvent.php b/src/Event/AfterObjectEvent.php index dba4afa..3fb2794 100644 --- a/src/Event/AfterObjectEvent.php +++ b/src/Event/AfterObjectEvent.php @@ -8,12 +8,9 @@ final class AfterObjectEvent implements AfterObjectEventInterface { - - private $path; - - public function __construct(PathInterface $path) - { - $this->path = $path; + public function __construct( + private PathInterface $path, + ) { } public function getPath(): PathInterface diff --git a/src/Event/AfterPropertyEvent.php b/src/Event/AfterPropertyEvent.php index e5ddb06..c03cc41 100644 --- a/src/Event/AfterPropertyEvent.php +++ b/src/Event/AfterPropertyEvent.php @@ -8,15 +8,10 @@ final class AfterPropertyEvent implements AfterPropertyEventInterface { - - private $name; - - private $path; - - public function __construct(string $name, PathInterface $path) - { - $this->name = $name; - $this->path = $path; + public function __construct( + private string $name, + private PathInterface $path, + ) { } public function getName(): string diff --git a/src/Event/BeforeArrayEvent.php b/src/Event/BeforeArrayEvent.php index 846620e..093caee 100644 --- a/src/Event/BeforeArrayEvent.php +++ b/src/Event/BeforeArrayEvent.php @@ -8,12 +8,9 @@ final class BeforeArrayEvent implements BeforeArrayEventInterface { - - private $path; - - public function __construct(PathInterface $path) - { - $this->path = $path; + public function __construct( + private PathInterface $path, + ) { } public function getPath(): PathInterface diff --git a/src/Event/BeforeElementEvent.php b/src/Event/BeforeElementEvent.php index f7bb7df..b0458af 100644 --- a/src/Event/BeforeElementEvent.php +++ b/src/Event/BeforeElementEvent.php @@ -8,15 +8,10 @@ final class BeforeElementEvent implements BeforeElementEventInterface { - - private $index; - - private $path; - - public function __construct(int $index, PathInterface $path) - { - $this->index = $index; - $this->path = $path; + public function __construct( + private int $index, + private PathInterface $path, + ) { } public function getIndex(): int @@ -24,7 +19,6 @@ public function getIndex(): int return $this->index; } - public function getPath(): PathInterface { return $this->path; diff --git a/src/Event/BeforeObjectEvent.php b/src/Event/BeforeObjectEvent.php index 61b3d2b..af6252e 100644 --- a/src/Event/BeforeObjectEvent.php +++ b/src/Event/BeforeObjectEvent.php @@ -8,12 +8,9 @@ final class BeforeObjectEvent implements BeforeObjectEventInterface { - - private $path; - - public function __construct(PathInterface $path) - { - $this->path = $path; + public function __construct( + private PathInterface $path, + ) { } public function getPath(): PathInterface diff --git a/src/Event/BeforePropertyEvent.php b/src/Event/BeforePropertyEvent.php index c805799..d69e5ad 100644 --- a/src/Event/BeforePropertyEvent.php +++ b/src/Event/BeforePropertyEvent.php @@ -8,15 +8,10 @@ final class BeforePropertyEvent implements BeforePropertyEventInterface { - - private $name; - - private $path; - - public function __construct(string $name, PathInterface $path) - { - $this->name = $name; - $this->path = $path; + public function __construct( + private string $name, + private PathInterface $path, + ) { } public function getName(): string diff --git a/src/Event/ElementEventInterface.php b/src/Event/ElementEventInterface.php index 3dc624d..ef41547 100644 --- a/src/Event/ElementEventInterface.php +++ b/src/Event/ElementEventInterface.php @@ -6,6 +6,5 @@ interface ElementEventInterface extends EventInterface { - public function getIndex(): int; } diff --git a/src/Event/EventInterface.php b/src/Event/EventInterface.php index 05dc43a..a66e9d2 100644 --- a/src/Event/EventInterface.php +++ b/src/Event/EventInterface.php @@ -8,6 +8,5 @@ interface EventInterface { - public function getPath(): PathInterface; } diff --git a/src/Event/Exception/InvalidScalarDataException.php b/src/Event/Exception/InvalidScalarDataException.php index 5dd3474..5b1f939 100644 --- a/src/Event/Exception/InvalidScalarDataException.php +++ b/src/Event/Exception/InvalidScalarDataException.php @@ -10,16 +10,14 @@ final class InvalidScalarDataException extends LogicException implements ExceptionInterface, DataAwareInterface { - - private $data; - - public function __construct($data, Throwable $previous = null) - { - $this->data = $data; + public function __construct( + private mixed $data, + ?Throwable $previous = null, + ) { parent::__construct("Invalid scalar data", 0, $previous); } - public function getData() + public function getData(): mixed { return $this->data; } diff --git a/src/Event/PropertyEventInterface.php b/src/Event/PropertyEventInterface.php index 13be97b..f866f75 100644 --- a/src/Event/PropertyEventInterface.php +++ b/src/Event/PropertyEventInterface.php @@ -6,6 +6,5 @@ interface PropertyEventInterface extends EventInterface { - public function getName(): string; } diff --git a/src/Event/ScalarEvent.php b/src/Event/ScalarEvent.php index f46c7f0..b4ac644 100644 --- a/src/Event/ScalarEvent.php +++ b/src/Event/ScalarEvent.php @@ -6,23 +6,22 @@ use Remorhaz\JSON\Data\Path\PathInterface; +use function is_scalar; + final class ScalarEvent implements ScalarEventInterface { - - private $data; - - private $path; - - public function __construct($data, PathInterface $path) - { - if (null !== $data && !is_scalar($data)) { - throw new Exception\InvalidScalarDataException($data); - } - $this->data = $data; - $this->path = $path; + private int|string|float|bool|null $data; + + public function __construct( + mixed $data, + private PathInterface $path, + ) { + $this->data = null === $data || is_scalar($data) + ? $data + : throw new Exception\InvalidScalarDataException($data); } - public function getData() + public function getData(): int|string|float|bool|null { return $this->data; } diff --git a/src/Event/ScalarEventInterface.php b/src/Event/ScalarEventInterface.php index 5452228..405bd8d 100644 --- a/src/Event/ScalarEventInterface.php +++ b/src/Event/ScalarEventInterface.php @@ -6,6 +6,5 @@ interface ScalarEventInterface extends EventInterface { - - public function getData(); + public function getData(): int|string|float|bool|null; } diff --git a/src/Export/EventDecoder.php b/src/Export/EventDecoder.php index e97ddd1..7f248e1 100644 --- a/src/Export/EventDecoder.php +++ b/src/Export/EventDecoder.php @@ -20,9 +20,8 @@ final class EventDecoder implements EventDecoderInterface { - /** - * @param Iterator|EventInterface[] $events + * @param Iterator $events * @return NodeValueInterface|null */ public function exportEvents(Iterator $events): ?NodeValueInterface @@ -76,13 +75,12 @@ public function exportEvents(Iterator $events): ?NodeValueInterface return (new NodeValueFactory())->createValue($data); } + /** + * @param Iterator $events + * @return NodeValueInterface + */ public function exportExistingEvents(Iterator $events): NodeValueInterface { - $value = $this->exportEvents($events); - if (isset($value)) { - return $value; - } - - throw new Exception\NoValueToExportException(); + return $this->exportEvents($events) ?? throw new Exception\NoValueToExportException(); } } diff --git a/src/Export/EventExporterInterface.php b/src/Export/EventExporterInterface.php index 4f7053b..31b6a91 100644 --- a/src/Export/EventExporterInterface.php +++ b/src/Export/EventExporterInterface.php @@ -10,12 +10,15 @@ interface EventExporterInterface { - /** - * @param Iterator|EventInterface[] $events + * @param Iterator $events * @return NodeValueInterface|null */ public function exportEvents(Iterator $events): ?NodeValueInterface; + /** + * @param Iterator $events + * @return NodeValueInterface + */ public function exportExistingEvents(Iterator $events): NodeValueInterface; } diff --git a/src/Export/Exception/EncodingFailedException.php b/src/Export/Exception/EncodingFailedException.php index 36ed8bf..5b29a70 100644 --- a/src/Export/Exception/EncodingFailedException.php +++ b/src/Export/Exception/EncodingFailedException.php @@ -10,16 +10,14 @@ final class EncodingFailedException extends LogicException implements ExceptionInterface, DataAwareInterface { - - private $data; - - public function __construct($data, Throwable $previous = null) - { - $this->data = $data; + public function __construct( + private mixed $data, + ?Throwable $previous = null, + ) { parent::__construct("Failed to encode data to JSON", 0, $previous); } - public function getData() + public function getData(): mixed { return $this->data; } diff --git a/src/Export/Exception/NoValueToExportException.php b/src/Export/Exception/NoValueToExportException.php index 07281a2..3c6c5dc 100644 --- a/src/Export/Exception/NoValueToExportException.php +++ b/src/Export/Exception/NoValueToExportException.php @@ -9,8 +9,7 @@ final class NoValueToExportException extends LogicException implements ExceptionInterface { - - public function __construct(Throwable $previous = null) + public function __construct(?Throwable $previous = null) { parent::__construct("No value to export", 0, $previous); } diff --git a/src/Export/Exception/UnexpectedValueException.php b/src/Export/Exception/UnexpectedValueException.php index 1cd38b6..9c2c774 100644 --- a/src/Export/Exception/UnexpectedValueException.php +++ b/src/Export/Exception/UnexpectedValueException.php @@ -10,12 +10,10 @@ final class UnexpectedValueException extends DomainException implements ExceptionInterface { - - private $value; - - public function __construct(ValueInterface $value, Throwable $previous = null) - { - $this->value = $value; + public function __construct( + private ValueInterface $value, + ?Throwable $previous = null, + ) { parent::__construct("Unexpected value", 0, $previous); } diff --git a/src/Export/Exception/UnknownEventException.php b/src/Export/Exception/UnknownEventException.php index c99b1ed..68706a4 100644 --- a/src/Export/Exception/UnknownEventException.php +++ b/src/Export/Exception/UnknownEventException.php @@ -10,12 +10,10 @@ final class UnknownEventException extends LogicException implements ExceptionInterface { - - private $event; - - public function __construct(EventInterface $event, Throwable $previous = null) - { - $this->event = $event; + public function __construct( + private EventInterface $event, + ?Throwable $previous = null, + ) { parent::__construct("Unknown event", 0, $previous); } diff --git a/src/Export/ValueDecoder.php b/src/Export/ValueDecoder.php index be200e4..0367d13 100644 --- a/src/Export/ValueDecoder.php +++ b/src/Export/ValueDecoder.php @@ -11,31 +11,34 @@ final class ValueDecoder implements ValueDecoderInterface { - - public function exportValue(ValueInterface $value) + public function exportValue(ValueInterface $value): mixed { - if ($value instanceof ScalarValueInterface) { - return $value->getData(); - } - - if ($value instanceof ArrayValueInterface) { - $result = []; - foreach ($value->createChildIterator() as $index => $element) { - $result[$index] = $this->exportValue($element); - } + return match (true) { + $value instanceof ScalarValueInterface => $value->getData(), + $value instanceof ArrayValueInterface => $this->exportArrayValue($value), + $value instanceof ObjectValueInterface => $this->exportObjectValue($value), + default => throw new Exception\UnexpectedValueException($value), + }; + } - return $result; + private function exportArrayValue(ArrayValueInterface $value): array + { + $result = []; + foreach ($value->createChildIterator() as $index => $element) { + /** @psalm-var mixed */ + $result[$index] = $this->exportValue($element); } - if ($value instanceof ObjectValueInterface) { - $result = (object) []; - foreach ($value->createChildIterator() as $name => $property) { - $result->{$name} = $this->exportValue($property); - } + return $result; + } - return $result; + private function exportObjectValue(ObjectValueInterface $value): object + { + $result = (object) []; + foreach ($value->createChildIterator() as $name => $property) { + $result->{$name} = $this->exportValue($property); } - throw new Exception\UnexpectedValueException($value); + return $result; } } diff --git a/src/Export/ValueEncoder.php b/src/Export/ValueEncoder.php index 1337c5e..0f2fdff 100644 --- a/src/Export/ValueEncoder.php +++ b/src/Export/ValueEncoder.php @@ -18,23 +18,21 @@ */ final class ValueEncoder implements ValueEncoderInterface { - - private $decoder; - - public function __construct(ValueDecoderInterface $decoder) - { - $this->decoder = $decoder; + public function __construct( + private ValueDecoderInterface $decoder, + ) { } public function exportValue(ValueInterface $value): string { + /** @psalm-var mixed $decodedValue */ $decodedValue = $this ->decoder ->exportValue($value); try { return json_encode( $decodedValue, - JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR + JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR, ); } catch (Throwable $e) { throw new Exception\EncodingFailedException($decodedValue, $e); diff --git a/src/Export/ValueEncoderInterface.php b/src/Export/ValueEncoderInterface.php index 965cb1b..c851e79 100644 --- a/src/Export/ValueEncoderInterface.php +++ b/src/Export/ValueEncoderInterface.php @@ -8,6 +8,5 @@ interface ValueEncoderInterface extends ValueExporterInterface { - public function exportValue(ValueInterface $value): string; } diff --git a/src/Export/ValueExporterInterface.php b/src/Export/ValueExporterInterface.php index 719cd75..87175f0 100644 --- a/src/Export/ValueExporterInterface.php +++ b/src/Export/ValueExporterInterface.php @@ -8,6 +8,5 @@ interface ValueExporterInterface { - - public function exportValue(ValueInterface $value); + public function exportValue(ValueInterface $value): mixed; } diff --git a/src/Path/Exception/ParentNotFoundException.php b/src/Path/Exception/ParentNotFoundException.php index 7395ab5..d556439 100644 --- a/src/Path/Exception/ParentNotFoundException.php +++ b/src/Path/Exception/ParentNotFoundException.php @@ -13,12 +13,10 @@ final class ParentNotFoundException extends LogicException implements ExceptionInterface, PathAwareInterface { - - private $path; - - public function __construct(PathInterface $path, Throwable $previous = null) - { - $this->path = $path; + public function __construct( + private PathInterface $path, + ?Throwable $previous = null, + ) { parent::__construct("Parent not found in path {$this->buildPath()}", 0, $previous); } diff --git a/src/Path/Path.php b/src/Path/Path.php index 3416ab4..468121d 100644 --- a/src/Path/Path.php +++ b/src/Path/Path.php @@ -5,16 +5,19 @@ namespace Remorhaz\JSON\Data\Path; use function array_slice; +use function array_values; use function count; final class Path implements PathInterface { + /** + * @var list + */ + private array $elements; - private $elements; - - public function __construct(...$elements) + public function __construct(int|string ...$elements) { - $this->elements = $elements; + $this->elements = array_values($elements); } public function copyWithElement(int $index): PathInterface @@ -29,13 +32,14 @@ public function copyWithProperty(string $name): PathInterface public function copyParent(): PathInterface { - if (empty($this->elements)) { - throw new Exception\ParentNotFoundException($this); - } - - return new self(...array_slice($this->elements, 0, -1)); + return empty($this->elements) + ? throw new Exception\ParentNotFoundException($this) + : new self(...array_slice($this->elements, 0, -1)); } + /** + * @return list + */ public function getElements(): array { return $this->elements; diff --git a/src/Path/PathAwareInterface.php b/src/Path/PathAwareInterface.php index ddb8545..4fbac95 100644 --- a/src/Path/PathAwareInterface.php +++ b/src/Path/PathAwareInterface.php @@ -6,6 +6,5 @@ interface PathAwareInterface { - public function getPath(): PathInterface; } diff --git a/src/Path/PathInterface.php b/src/Path/PathInterface.php index 8da0f6f..f548e1a 100644 --- a/src/Path/PathInterface.php +++ b/src/Path/PathInterface.php @@ -6,13 +6,15 @@ interface PathInterface { - public function copyWithElement(int $index): PathInterface; public function copyWithProperty(string $name): PathInterface; public function copyParent(): PathInterface; + /** + * @return list + */ public function getElements(): array; public function equals(PathInterface $path): bool; diff --git a/src/Value/ArrayValueInterface.php b/src/Value/ArrayValueInterface.php index 44e26bc..288e3c9 100644 --- a/src/Value/ArrayValueInterface.php +++ b/src/Value/ArrayValueInterface.php @@ -4,6 +4,12 @@ namespace Remorhaz\JSON\Data\Value; +use Iterator; + interface ArrayValueInterface extends StructValueInterface { + /** + * @return Iterator + */ + public function createChildIterator(): Iterator; } diff --git a/src/Value/DataAwareInterface.php b/src/Value/DataAwareInterface.php index 28d619c..9906e0c 100644 --- a/src/Value/DataAwareInterface.php +++ b/src/Value/DataAwareInterface.php @@ -6,6 +6,5 @@ interface DataAwareInterface { - - public function getData(); + public function getData(): mixed; } diff --git a/src/Value/DecodedJson/Exception/InvalidElementKeyException.php b/src/Value/DecodedJson/Exception/InvalidElementKeyException.php index 6be1bb6..695e4c2 100644 --- a/src/Value/DecodedJson/Exception/InvalidElementKeyException.php +++ b/src/Value/DecodedJson/Exception/InvalidElementKeyException.php @@ -16,20 +16,16 @@ class InvalidElementKeyException extends RuntimeException implements ExceptionInterface, PathAwareInterface { - - private $key; - - private $path; - /** * @param mixed $key * @param PathInterface $path * @param Throwable|null $previous */ - public function __construct($key, PathInterface $path, Throwable $previous = null) - { - $this->key = $key; - $this->path = $path; + public function __construct( + private mixed $key, + private PathInterface $path, + ?Throwable $previous = null, + ) { parent::__construct($this->buildMessage(), 0, $previous); } @@ -38,7 +34,7 @@ private function buildMessage(): string return "Invalid element key in decoded JSON: {$this->buildKey()} at {$this->buildPath()}"; } - public function getKey() + public function getKey(): mixed { return $this->key; } diff --git a/src/Value/DecodedJson/Exception/InvalidNodeDataException.php b/src/Value/DecodedJson/Exception/InvalidNodeDataException.php index 6701bd4..817685b 100644 --- a/src/Value/DecodedJson/Exception/InvalidNodeDataException.php +++ b/src/Value/DecodedJson/Exception/InvalidNodeDataException.php @@ -16,15 +16,11 @@ class InvalidNodeDataException extends RuntimeException implements PathAwareInterface, DataAwareInterface { - - private $data; - - private $path; - - public function __construct($data, PathInterface $path, Throwable $previous = null) - { - $this->data = $data; - $this->path = $path; + public function __construct( + private mixed $data, + private PathInterface $path, + ?Throwable $previous = null, + ) { parent::__construct($this->buildMessage(), 0, $previous); } @@ -33,7 +29,7 @@ private function buildMessage(): string return "Invalid data in decoded JSON at {$this->buildPath()}"; } - public function getData() + public function getData(): mixed { return $this->data; } diff --git a/src/Value/DecodedJson/NodeArrayValue.php b/src/Value/DecodedJson/NodeArrayValue.php index 9d8fd4b..959edcc 100644 --- a/src/Value/DecodedJson/NodeArrayValue.php +++ b/src/Value/DecodedJson/NodeArrayValue.php @@ -9,30 +9,26 @@ use Remorhaz\JSON\Data\Path\PathInterface; use Remorhaz\JSON\Data\Value\NodeValueInterface; +use function is_int; + final class NodeArrayValue implements NodeValueInterface, ArrayValueInterface { - - private $data; - - private $path; - - private $valueFactory; - public function __construct( - array $data, - PathInterface $path, - NodeValueFactoryInterface $valueFactory + private array $data, + private PathInterface $path, + private NodeValueFactoryInterface $valueFactory ) { - $this->data = $data; - $this->path = $path; - $this->valueFactory = $valueFactory; } + /** + * @return Iterator + */ public function createChildIterator(): Iterator { $validIndex = 0; + /** @psalm-var mixed $element */ foreach ($this->data as $index => $element) { - if ($index !== $validIndex++) { + if (!is_int($index) || $index != $validIndex++) { throw new Exception\InvalidElementKeyException($index, $this->path); } yield $index => $this diff --git a/src/Value/DecodedJson/NodeObjectValue.php b/src/Value/DecodedJson/NodeObjectValue.php index 318b3c5..4a910a1 100644 --- a/src/Value/DecodedJson/NodeObjectValue.php +++ b/src/Value/DecodedJson/NodeObjectValue.php @@ -4,40 +4,28 @@ namespace Remorhaz\JSON\Data\Value\DecodedJson; -use Generator; use Iterator; use Remorhaz\JSON\Data\Value\ObjectValueInterface; use Remorhaz\JSON\Data\Path\PathInterface; use Remorhaz\JSON\Data\Value\NodeValueInterface; -use stdClass; final class NodeObjectValue implements NodeValueInterface, ObjectValueInterface { - - private $data; - - private $path; - - private $valueFactory; - public function __construct( - stdClass $data, - PathInterface $path, - NodeValueFactoryInterface $valueFactory + private object $data, + private PathInterface $path, + private NodeValueFactoryInterface $valueFactory, ) { - $this->data = $data; - $this->path = $path; - $this->valueFactory = $valueFactory; } + /** + * @return Iterator + */ public function createChildIterator(): Iterator { - return $this->createChildGenerator(); - } - - private function createChildGenerator(): Generator - { + /** @psalm-var mixed $property */ foreach (get_object_vars($this->data) as $name => $property) { + /** @psalm-suppress RedundantCast */ $stringName = (string) $name; yield $stringName => $this ->valueFactory diff --git a/src/Value/DecodedJson/NodeScalarValue.php b/src/Value/DecodedJson/NodeScalarValue.php index b106765..e48a795 100644 --- a/src/Value/DecodedJson/NodeScalarValue.php +++ b/src/Value/DecodedJson/NodeScalarValue.php @@ -8,23 +8,22 @@ use Remorhaz\JSON\Data\Value\NodeValueInterface; use Remorhaz\JSON\Data\Value\ScalarValueInterface; +use function is_scalar; + final class NodeScalarValue implements NodeValueInterface, ScalarValueInterface { - - private $data; - - private $path; - - public function __construct($data, PathInterface $path) - { - if (null !== $data && !is_scalar($data)) { - throw new Exception\InvalidNodeDataException($data, $path); - } - $this->data = $data; - $this->path = $path; + private int|float|string|bool|null $data; + + public function __construct( + mixed $data, + private PathInterface $path, + ) { + $this->data = null === $data || is_scalar($data) + ? $data + : throw new Exception\InvalidNodeDataException($data, $path); } - public function getData() + public function getData(): int|float|string|bool|null { return $this->data; } diff --git a/src/Value/DecodedJson/NodeValueFactory.php b/src/Value/DecodedJson/NodeValueFactory.php index 5853b50..33f7c15 100644 --- a/src/Value/DecodedJson/NodeValueFactory.php +++ b/src/Value/DecodedJson/NodeValueFactory.php @@ -7,14 +7,13 @@ use Remorhaz\JSON\Data\Path\Path; use Remorhaz\JSON\Data\Value\NodeValueInterface; use Remorhaz\JSON\Data\Path\PathInterface; -use stdClass; use function is_array; +use function is_object; use function is_scalar; final class NodeValueFactory implements NodeValueFactoryInterface { - public static function create(): NodeValueFactoryInterface { return new self(); @@ -22,28 +21,17 @@ public static function create(): NodeValueFactoryInterface /** * {@inheritDoc} - * - * @param array|bool|float|int|stdClass|string|null $data - * @param PathInterface|null $path - * @return NodeValueInterface */ - public function createValue($data, ?PathInterface $path = null): NodeValueInterface + public function createValue(mixed $data, ?PathInterface $path = null): NodeValueInterface { - if (!isset($path)) { - $path = new Path(); - } - if (null === $data || is_scalar($data)) { - return new NodeScalarValue($data, $path); - } - - if (is_array($data)) { - return new NodeArrayValue($data, $path, $this); - } - - if ($data instanceof stdClass) { - return new NodeObjectValue($data, $path, $this); - } - - throw new Exception\InvalidNodeDataException($data, $path); + $path ??= new Path(); + + return match (true) { + null === $data, + is_scalar($data) => new NodeScalarValue($data, $path), + is_array($data) => new NodeArrayValue($data, $path, $this), + is_object($data) => new NodeObjectValue($data, $path, $this), + default => throw new Exception\InvalidNodeDataException($data, $path), + }; } } diff --git a/src/Value/DecodedJson/NodeValueFactoryInterface.php b/src/Value/DecodedJson/NodeValueFactoryInterface.php index 8b6af20..cc83459 100644 --- a/src/Value/DecodedJson/NodeValueFactoryInterface.php +++ b/src/Value/DecodedJson/NodeValueFactoryInterface.php @@ -6,17 +6,11 @@ use Remorhaz\JSON\Data\Value\NodeValueInterface; use Remorhaz\JSON\Data\Path\PathInterface; -use stdClass; interface NodeValueFactoryInterface { - /** * Converts decoded JSON to JSON node value. - * - * @param array|bool|float|int|stdClass|string|null $data - * @param PathInterface|null $path - * @return NodeValueInterface */ - public function createValue($data, ?PathInterface $path = null): NodeValueInterface; + public function createValue(mixed $data, ?PathInterface $path = null): NodeValueInterface; } diff --git a/src/Value/EncodedJson/Exception/JsonNotDecodedException.php b/src/Value/EncodedJson/Exception/JsonNotDecodedException.php index 0cf8fe1..12867cd 100644 --- a/src/Value/EncodedJson/Exception/JsonNotDecodedException.php +++ b/src/Value/EncodedJson/Exception/JsonNotDecodedException.php @@ -9,12 +9,10 @@ final class JsonNotDecodedException extends RuntimeException implements ExceptionInterface { - - private $json; - - public function __construct(string $json, Throwable $previous = null) - { - $this->json = $json; + public function __construct( + private string $json, + ?Throwable $previous = null, + ) { parent::__construct("Failed to decode JSON", 0, $previous); } diff --git a/src/Value/EncodedJson/NodeValueFactory.php b/src/Value/EncodedJson/NodeValueFactory.php index aca7845..d94119c 100644 --- a/src/Value/EncodedJson/NodeValueFactory.php +++ b/src/Value/EncodedJson/NodeValueFactory.php @@ -5,8 +5,7 @@ namespace Remorhaz\JSON\Data\Value\EncodedJson; use Remorhaz\JSON\Data\Path\PathInterface; -use Remorhaz\JSON\Data\Value\DecodedJson\NodeValueFactory as DecodedJsonNodeValueFactory; -use Remorhaz\JSON\Data\Value\DecodedJson\NodeValueFactoryInterface as DecodedJsonNodeValueFactoryInterface; +use Remorhaz\JSON\Data\Value\DecodedJson; use Remorhaz\JSON\Data\Value\NodeValueInterface; use Throwable; @@ -16,22 +15,20 @@ final class NodeValueFactory implements NodeValueFactoryInterface { - - private $decodedJsonNodeValueFactory; - public static function create(): NodeValueFactoryInterface { - return new self(DecodedJsonNodeValueFactory::create()); + return new self(DecodedJson\NodeValueFactory::create()); } - public function __construct(DecodedJsonNodeValueFactoryInterface $decodedJsonNodeValueFactory) - { - $this->decodedJsonNodeValueFactory = $decodedJsonNodeValueFactory; + public function __construct( + private DecodedJson\NodeValueFactoryInterface $decodedJsonNodeValueFactory, + ) { } public function createValue(string $json, ?PathInterface $path = null): NodeValueInterface { try { + /** @psalm-var mixed $decodedData */ $decodedData = json_decode($json, false, 512, JSON_THROW_ON_ERROR); } catch (Throwable $e) { throw new Exception\JsonNotDecodedException($json, $e); diff --git a/src/Value/EncodedJson/NodeValueFactoryInterface.php b/src/Value/EncodedJson/NodeValueFactoryInterface.php index fe5713a..7fa0097 100644 --- a/src/Value/EncodedJson/NodeValueFactoryInterface.php +++ b/src/Value/EncodedJson/NodeValueFactoryInterface.php @@ -9,6 +9,5 @@ interface NodeValueFactoryInterface { - public function createValue(string $json, ?PathInterface $path = null): NodeValueInterface; } diff --git a/src/Value/ObjectValueInterface.php b/src/Value/ObjectValueInterface.php index 20d62c1..b637ae4 100644 --- a/src/Value/ObjectValueInterface.php +++ b/src/Value/ObjectValueInterface.php @@ -4,6 +4,12 @@ namespace Remorhaz\JSON\Data\Value; +use Iterator; + interface ObjectValueInterface extends StructValueInterface { + /** + * @return Iterator + */ + public function createChildIterator(): Iterator; } diff --git a/src/Value/ScalarValueInterface.php b/src/Value/ScalarValueInterface.php index 8abcef1..95e0e57 100644 --- a/src/Value/ScalarValueInterface.php +++ b/src/Value/ScalarValueInterface.php @@ -6,4 +6,5 @@ interface ScalarValueInterface extends ValueInterface, DataAwareInterface { + public function getData(): int|float|string|bool|null; } diff --git a/src/Value/StructValueInterface.php b/src/Value/StructValueInterface.php index 4a82bec..d51d686 100644 --- a/src/Value/StructValueInterface.php +++ b/src/Value/StructValueInterface.php @@ -8,6 +8,8 @@ interface StructValueInterface extends ValueInterface { - + /** + * @return Iterator + */ public function createChildIterator(): Iterator; } diff --git a/src/Walker/EventGenerator.php b/src/Walker/EventGenerator.php index 2b65efe..837c670 100644 --- a/src/Walker/EventGenerator.php +++ b/src/Walker/EventGenerator.php @@ -5,6 +5,7 @@ namespace Remorhaz\JSON\Data\Walker; use Generator; +use Iterator; use Remorhaz\JSON\Data\Event\AfterArrayEvent; use Remorhaz\JSON\Data\Event\AfterElementEvent; use Remorhaz\JSON\Data\Event\AfterElementEventInterface; @@ -27,18 +28,22 @@ final class EventGenerator { - - private $stack; - - private $path; - - public function __construct(NodeValueInterface $value, PathInterface $path) - { + /** + * @var list + */ + private array $stack; + + public function __construct( + NodeValueInterface $value, + private PathInterface $path, + ) { $this->stack = [$value]; - $this->path = $path; } - public function __invoke(): Generator + /** + * @return Iterator + */ + public function __invoke(): Iterator { while (true) { if (empty($this->stack)) { @@ -68,7 +73,11 @@ public function __invoke(): Generator } } - private function onEvent(EventInterface $event): Generator + /** + * @param EventInterface $event + * @return Iterator + */ + private function onEvent(EventInterface $event): Iterator { switch (true) { case $event instanceof BeforeElementEventInterface: @@ -93,12 +102,20 @@ private function onEvent(EventInterface $event): Generator yield $event; } - private function onScalarValue(ScalarValueInterface $value): Generator + /** + * @param ScalarValueInterface $value + * @return Iterator + */ + private function onScalarValue(ScalarValueInterface $value): Iterator { yield new ScalarEvent($value->getData(), $this->path); } - private function onArrayValue(ArrayValueInterface $value): Generator + /** + * @param ArrayValueInterface $value + * @return Iterator + */ + private function onArrayValue(ArrayValueInterface $value): Iterator { $localStack = []; foreach ($value->createChildIterator() as $index => $child) { @@ -115,12 +132,16 @@ private function onArrayValue(ArrayValueInterface $value): Generator array_push( $this->stack, new AfterArrayEvent($this->path), - ...array_reverse($localStack) + ...array_reverse($localStack), ); yield new BeforeArrayEvent($this->path); } - private function onObjectValue(ObjectValueInterface $value): Generator + /** + * @param ObjectValueInterface $value + * @return Iterator + */ + private function onObjectValue(ObjectValueInterface $value): Iterator { $localStack = []; foreach ($value->createChildIterator() as $name => $child) { @@ -131,13 +152,13 @@ private function onObjectValue(ObjectValueInterface $value): Generator $localStack, new BeforePropertyEvent($name, $elementPath), $child, - new AfterPropertyEvent($name, $elementPath) + new AfterPropertyEvent($name, $elementPath), ); } array_push( $this->stack, new AfterObjectEvent($this->path), - ...array_reverse($localStack) + ...array_reverse($localStack), ); yield new BeforeObjectEvent($this->path); } diff --git a/src/Walker/Exception/UnexpectedEntityException.php b/src/Walker/Exception/UnexpectedEntityException.php index 30da8ab..4b8deb1 100644 --- a/src/Walker/Exception/UnexpectedEntityException.php +++ b/src/Walker/Exception/UnexpectedEntityException.php @@ -9,16 +9,14 @@ final class UnexpectedEntityException extends LogicException implements ExceptionInterface { - - private $entity; - - public function __construct($entity, Throwable $previous = null) - { - $this->entity = $entity; + public function __construct( + private mixed $entity, + ?Throwable $previous = null, + ) { parent::__construct("Invalid entity", 0, $previous); } - public function getEntity() + public function getEntity(): mixed { return $this->entity; } diff --git a/src/Walker/MutationInterface.php b/src/Walker/MutationInterface.php index c88fd6e..c8d3e36 100644 --- a/src/Walker/MutationInterface.php +++ b/src/Walker/MutationInterface.php @@ -4,12 +4,17 @@ namespace Remorhaz\JSON\Data\Walker; +use Iterator; use Remorhaz\JSON\Data\Event\EventInterface; interface MutationInterface { - - public function __invoke(EventInterface $event, ValueWalkerInterface $valueWalker); + /** + * @param EventInterface $event + * @param ValueWalkerInterface $valueWalker + * @return Iterator + */ + public function __invoke(EventInterface $event, ValueWalkerInterface $valueWalker): Iterator; public function reset(): void; } diff --git a/src/Walker/ValueWalker.php b/src/Walker/ValueWalker.php index b0f0e9e..4923a49 100644 --- a/src/Walker/ValueWalker.php +++ b/src/Walker/ValueWalker.php @@ -5,21 +5,32 @@ namespace Remorhaz\JSON\Data\Walker; use Iterator; +use Remorhaz\JSON\Data\Event\EventInterface; use Remorhaz\JSON\Data\Path\PathInterface; use Remorhaz\JSON\Data\Value\NodeValueInterface; final class ValueWalker implements ValueWalkerInterface { - + /** + * @param NodeValueInterface $value + * @param PathInterface $path + * @return Iterator + */ public function createEventIterator(NodeValueInterface $value, PathInterface $path): Iterator { return (new EventGenerator($value, $path))(); } + /** + * @param NodeValueInterface $value + * @param PathInterface $path + * @param MutationInterface $modifier + * @return Iterator + */ public function createMutableEventIterator( NodeValueInterface $value, PathInterface $path, - MutationInterface $modifier + MutationInterface $modifier, ): Iterator { $modifier->reset(); foreach ($this->createEventIterator($value, $path) as $event) { diff --git a/src/Walker/ValueWalkerInterface.php b/src/Walker/ValueWalkerInterface.php index 6bbb28c..f9e4af7 100644 --- a/src/Walker/ValueWalkerInterface.php +++ b/src/Walker/ValueWalkerInterface.php @@ -10,7 +10,6 @@ interface ValueWalkerInterface { - public function createEventIterator(NodeValueInterface $value, PathInterface $path): Iterator; public function createMutableEventIterator( diff --git a/tests/Comparator/ContainsValueComparatorTest.php b/tests/Comparator/ContainsValueComparatorTest.php index f8bd7c4..6f1553f 100644 --- a/tests/Comparator/ContainsValueComparatorTest.php +++ b/tests/Comparator/ContainsValueComparatorTest.php @@ -18,7 +18,6 @@ */ class ContainsValueComparatorTest extends TestCase { - /** * @param string $data * @param string $containedData @@ -35,7 +34,10 @@ public function testCompare_MatchingValues_ReturnsTrue(string $data, string $con self::assertTrue($actualValue); } - public function providerMatchingValues(): array + /** + * @return iterable + */ + public static function providerMatchingValues(): iterable { return [ 'Same string' => ['"a"', '"a"'], @@ -72,7 +74,10 @@ public function testCompare_NonMatchingValues_ReturnsFalse(string $data, string self::assertFalse($actualValue); } - public function providerNonMatchingValues(): array + /** + * @return iterable + */ + public static function providerNonMatchingValues(): iterable { return [ 'Array and scalar' => ['["a"]', '"a"'], diff --git a/tests/Comparator/EqualValueComparatorTest.php b/tests/Comparator/EqualValueComparatorTest.php index 3daa7bf..a3d0b09 100644 --- a/tests/Comparator/EqualValueComparatorTest.php +++ b/tests/Comparator/EqualValueComparatorTest.php @@ -18,7 +18,6 @@ */ class EqualValueComparatorTest extends TestCase { - /** * @param string $data * @param string $equalData @@ -35,7 +34,7 @@ public function testCompare_MatchingValues_ReturnsTrue(string $data, string $equ self::assertTrue($actualValue); } - public function providerMatchingValues(): array + public static function providerMatchingValues(): iterable { return [ 'Same string' => ['"a"', '"a"'], diff --git a/tests/Comparator/GreaterValueComparatorTest.php b/tests/Comparator/GreaterValueComparatorTest.php index 9f1e2ba..34cb5bb 100644 --- a/tests/Comparator/GreaterValueComparatorTest.php +++ b/tests/Comparator/GreaterValueComparatorTest.php @@ -14,7 +14,6 @@ */ class GreaterValueComparatorTest extends TestCase { - /** * @param string $leftData * @param string $rightData diff --git a/tests/Event/AfterArrayEventTest.php b/tests/Event/AfterArrayEventTest.php index 987d23e..5a99ccb 100644 --- a/tests/Event/AfterArrayEventTest.php +++ b/tests/Event/AfterArrayEventTest.php @@ -13,7 +13,6 @@ */ class AfterArrayEventTest extends TestCase { - public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void { $path = new Path(); diff --git a/tests/Event/AfterElementEventTest.php b/tests/Event/AfterElementEventTest.php index 49d9a29..39eefc9 100644 --- a/tests/Event/AfterElementEventTest.php +++ b/tests/Event/AfterElementEventTest.php @@ -13,7 +13,6 @@ */ class AfterElementEventTest extends TestCase { - public function testGetIndex_ConstructedWithIndex_ReturnsSameIndex(): void { $event = new AfterElementEvent(1, new Path()); diff --git a/tests/Event/AfterObjectEventTest.php b/tests/Event/AfterObjectEventTest.php index 08e25b2..fbac171 100644 --- a/tests/Event/AfterObjectEventTest.php +++ b/tests/Event/AfterObjectEventTest.php @@ -13,7 +13,6 @@ */ class AfterObjectEventTest extends TestCase { - public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void { $path = new Path(); diff --git a/tests/Event/AfterPropertyEventTest.php b/tests/Event/AfterPropertyEventTest.php index 102f8f7..383e78b 100644 --- a/tests/Event/AfterPropertyEventTest.php +++ b/tests/Event/AfterPropertyEventTest.php @@ -13,7 +13,6 @@ */ class AfterPropertyEventTest extends TestCase { - public function testGetName_ConstructedWithName_ReturnsSameIndex(): void { $event = new AfterPropertyEvent('a', new Path()); diff --git a/tests/Event/BeforeArrayEventTest.php b/tests/Event/BeforeArrayEventTest.php index 32cce57..37973ab 100644 --- a/tests/Event/BeforeArrayEventTest.php +++ b/tests/Event/BeforeArrayEventTest.php @@ -13,7 +13,6 @@ */ class BeforeArrayEventTest extends TestCase { - public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void { $path = new Path(); diff --git a/tests/Event/BeforeElementEventTest.php b/tests/Event/BeforeElementEventTest.php index 7ed6b55..df74982 100644 --- a/tests/Event/BeforeElementEventTest.php +++ b/tests/Event/BeforeElementEventTest.php @@ -13,7 +13,6 @@ */ class BeforeElementEventTest extends TestCase { - public function testGetIndex_ConstructedWithIndex_ReturnsSameIndex(): void { $event = new BeforeElementEvent(1, new Path()); diff --git a/tests/Event/BeforeObjectEventTest.php b/tests/Event/BeforeObjectEventTest.php index 451f3f9..7b4a86b 100644 --- a/tests/Event/BeforeObjectEventTest.php +++ b/tests/Event/BeforeObjectEventTest.php @@ -13,7 +13,6 @@ */ class BeforeObjectEventTest extends TestCase { - public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void { $path = new Path(); diff --git a/tests/Event/BeforePropertyEventTest.php b/tests/Event/BeforePropertyEventTest.php index 48ef459..60b07af 100644 --- a/tests/Event/BeforePropertyEventTest.php +++ b/tests/Event/BeforePropertyEventTest.php @@ -13,7 +13,6 @@ */ class BeforePropertyEventTest extends TestCase { - public function testGetName_ConstructedWithName_ReturnsSameIndex(): void { $event = new BeforePropertyEvent('a', new Path()); diff --git a/tests/Event/Exception/InvalidScalarDataExceptionTest.php b/tests/Event/Exception/InvalidScalarDataExceptionTest.php index ff50a5d..96317b9 100644 --- a/tests/Event/Exception/InvalidScalarDataExceptionTest.php +++ b/tests/Event/Exception/InvalidScalarDataExceptionTest.php @@ -13,7 +13,6 @@ */ class InvalidScalarDataExceptionTest extends TestCase { - public function testGetMessage_Constructed_ReturnsMatchingValue(): void { $exception = new InvalidScalarDataException(null); diff --git a/tests/Event/ScalarEventTest.php b/tests/Event/ScalarEventTest.php index 5c32bed..18c0129 100644 --- a/tests/Event/ScalarEventTest.php +++ b/tests/Event/ScalarEventTest.php @@ -14,7 +14,6 @@ */ class ScalarEventTest extends TestCase { - public function testConstruct_NonScalarData_ThrowsException(): void { $this->expectException(InvalidScalarDataException::class); @@ -22,17 +21,18 @@ public function testConstruct_NonScalarData_ThrowsException(): void } /** - * @param $data - * @param $expectedValue * @dataProvider providerGetData */ - public function testGetData_ConstructedWithScalarData_ReturnsSameValue($data, $expectedValue): void + public function testGetData_ConstructedWithScalarData_ReturnsSameValue(mixed $data, mixed $expectedValue): void { $event = new ScalarEvent($data, new Path()); self::assertSame($expectedValue, $event->getData()); } - public function providerGetData(): array + /** + * @return iterable + */ + public static function providerGetData(): iterable { return [ 'Null' => [null, null], diff --git a/tests/Export/Exception/EncodingFailedExceptionTest.php b/tests/Export/Exception/EncodingFailedExceptionTest.php index f4c74bf..908babb 100644 --- a/tests/Export/Exception/EncodingFailedExceptionTest.php +++ b/tests/Export/Exception/EncodingFailedExceptionTest.php @@ -13,7 +13,6 @@ */ class EncodingFailedExceptionTest extends TestCase { - public function testGetMessage_Constructed_ReturnsMatchingValue(): void { $exception = new EncodingFailedException('a'); diff --git a/tests/Export/Exception/NoValueToExportExceptionTest.php b/tests/Export/Exception/NoValueToExportExceptionTest.php index 4f595b5..068afe7 100644 --- a/tests/Export/Exception/NoValueToExportExceptionTest.php +++ b/tests/Export/Exception/NoValueToExportExceptionTest.php @@ -13,7 +13,6 @@ */ class NoValueToExportExceptionTest extends TestCase { - public function testGetMessage_Constructed_ReturnsMatchingValue(): void { $exception = new NoValueToExportException(); diff --git a/tests/Export/Exception/UnexpectedValueExceptionTest.php b/tests/Export/Exception/UnexpectedValueExceptionTest.php index da3ecdd..b9be11f 100644 --- a/tests/Export/Exception/UnexpectedValueExceptionTest.php +++ b/tests/Export/Exception/UnexpectedValueExceptionTest.php @@ -14,7 +14,6 @@ */ class UnexpectedValueExceptionTest extends TestCase { - public function testGetMessage_Constructed_ReturnsMatchingValue(): void { $exception = new UnexpectedValueException($this->createMock(ValueInterface::class)); diff --git a/tests/Export/Exception/UnknownEventExceptionTest.php b/tests/Export/Exception/UnknownEventExceptionTest.php index cb29689..9fe43bb 100644 --- a/tests/Export/Exception/UnknownEventExceptionTest.php +++ b/tests/Export/Exception/UnknownEventExceptionTest.php @@ -14,7 +14,6 @@ */ class UnknownEventExceptionTest extends TestCase { - public function testGetMessage_Constructed_ReturnsMatchingValue(): void { $exception = new UnknownEventException($this->createMock(EventInterface::class)); diff --git a/tests/Path/Exception/ParentNotFoundExceptionTest.php b/tests/Path/Exception/ParentNotFoundExceptionTest.php index 2fac766..3a400bc 100644 --- a/tests/Path/Exception/ParentNotFoundExceptionTest.php +++ b/tests/Path/Exception/ParentNotFoundExceptionTest.php @@ -14,7 +14,6 @@ */ class ParentNotFoundExceptionTest extends TestCase { - public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void { $path = new Path(); @@ -23,8 +22,8 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void } /** - * @param array $pathElements - * @param string $expectedValue + * @param list $pathElements + * @param string $expectedValue * @dataProvider providerGetMessage */ public function testGetMessage(array $pathElements, string $expectedValue): void @@ -34,7 +33,10 @@ public function testGetMessage(array $pathElements, string $expectedValue): void self::assertSame($expectedValue, $exception->getMessage()); } - public function providerGetMessage(): array + /** + * @return iterable, string}> + */ + public static function providerGetMessage(): iterable { return [ 'Empty path' => [[], "Parent not found in path /"], diff --git a/tests/Path/PathTest.php b/tests/Path/PathTest.php index 6a59d0e..c36e232 100644 --- a/tests/Path/PathTest.php +++ b/tests/Path/PathTest.php @@ -13,7 +13,6 @@ */ class PathTest extends TestCase { - public function testGetElements_ConstructedWithGivenElements_ReturnsSameValues(): void { $path = new Path('a', 1); @@ -45,8 +44,8 @@ public function testCopyWithProperty_Constructed_ResultContainsMatchingElements( } /** - * @param array $firstElements - * @param array $secondElements + * @param list $firstElements + * @param list $secondElements * @dataProvider providerEquals */ public function testEquals_EqualPath_ReturnsTrue(array $firstElements, array $secondElements): void @@ -57,7 +56,10 @@ public function testEquals_EqualPath_ReturnsTrue(array $firstElements, array $se self::assertTrue($firstPath->equals($secondPath)); } - public function providerEquals(): array + /** + * @return iterable, list}> + */ + public static function providerEquals(): iterable { return [ 'Empty paths' => [[], []], @@ -66,8 +68,8 @@ public function providerEquals(): array } /** - * @param array $firstElements - * @param array $secondElements + * @param list $firstElements + * @param list $secondElements * @dataProvider providerNotEquals */ public function testEquals_NotEqualPath_ReturnsFalse(array $firstElements, array $secondElements): void @@ -78,7 +80,10 @@ public function testEquals_NotEqualPath_ReturnsFalse(array $firstElements, array self::assertFalse($firstPath->equals($secondPath)); } - public function providerNotEquals(): array + /** + * @return iterable, list}> + */ + public static function providerNotEquals(): iterable { return [ 'Nested paths' => [['a', 1], ['a']], @@ -87,8 +92,8 @@ public function providerNotEquals(): array } /** - * @param array $pathElements - * @param array $containedPathElements + * @param list $pathElements + * @param list $containedPathElements * @dataProvider providerContains */ public function testContains_ContainedPath_ReturnsTrue(array $pathElements, array $containedPathElements): void @@ -98,7 +103,10 @@ public function testContains_ContainedPath_ReturnsTrue(array $pathElements, arra self::assertTrue($path->contains($containedPath)); } - public function providerContains(): array + /** + * @return iterable, list}> + */ + public static function providerContains(): iterable { return [ 'Same path' => [['a', 1], ['a', 1]], @@ -115,8 +123,8 @@ public function testCopyParent_NonEmptyPath_ReturnsNewInstance(): void /** * @dataProvider providerCopyExistingParent - * @param array $pathElements - * @param array $expectedElements + * @param list $pathElements + * @param list $expectedElements */ public function testCopyParent_NonEmptyPath_ReturnsMatchingPath(array $pathElements, array $expectedElements): void { @@ -125,7 +133,10 @@ public function testCopyParent_NonEmptyPath_ReturnsMatchingPath(array $pathEleme self::assertSame($expectedElements, $pathCopy->getElements()); } - public function providerCopyExistingParent(): array + /** + * @return iterable, list}> + */ + public static function providerCopyExistingParent(): iterable { return [ 'Single element path' => [['a'], []], diff --git a/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php b/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php index 0ffd3cf..4b6c455 100644 --- a/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php +++ b/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php @@ -14,20 +14,25 @@ */ class InvalidElementKeyExceptionTest extends TestCase { - /** - * @param $key - * @param array $pathElements - * @param $expectedValue + * @param mixed $key + * @param list $pathElements + * @param string $expectedValue * @dataProvider providerKeyMessage */ - public function testGetMessage_Constructed_ReturnsMatchingValue($key, array $pathElements, $expectedValue): void - { + public function testGetMessage_Constructed_ReturnsMatchingValue( + mixed $key, + array $pathElements, + string $expectedValue, + ): void { $exception = new InvalidElementKeyException($key, new Path(...$pathElements)); self::assertSame($expectedValue, $exception->getMessage()); } - public function providerKeyMessage(): array + /** + * @return iterable, string}> + */ + public static function providerKeyMessage(): iterable { /** @noinspection HtmlUnknownTag */ return [ @@ -45,17 +50,18 @@ public function testGetPath_ConstructedWithGivenPath_ReturnsSameInstance(): void } /** - * @param $key - * @param $expectedValue * @dataProvider providerKey */ - public function testGetKey_ConstructedWithGivenKey_ReturnsSameValue($key, $expectedValue): void + public function testGetKey_ConstructedWithGivenKey_ReturnsSameValue(mixed $key, mixed $expectedValue): void { $exception = new InvalidElementKeyException($key, new Path()); self::assertSame($expectedValue, $exception->getKey()); } - public function providerKey(): array + /** + * @return iterable + */ + public static function providerKey(): iterable { return [ 'Integer' => [1, 1], diff --git a/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php b/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php index a64e475..ca3282f 100644 --- a/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php +++ b/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php @@ -14,19 +14,21 @@ */ class InvalidNodeDataExceptionTest extends TestCase { - /** - * @param array $elements - * @param $expectedValue + * @param list $elements + * @param string $expectedValue * @dataProvider providerGetMessage */ - public function testGetMessage_Constructed_ReturnsMatchingValue(array $elements, $expectedValue): void + public function testGetMessage_Constructed_ReturnsMatchingValue(array $elements, string $expectedValue): void { $exception = new InvalidNodeDataException(null, new Path(...$elements)); self::assertSame($expectedValue, $exception->getMessage()); } - public function providerGetMessage(): array + /** + * @return iterable, string}> + */ + public static function providerGetMessage(): iterable { return [ 'Empty path' => [[], 'Invalid data in decoded JSON at /'], diff --git a/tests/Value/DecodedJson/NodeArrayValueTest.php b/tests/Value/DecodedJson/NodeArrayValueTest.php index 3c1e1ba..228c4a0 100644 --- a/tests/Value/DecodedJson/NodeArrayValueTest.php +++ b/tests/Value/DecodedJson/NodeArrayValueTest.php @@ -21,9 +21,7 @@ */ class NodeArrayValueTest extends TestCase { - /** - * @param array $data * @dataProvider providerArrayWithInvalidIndex */ public function testCreateChildIterator_ArrayDataWithInvalidIndex_ThrowsException(array $data): void @@ -34,7 +32,10 @@ public function testCreateChildIterator_ArrayDataWithInvalidIndex_ThrowsExceptio iterator_to_array($value->createChildIterator(), true); } - public function providerArrayWithInvalidIndex(): array + /** + * @return iterable + */ + public static function providerArrayWithInvalidIndex(): iterable { return [ 'Non-zero first index' => [[1 => 'a']], @@ -54,17 +55,26 @@ public function testCreateChildIterator_NotEmptyArrayData_CallsFactoryForEachEle $nodeValueFactory = $this->createMock(NodeValueFactoryInterface::class); $value = new NodeArrayValue(['a', 1], new Path('b'), $nodeValueFactory); + $interceptedArguments = []; $nodeValueFactory - ->expects(self::exactly(2)) ->method('createValue') - ->withConsecutive( - [self::identicalTo('a'), $this->isArgEqualPath('b', 0)], - [self::identicalTo(1), $this->isArgEqualPath('b', 1)], + ->willReturnCallback( + function (mixed $data, ?PathInterface $path) use (&$interceptedArguments): NodeValueInterface { + /** @psalm-var array $interceptedArguments */ + $interceptedArguments[] = [$data, $path?->getElements() ?? []]; + + return $this->createStub(NodeValueInterface::class); + } ); iterator_to_array($value->createChildIterator(), true); + $expectedValue = [ + ['a', ['b', 0]], + [1, ['b', 1]], + ]; + self::assertSame($expectedValue, $interceptedArguments); } - private function isArgEqualPath(...$elements): Callback + private function isArgEqualPath(int|string ...$elements): Callback { $callback = function (PathInterface $path) use ($elements): bool { return $path->equals(new Path(...$elements)); diff --git a/tests/Value/DecodedJson/NodeObjectValueTest.php b/tests/Value/DecodedJson/NodeObjectValueTest.php index 55bae3c..58a6ccc 100644 --- a/tests/Value/DecodedJson/NodeObjectValueTest.php +++ b/tests/Value/DecodedJson/NodeObjectValueTest.php @@ -20,7 +20,6 @@ */ class NodeObjectValueTest extends TestCase { - public function testCreateChildIterator_EmptyObjectData_ReturnsEmptyIterator(): void { $value = new NodeObjectValue((object) [], new Path(), NodeValueFactory::create()); @@ -30,26 +29,33 @@ public function testCreateChildIterator_EmptyObjectData_ReturnsEmptyIterator(): public function testCreateChildIterator_NotEmptyObjectData_CallsFactoryForEachElement(): void { - $nodeValueFactory = $this->createMock(NodeValueFactoryInterface::class); + $nodeValueFactory = $this->createStub(NodeValueFactoryInterface::class); $value = new NodeObjectValue((object) ['a' => 'b', 'c' => 1], new Path('d'), $nodeValueFactory); + $interceptedArgs = []; $nodeValueFactory - ->expects(self::exactly(2)) ->method('createValue') - ->withConsecutive( - [self::identicalTo('b'), $this->isArgEqualPath('d', 'a')], - [self::identicalTo(1), $this->isArgEqualPath('d', 'c')], + ->willReturnCallback( + function (mixed $data, ?PathInterface $path) use (&$interceptedArgs): NodeValueInterface { + /** @psalm-var array $interceptedArgs */ + $interceptedArgs[] = [$data, $path?->getElements() ?? []]; + + return $this->createStub(NodeValueInterface::class); + }, ); iterator_to_array($value->createChildIterator(), true); + $expectedValue = [ + ['b', ['d', 'a']], + [1, ['d', 'c']], + ]; + self::assertSame($expectedValue, $interceptedArgs); } - private function isArgEqualPath(...$elements): Callback + private static function isArgEqualPath(...$elements): Callback { - $callback = function (PathInterface $path) use ($elements): bool { - return $path->equals(new Path(...$elements)); - }; - - return self::callback($callback); + return self::callback( + fn (PathInterface $path): bool => $path->equals(new Path(...$elements)), + ); } public function testCreateChildIterator_NodeFactoryReturnsValues_ReturnsSameValuesWithMatchingIndexes(): void diff --git a/tests/Value/DecodedJson/NodeScalarValueTest.php b/tests/Value/DecodedJson/NodeScalarValueTest.php index e0b7239..40edc9c 100644 --- a/tests/Value/DecodedJson/NodeScalarValueTest.php +++ b/tests/Value/DecodedJson/NodeScalarValueTest.php @@ -14,18 +14,19 @@ */ class NodeScalarValueTest extends TestCase { - /** - * @param $data * @dataProvider providerInvalidData */ - public function testConstruct_InvalidData_ThrowsMatchingException($data): void + public function testConstruct_InvalidData_ThrowsMatchingException(mixed $data): void { $this->expectException(InvalidNodeDataException::class); new NodeScalarValue($data, new Path()); } - public function providerInvalidData(): array + /** + * @return iterable + */ + public static function providerInvalidData(): iterable { return [ 'Resource' => [STDERR], diff --git a/tests/Value/DecodedJson/NodeValueFactoryTest.php b/tests/Value/DecodedJson/NodeValueFactoryTest.php index 3f21594..0b8287f 100644 --- a/tests/Value/DecodedJson/NodeValueFactoryTest.php +++ b/tests/Value/DecodedJson/NodeValueFactoryTest.php @@ -20,18 +20,19 @@ */ class NodeValueFactoryTest extends TestCase { - /** - * @param mixed $data * @dataProvider providerScalarDataOrNull */ - public function testCreateValue_ScalarDataOrNull_ReturnsNodeScalarValue($data): void + public function testCreateValue_ScalarDataOrNull_ReturnsNodeScalarValue(mixed $data): void { $actualValue = NodeValueFactory::create()->createValue($data, new Path()); self::assertInstanceOf(NodeScalarValue::class, $actualValue); } - public function providerScalarDataOrNull(): array + /** + * @return iterable + */ + public static function providerScalarDataOrNull(): iterable { return [ 'Null' => [null, null], @@ -43,10 +44,9 @@ public function providerScalarDataOrNull(): array } /** - * @param mixed $data * @dataProvider providerScalarDataOrNull */ - public function testCreateValue_ScalarValueAndGivenPath_ResultHasSamePathInstance($data): void + public function testCreateValue_ScalarValueAndGivenPath_ResultHasSamePathInstance(mixed $data): void { $path = new Path(); $actualValue = NodeValueFactory::create()->createValue($data, $path); @@ -54,21 +54,18 @@ public function testCreateValue_ScalarValueAndGivenPath_ResultHasSamePathInstanc } /** - * @param mixed $data * @dataProvider providerScalarDataOrNull */ - public function testCreateValue_ScalarValueAndNoPath_ResultHasEmptyPath($data): void + public function testCreateValue_ScalarValueAndNoPath_ResultHasEmptyPath(mixed $data): void { $actualValue = NodeValueFactory::create()->createValue($data); self::assertEmpty($actualValue->getPath()->getElements()); } /** - * @param mixed $data - * @param $expectedValue * @dataProvider providerScalarDataOrNull */ - public function testCreateValue_ScalarValue_ResultHasMatchingData($data, $expectedValue): void + public function testCreateValue_ScalarValue_ResultHasMatchingData(mixed $data, mixed $expectedValue): void { $path = new Path(); /** @var ScalarValueInterface $actualValue */ @@ -120,11 +117,4 @@ public function testCreateValue_NonScalarValue_ThrowsException(): void $this->expectException(InvalidNodeDataException::class); $factory->createValue(STDOUT, new Path()); } - - public function testCreateValue_NonMatchingObject_ThrowsException(): void - { - $factory = NodeValueFactory::create(); - $this->expectException(InvalidNodeDataException::class); - $factory->createValue(new Path(), new Path()); - } } diff --git a/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php b/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php index b70331a..8d65a6c 100644 --- a/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php +++ b/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php @@ -13,7 +13,6 @@ */ class JsonNotDecodedExceptionTest extends TestCase { - public function testGetMessage_Constructed_ReturnsMatchingValue(): void { $exception = new JsonNotDecodedException('a'); diff --git a/tests/Value/EncodedJson/NodeValueFactoryTest.php b/tests/Value/EncodedJson/NodeValueFactoryTest.php index c5d4d8d..7ac9d7a 100644 --- a/tests/Value/EncodedJson/NodeValueFactoryTest.php +++ b/tests/Value/EncodedJson/NodeValueFactoryTest.php @@ -16,7 +16,6 @@ */ class NodeValueFactoryTest extends TestCase { - public function testCreate_Always_ReturnsNodeValueInstance(): void { self::assertInstanceOf(NodeValueFactory::class, NodeValueFactory::create()); diff --git a/tests/Walker/Exception/UnexpectedEntityExceptionTest.php b/tests/Walker/Exception/UnexpectedEntityExceptionTest.php index 5d041b5..21db604 100644 --- a/tests/Walker/Exception/UnexpectedEntityExceptionTest.php +++ b/tests/Walker/Exception/UnexpectedEntityExceptionTest.php @@ -13,7 +13,6 @@ */ class UnexpectedEntityExceptionTest extends TestCase { - public function testGetMessage_Constructed_ReturnsMatchingValue(): void { $exception = new UnexpectedEntityException('a'); From 2bf978a245de9d00cd1026deeb45a697ad91ca5c Mon Sep 17 00:00:00 2001 From: remorhaz Date: Fri, 16 Jun 2023 16:51:54 +0300 Subject: [PATCH 2/8] Release 0.6.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea12f16..dbfaf81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.6.0] - 2023-06-16 ### Changed - JSON source structure may contain arbitrary objects, not only `stdClass`. ### Removed From c5a6b3f753b26eea81ef058f790db57fd68279b5 Mon Sep 17 00:00:00 2001 From: remorhaz Date: Fri, 16 Jun 2023 17:04:05 +0300 Subject: [PATCH 3/8] Infection badge fixed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eab63d1..6b1a252 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/remorhaz/php-json-data/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/remorhaz/php-json-data/?branch=master) [![codecov](https://codecov.io/gh/remorhaz/php-json-data/branch/master/graph/badge.svg)](https://codecov.io/gh/remorhaz/php-json-data) [![Total Downloads](https://poser.pugx.org/remorhaz/php-json-data/downloads)](https://packagist.org/packages/remorhaz/php-json-data) -[![Mutation testing badge](https://badge.stryker-mutator.io/github.com/remorhaz/php-json-data/master)](https://stryker-mutator.github.io) +[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fremorhaz%2Fphp-json-data%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/remorhaz/php-json-data/master) [![License](https://poser.pugx.org/remorhaz/php-json-data/license)](https://packagist.org/packages/remorhaz/php-json-data) This library provides infrastructure for JSON documents processing. From 3008c1d9c14831f1f9db737e8a5440e90d591cfa Mon Sep 17 00:00:00 2001 From: remorhaz Date: Sun, 11 Feb 2024 00:06:52 +0200 Subject: [PATCH 4/8] Drop PHP 8.0, support PHP 8.3 --- .github/workflows/build.yml | 6 +++- .gitignore | 3 ++ .phive/phars.xml | 4 +++ CHANGELOG.md | 6 ++++ LICENSE | 2 +- README.md | 2 +- composer.json | 36 ++++++++++++++----- docker-compose.yml | 10 +++--- php-8.0.Dockerfile | 15 -------- php-8.1.Dockerfile | 22 +++++++++--- php-8.2.Dockerfile | 22 +++++++++--- php-8.3.Dockerfile | 27 ++++++++++++++ phpunit.xml.dist | 29 +++++++-------- psalm.xml.dist | 2 +- src/Comparator/ContainsValueComparator.php | 19 +++++----- src/Comparator/EqualValueComparator.php | 32 +++++++---------- src/Comparator/GreaterValueComparator.php | 8 ++--- src/Event/AfterArrayEvent.php | 2 +- src/Event/AfterElementEvent.php | 4 +-- src/Event/AfterObjectEvent.php | 2 +- src/Event/AfterPropertyEvent.php | 4 +-- src/Event/BeforeArrayEvent.php | 2 +- src/Event/BeforeElementEvent.php | 4 +-- src/Event/BeforeObjectEvent.php | 2 +- src/Event/BeforePropertyEvent.php | 4 +-- .../Exception/InvalidScalarDataException.php | 4 +-- src/Event/ScalarEvent.php | 2 +- .../Exception/EncodingFailedException.php | 4 +-- .../Exception/NoValueToExportException.php | 2 +- .../Exception/UnexpectedValueException.php | 2 +- .../Exception/UnknownEventException.php | 4 +-- src/Export/ValueEncoder.php | 2 +- .../Exception/ParentNotFoundException.php | 4 +-- .../Exception/InvalidElementKeyException.php | 11 ++---- .../Exception/InvalidNodeDataException.php | 6 ++-- src/Value/DecodedJson/NodeArrayValue.php | 6 ++-- src/Value/DecodedJson/NodeObjectValue.php | 6 ++-- src/Value/DecodedJson/NodeScalarValue.php | 2 +- .../Exception/JsonNotDecodedException.php | 4 +-- src/Value/EncodedJson/NodeValueFactory.php | 2 +- .../Exception/UnexpectedEntityException.php | 4 +-- .../ContainsValueComparatorTest.php | 28 ++++++--------- tests/Comparator/EqualValueComparatorTest.php | 36 +++++++++---------- .../Comparator/GreaterValueComparatorTest.php | 32 ++++++++--------- tests/Event/AfterArrayEventTest.php | 5 ++- tests/Event/AfterElementEventTest.php | 5 ++- tests/Event/AfterObjectEventTest.php | 5 ++- tests/Event/AfterPropertyEventTest.php | 5 ++- tests/Event/BeforeArrayEventTest.php | 5 ++- tests/Event/BeforeElementEventTest.php | 5 ++- tests/Event/BeforeObjectEventTest.php | 5 ++- tests/Event/BeforePropertyEventTest.php | 5 ++- .../InvalidScalarDataExceptionTest.php | 13 ++----- tests/Event/ScalarEventTest.php | 10 +++--- .../Exception/EncodingFailedExceptionTest.php | 11 ++---- .../NoValueToExportExceptionTest.php | 5 ++- .../UnexpectedValueExceptionTest.php | 19 ++++------ .../Exception/UnknownEventExceptionTest.php | 19 ++++------ .../Exception/ParentNotFoundExceptionTest.php | 14 +++----- tests/Path/PathTest.php | 14 ++++---- .../InvalidElementKeyExceptionTest.php | 18 +++------- .../InvalidNodeDataExceptionTest.php | 14 +++----- .../Value/DecodedJson/NodeArrayValueTest.php | 30 +++++----------- .../Value/DecodedJson/NodeObjectValueTest.php | 23 ++++-------- .../Value/DecodedJson/NodeScalarValueTest.php | 10 +++--- .../DecodedJson/NodeValueFactoryTest.php | 22 ++++-------- .../Exception/JsonNotDecodedExceptionTest.php | 11 ++---- .../EncodedJson/NodeValueFactoryTest.php | 13 ++++--- .../UnexpectedEntityExceptionTest.php | 11 ++---- vendor-bin/cs/composer.json | 5 +++ vendor-bin/psalm/composer.json | 9 +++++ 71 files changed, 346 insertions(+), 395 deletions(-) create mode 100644 .phive/phars.xml delete mode 100644 php-8.0.Dockerfile create mode 100644 php-8.3.Dockerfile create mode 100644 vendor-bin/cs/composer.json create mode 100644 vendor-bin/psalm/composer.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 34962d6..b5ff14f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,13 +12,14 @@ jobs: tests: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: platform-reqs: - use-platform-reqs php-version: - - "8.0" - "8.1" - "8.2" + - "8.3" dependencies: - lowest - highest @@ -32,6 +33,9 @@ jobs: with: php-version: ${{ matrix.php-version }} + - name: Install PHIVE + uses: szepeviktor/phive@v1 + - name: Install lowest dependencies if: ${{ matrix.dependencies == 'lowest' && matrix.platform-reqs == 'use-platform-reqs' }} run: composer update --no-interaction --prefer-lowest diff --git a/.gitignore b/.gitignore index 04d9ea3..6958379 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ /build/ /vendor/ /composer.lock +/vendor-bin/**/vendor/ +/vendor-bin/**/composer.lock /infection.json /phpunit.xml +/tools/ .phpunit.result.cache diff --git a/.phive/phars.xml b/.phive/phars.xml new file mode 100644 index 0000000..bda539d --- /dev/null +++ b/.phive/phars.xml @@ -0,0 +1,4 @@ + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index dbfaf81..ecb3f7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Added +- Added PHP 8.3 support. +### Removed +- Removed PHP 8.0 support. + ## [0.6.0] - 2023-06-16 ### Changed - JSON source structure may contain arbitrary objects, not only `stdClass`. diff --git a/LICENSE b/LICENSE index f7a5ce0..9e9e88a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2019 Edward Surov +Copyright (c) 2016-2024 Edward Surov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6b1a252..413bd30 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This library provides infrastructure for JSON documents processing. ## Requirements -- PHP 8 +- PHP 8.1 or newer. - [Internationalization functions](https://www.php.net/manual/en/book.intl.php) (ext-intl) - to compare Unicode strings. - [JSON extension](https://www.php.net/manual/en/book.json.php) (ext-json) - to encode and decode JSON documents. diff --git a/composer.json b/composer.json index f90ca93..3a7ff0f 100644 --- a/composer.json +++ b/composer.json @@ -14,16 +14,13 @@ } ], "require": { - "php": "~8.0.0 || ~8.1.0 || ~8.2.0", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0", "ext-json": "*", "ext-intl": "*" }, "require-dev": { - "infection/infection": "^0.26 || ^0.27", - "phpunit/phpunit": "^9.5 || ^10", - "psalm/plugin-phpunit": "^0.18.1", - "squizlabs/php_codesniffer": "^3.7.2", - "vimeo/psalm": "^5.12" + "bamarni/composer-bin-plugin": "^1.8", + "phpunit/phpunit": "^10.1 || ^11" }, "autoload": { "psr-4": { @@ -36,21 +33,34 @@ } }, "scripts": { + "post-update-cmd": ["@phive-install"], + "post-install-cmd": ["@phive-install"], + "phive-install": [ + "`if [ -f tools/phive ]; then echo 'tools/'; fi`phive install --trust-gpg-keys C5095986493B4AA0" + ], "test-cs": [ - "vendor/bin/phpcs -sp" + "vendor-bin/cs/vendor/bin/phpcs -sp" ], "test-unit": [ "vendor/bin/phpunit --coverage-xml=build/log/coverage-xml --coverage-clover=build/log/clover.xml --log-junit=build/log/junit.xml" ], - "test-psalm": "vendor/bin/psalm --threads=4 --shepherd", + "test-unit-9": [ + "vendor/bin/phpunit --configuration=phpunit-9.xml --coverage-xml=build/log/coverage-xml --coverage-clover=build/log/clover.xml --log-junit=build/log/junit.xml" + ], + "test-psalm": "vendor-bin/psalm/vendor/bin/psalm --threads=4 --shepherd", "test": [ "@test-cs", "@test-unit", "@test-psalm" ], + "test-8.0": [ + "@test-cs", + "@test-unit-9", + "@test-psalm" + ], "infection": [ "mkdir -p build/log/infection", - "vendor/bin/infection --threads=4 --coverage=build/log --no-progress --skip-initial-tests" + "tools/infection --threads=4 --coverage=build/log --no-progress --skip-initial-tests" ], "test-infection": [ "@test-unit", @@ -59,7 +69,15 @@ }, "config": { "allow-plugins": { + "bamarni/composer-bin-plugin": true, "infection/extension-installer": true + }, + "sort-packages": true + }, + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": true } } } diff --git a/docker-compose.yml b/docker-compose.yml index 92abc6e..a3e8597 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,21 +4,21 @@ services: php: build: context: . - dockerfile: php-8.0.Dockerfile + dockerfile: php-8.1.Dockerfile volumes: - .:/app working_dir: /app - php8.1: + php8.2: build: context: . - dockerfile: php-8.1.Dockerfile + dockerfile: php-8.2.Dockerfile volumes: - .:/app working_dir: /app - php8.2: + php8.3: build: context: . - dockerfile: php-8.2.Dockerfile + dockerfile: php-8.3.Dockerfile volumes: - .:/app working_dir: /app diff --git a/php-8.0.Dockerfile b/php-8.0.Dockerfile deleted file mode 100644 index b0ce733..0000000 --- a/php-8.0.Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM php:8.0-cli - -RUN apt-get update && apt-get install -y \ - zip \ - git \ - libicu-dev && \ - docker-php-ext-configure intl --enable-intl && \ - docker-php-ext-install intl pcntl && \ - echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" - -ENV COMPOSER_ALLOW_SUPERUSER=1 \ - COMPOSER_PROCESS_TIMEOUT=1200 - -RUN curl --silent --show-error https://getcomposer.org/installer | php -- \ - --install-dir=/usr/bin --filename=composer diff --git a/php-8.1.Dockerfile b/php-8.1.Dockerfile index b0ce733..eb2ffdf 100644 --- a/php-8.1.Dockerfile +++ b/php-8.1.Dockerfile @@ -1,15 +1,27 @@ -FROM php:8.0-cli +FROM php:8.1-cli RUN apt-get update && apt-get install -y \ - zip \ - git \ - libicu-dev && \ + zip \ + git \ + wget \ + gpg \ + libicu-dev && \ + pecl install xdebug && \ docker-php-ext-configure intl --enable-intl && \ docker-php-ext-install intl pcntl && \ + docker-php-ext-enable xdebug && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ COMPOSER_PROCESS_TIMEOUT=1200 RUN curl --silent --show-error https://getcomposer.org/installer | php -- \ - --install-dir=/usr/bin --filename=composer + --install-dir=/usr/bin --filename=composer && \ + git config --global --add safe.directory "*" + +RUN wget -O phive.phar https://phar.io/releases/phive.phar && \ + wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc && \ + gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 && \ + gpg --verify phive.phar.asc phive.phar && \ + chmod +x phive.phar && \ + mv phive.phar /usr/local/bin/phive \ diff --git a/php-8.2.Dockerfile b/php-8.2.Dockerfile index b0ce733..8ac0caa 100644 --- a/php-8.2.Dockerfile +++ b/php-8.2.Dockerfile @@ -1,15 +1,27 @@ -FROM php:8.0-cli +FROM php:8.2-cli RUN apt-get update && apt-get install -y \ - zip \ - git \ - libicu-dev && \ + zip \ + git \ + wget \ + gpg \ + libicu-dev && \ + pecl install xdebug && \ docker-php-ext-configure intl --enable-intl && \ docker-php-ext-install intl pcntl && \ + docker-php-ext-enable xdebug && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ COMPOSER_PROCESS_TIMEOUT=1200 RUN curl --silent --show-error https://getcomposer.org/installer | php -- \ - --install-dir=/usr/bin --filename=composer + --install-dir=/usr/bin --filename=composer && \ + git config --global --add safe.directory "*" + +RUN wget -O phive.phar https://phar.io/releases/phive.phar && \ + wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc && \ + gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 && \ + gpg --verify phive.phar.asc phive.phar && \ + chmod +x phive.phar && \ + mv phive.phar /usr/local/bin/phive \ diff --git a/php-8.3.Dockerfile b/php-8.3.Dockerfile new file mode 100644 index 0000000..f83e2e2 --- /dev/null +++ b/php-8.3.Dockerfile @@ -0,0 +1,27 @@ +FROM php:8.3-cli + +RUN apt-get update && apt-get install -y \ + zip \ + git \ + wget \ + gpg \ + libicu-dev && \ + pecl install xdebug && \ + docker-php-ext-configure intl --enable-intl && \ + docker-php-ext-install intl pcntl && \ + docker-php-ext-enable xdebug && \ + echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" + +ENV COMPOSER_ALLOW_SUPERUSER=1 \ + COMPOSER_PROCESS_TIMEOUT=1200 + +RUN curl --silent --show-error https://getcomposer.org/installer | php -- \ + --install-dir=/usr/bin --filename=composer && \ + git config --global --add safe.directory "*" + +RUN wget -O phive.phar https://phar.io/releases/phive.phar && \ + wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc && \ + gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 && \ + gpg --verify phive.phar.asc phive.phar && \ + chmod +x phive.phar && \ + mv phive.phar /usr/local/bin/phive \ diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f9a7b24..df2a9ff 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,18 +1,19 @@ - + - - - tests/ - - - - - src/ - - + colors="true" + cacheDirectory="build/.phpunit.cache" + requireCoverageMetadata="true"> + + + tests/ + + + + + src/ + + diff --git a/psalm.xml.dist b/psalm.xml.dist index ab09605..efca3b8 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -9,7 +9,7 @@ findUnusedVariablesAndParams="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" - xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"> + xsi:schemaLocation="https://getpsalm.org/schema/config vendor-bin/psalm/vendor/vimeo/psalm/config.xsd"> diff --git a/src/Comparator/ContainsValueComparator.php b/src/Comparator/ContainsValueComparator.php index a54d8f1..c235f70 100644 --- a/src/Comparator/ContainsValueComparator.php +++ b/src/Comparator/ContainsValueComparator.php @@ -23,17 +23,14 @@ public function __construct(Collator $collator) public function compare(ValueInterface $leftValue, ValueInterface $rightValue): bool { - if ($leftValue instanceof ScalarValueInterface && $rightValue instanceof ScalarValueInterface) { - return $this->equalComparator->compare($leftValue, $rightValue); - } - if ($leftValue instanceof ArrayValueInterface && $rightValue instanceof ArrayValueInterface) { - return $this->equalComparator->compare($leftValue, $rightValue); - } - if ($leftValue instanceof ObjectValueInterface && $rightValue instanceof ObjectValueInterface) { - return $this->objectContains($leftValue, $rightValue); - } - - return false; + return match (true) { + $leftValue instanceof ScalarValueInterface && $rightValue instanceof ScalarValueInterface, + $leftValue instanceof ArrayValueInterface && $rightValue instanceof ArrayValueInterface => + $this->equalComparator->compare($leftValue, $rightValue), + $leftValue instanceof ObjectValueInterface && $rightValue instanceof ObjectValueInterface => + $this->objectContains($leftValue, $rightValue), + default => false, + }; } private function objectContains(ObjectValueInterface $leftValue, ObjectValueInterface $rightValue): bool diff --git a/src/Comparator/EqualValueComparator.php b/src/Comparator/EqualValueComparator.php index 4115338..aa7f1e4 100644 --- a/src/Comparator/EqualValueComparator.php +++ b/src/Comparator/EqualValueComparator.php @@ -17,25 +17,21 @@ final class EqualValueComparator implements ComparatorInterface { public function __construct( - private Collator $collator, + private readonly Collator $collator, ) { } public function compare(ValueInterface $leftValue, ValueInterface $rightValue): bool { - if ($leftValue instanceof ScalarValueInterface && $rightValue instanceof ScalarValueInterface) { - return $this->isScalarEqual($leftValue, $rightValue); - } - - if ($leftValue instanceof ArrayValueInterface && $rightValue instanceof ArrayValueInterface) { - return $this->isArrayEqual($leftValue, $rightValue); - } - - if ($leftValue instanceof ObjectValueInterface && $rightValue instanceof ObjectValueInterface) { - return $this->isObjectEqual($leftValue, $rightValue); - } - - return false; + return match (true) { + $leftValue instanceof ScalarValueInterface && $rightValue instanceof ScalarValueInterface => + $this->isScalarEqual($leftValue, $rightValue), + $leftValue instanceof ArrayValueInterface && $rightValue instanceof ArrayValueInterface => + $this->isArrayEqual($leftValue, $rightValue), + $leftValue instanceof ObjectValueInterface && $rightValue instanceof ObjectValueInterface => + $this->isObjectEqual($leftValue, $rightValue), + default => false, + }; } private function isScalarEqual(ScalarValueInterface $leftValue, ScalarValueInterface $rightValue): bool @@ -43,11 +39,9 @@ private function isScalarEqual(ScalarValueInterface $leftValue, ScalarValueInter $leftData = $leftValue->getData(); $rightData = $rightValue->getData(); - if (is_string($leftData) && is_string($rightData)) { - return 0 === $this->collator->compare($leftData, $rightData); - } - - return $leftData === $rightData; + return is_string($leftData) && is_string($rightData) + ? 0 === $this->collator->compare($leftData, $rightData) + : $leftData === $rightData; } private function isArrayEqual(ArrayValueInterface $leftValue, ArrayValueInterface $rightValue): bool diff --git a/src/Comparator/GreaterValueComparator.php b/src/Comparator/GreaterValueComparator.php index 20a2910..02dc616 100644 --- a/src/Comparator/GreaterValueComparator.php +++ b/src/Comparator/GreaterValueComparator.php @@ -15,7 +15,7 @@ final class GreaterValueComparator implements ComparatorInterface { public function __construct( - private Collator $collator, + private readonly Collator $collator, ) { } @@ -35,10 +35,6 @@ private function isScalarGreater(ScalarValueInterface $leftValue, ScalarValueInt return $leftData > $rightData; } - if (is_string($leftData) && is_string($rightData)) { - return 1 === $this->collator->compare($leftData, $rightData); - } - - return false; + return is_string($leftData) && is_string($rightData) && 1 === $this->collator->compare($leftData, $rightData); } } diff --git a/src/Event/AfterArrayEvent.php b/src/Event/AfterArrayEvent.php index 690ffe1..9cf10be 100644 --- a/src/Event/AfterArrayEvent.php +++ b/src/Event/AfterArrayEvent.php @@ -9,7 +9,7 @@ final class AfterArrayEvent implements AfterArrayEventInterface { public function __construct( - private PathInterface $path, + private readonly PathInterface $path, ) { } diff --git a/src/Event/AfterElementEvent.php b/src/Event/AfterElementEvent.php index 062730a..b2858b2 100644 --- a/src/Event/AfterElementEvent.php +++ b/src/Event/AfterElementEvent.php @@ -9,8 +9,8 @@ final class AfterElementEvent implements AfterElementEventInterface { public function __construct( - private int $index, - private PathInterface $path, + private readonly int $index, + private readonly PathInterface $path, ) { } diff --git a/src/Event/AfterObjectEvent.php b/src/Event/AfterObjectEvent.php index 3fb2794..c03dcb6 100644 --- a/src/Event/AfterObjectEvent.php +++ b/src/Event/AfterObjectEvent.php @@ -9,7 +9,7 @@ final class AfterObjectEvent implements AfterObjectEventInterface { public function __construct( - private PathInterface $path, + private readonly PathInterface $path, ) { } diff --git a/src/Event/AfterPropertyEvent.php b/src/Event/AfterPropertyEvent.php index c03cc41..2ca32de 100644 --- a/src/Event/AfterPropertyEvent.php +++ b/src/Event/AfterPropertyEvent.php @@ -9,8 +9,8 @@ final class AfterPropertyEvent implements AfterPropertyEventInterface { public function __construct( - private string $name, - private PathInterface $path, + private readonly string $name, + private readonly PathInterface $path, ) { } diff --git a/src/Event/BeforeArrayEvent.php b/src/Event/BeforeArrayEvent.php index 093caee..5230aa4 100644 --- a/src/Event/BeforeArrayEvent.php +++ b/src/Event/BeforeArrayEvent.php @@ -9,7 +9,7 @@ final class BeforeArrayEvent implements BeforeArrayEventInterface { public function __construct( - private PathInterface $path, + private readonly PathInterface $path, ) { } diff --git a/src/Event/BeforeElementEvent.php b/src/Event/BeforeElementEvent.php index b0458af..3b8b313 100644 --- a/src/Event/BeforeElementEvent.php +++ b/src/Event/BeforeElementEvent.php @@ -9,8 +9,8 @@ final class BeforeElementEvent implements BeforeElementEventInterface { public function __construct( - private int $index, - private PathInterface $path, + private readonly int $index, + private readonly PathInterface $path, ) { } diff --git a/src/Event/BeforeObjectEvent.php b/src/Event/BeforeObjectEvent.php index af6252e..4923cb4 100644 --- a/src/Event/BeforeObjectEvent.php +++ b/src/Event/BeforeObjectEvent.php @@ -9,7 +9,7 @@ final class BeforeObjectEvent implements BeforeObjectEventInterface { public function __construct( - private PathInterface $path, + private readonly PathInterface $path, ) { } diff --git a/src/Event/BeforePropertyEvent.php b/src/Event/BeforePropertyEvent.php index d69e5ad..6274320 100644 --- a/src/Event/BeforePropertyEvent.php +++ b/src/Event/BeforePropertyEvent.php @@ -9,8 +9,8 @@ final class BeforePropertyEvent implements BeforePropertyEventInterface { public function __construct( - private string $name, - private PathInterface $path, + private readonly string $name, + private readonly PathInterface $path, ) { } diff --git a/src/Event/Exception/InvalidScalarDataException.php b/src/Event/Exception/InvalidScalarDataException.php index 5b1f939..8aec0b0 100644 --- a/src/Event/Exception/InvalidScalarDataException.php +++ b/src/Event/Exception/InvalidScalarDataException.php @@ -11,10 +11,10 @@ final class InvalidScalarDataException extends LogicException implements ExceptionInterface, DataAwareInterface { public function __construct( - private mixed $data, + private readonly mixed $data, ?Throwable $previous = null, ) { - parent::__construct("Invalid scalar data", 0, $previous); + parent::__construct("Invalid scalar data", previous: $previous); } public function getData(): mixed diff --git a/src/Event/ScalarEvent.php b/src/Event/ScalarEvent.php index b4ac644..792524c 100644 --- a/src/Event/ScalarEvent.php +++ b/src/Event/ScalarEvent.php @@ -14,7 +14,7 @@ final class ScalarEvent implements ScalarEventInterface public function __construct( mixed $data, - private PathInterface $path, + private readonly PathInterface $path, ) { $this->data = null === $data || is_scalar($data) ? $data diff --git a/src/Export/Exception/EncodingFailedException.php b/src/Export/Exception/EncodingFailedException.php index 5b29a70..3e784f2 100644 --- a/src/Export/Exception/EncodingFailedException.php +++ b/src/Export/Exception/EncodingFailedException.php @@ -11,10 +11,10 @@ final class EncodingFailedException extends LogicException implements ExceptionInterface, DataAwareInterface { public function __construct( - private mixed $data, + private readonly mixed $data, ?Throwable $previous = null, ) { - parent::__construct("Failed to encode data to JSON", 0, $previous); + parent::__construct("Failed to encode data to JSON", previous: $previous); } public function getData(): mixed diff --git a/src/Export/Exception/NoValueToExportException.php b/src/Export/Exception/NoValueToExportException.php index 3c6c5dc..4ca6c88 100644 --- a/src/Export/Exception/NoValueToExportException.php +++ b/src/Export/Exception/NoValueToExportException.php @@ -11,6 +11,6 @@ final class NoValueToExportException extends LogicException implements Exception { public function __construct(?Throwable $previous = null) { - parent::__construct("No value to export", 0, $previous); + parent::__construct("No value to export", previous: $previous); } } diff --git a/src/Export/Exception/UnexpectedValueException.php b/src/Export/Exception/UnexpectedValueException.php index 9c2c774..3d2d783 100644 --- a/src/Export/Exception/UnexpectedValueException.php +++ b/src/Export/Exception/UnexpectedValueException.php @@ -14,7 +14,7 @@ public function __construct( private ValueInterface $value, ?Throwable $previous = null, ) { - parent::__construct("Unexpected value", 0, $previous); + parent::__construct("Unexpected value", previous: $previous); } public function getValue(): ValueInterface diff --git a/src/Export/Exception/UnknownEventException.php b/src/Export/Exception/UnknownEventException.php index 68706a4..ba254c7 100644 --- a/src/Export/Exception/UnknownEventException.php +++ b/src/Export/Exception/UnknownEventException.php @@ -11,10 +11,10 @@ final class UnknownEventException extends LogicException implements ExceptionInterface { public function __construct( - private EventInterface $event, + private readonly EventInterface $event, ?Throwable $previous = null, ) { - parent::__construct("Unknown event", 0, $previous); + parent::__construct("Unknown event", previous: $previous); } public function getEvent(): EventInterface diff --git a/src/Export/ValueEncoder.php b/src/Export/ValueEncoder.php index 0f2fdff..06d82cb 100644 --- a/src/Export/ValueEncoder.php +++ b/src/Export/ValueEncoder.php @@ -19,7 +19,7 @@ final class ValueEncoder implements ValueEncoderInterface { public function __construct( - private ValueDecoderInterface $decoder, + private readonly ValueDecoderInterface $decoder, ) { } diff --git a/src/Path/Exception/ParentNotFoundException.php b/src/Path/Exception/ParentNotFoundException.php index d556439..4ff498e 100644 --- a/src/Path/Exception/ParentNotFoundException.php +++ b/src/Path/Exception/ParentNotFoundException.php @@ -14,10 +14,10 @@ final class ParentNotFoundException extends LogicException implements ExceptionInterface, PathAwareInterface { public function __construct( - private PathInterface $path, + private readonly PathInterface $path, ?Throwable $previous = null, ) { - parent::__construct("Parent not found in path {$this->buildPath()}", 0, $previous); + parent::__construct("Parent not found in path {$this->buildPath()}", previous: $previous); } public function getPath(): PathInterface diff --git a/src/Value/DecodedJson/Exception/InvalidElementKeyException.php b/src/Value/DecodedJson/Exception/InvalidElementKeyException.php index 695e4c2..8159108 100644 --- a/src/Value/DecodedJson/Exception/InvalidElementKeyException.php +++ b/src/Value/DecodedJson/Exception/InvalidElementKeyException.php @@ -16,17 +16,12 @@ class InvalidElementKeyException extends RuntimeException implements ExceptionInterface, PathAwareInterface { - /** - * @param mixed $key - * @param PathInterface $path - * @param Throwable|null $previous - */ public function __construct( - private mixed $key, - private PathInterface $path, + private readonly mixed $key, + private readonly PathInterface $path, ?Throwable $previous = null, ) { - parent::__construct($this->buildMessage(), 0, $previous); + parent::__construct($this->buildMessage(), previous: $previous); } private function buildMessage(): string diff --git a/src/Value/DecodedJson/Exception/InvalidNodeDataException.php b/src/Value/DecodedJson/Exception/InvalidNodeDataException.php index 817685b..f6809ca 100644 --- a/src/Value/DecodedJson/Exception/InvalidNodeDataException.php +++ b/src/Value/DecodedJson/Exception/InvalidNodeDataException.php @@ -17,11 +17,11 @@ class InvalidNodeDataException extends RuntimeException implements DataAwareInterface { public function __construct( - private mixed $data, - private PathInterface $path, + private readonly mixed $data, + private readonly PathInterface $path, ?Throwable $previous = null, ) { - parent::__construct($this->buildMessage(), 0, $previous); + parent::__construct($this->buildMessage(), previous: $previous); } private function buildMessage(): string diff --git a/src/Value/DecodedJson/NodeArrayValue.php b/src/Value/DecodedJson/NodeArrayValue.php index 959edcc..5add4aa 100644 --- a/src/Value/DecodedJson/NodeArrayValue.php +++ b/src/Value/DecodedJson/NodeArrayValue.php @@ -14,9 +14,9 @@ final class NodeArrayValue implements NodeValueInterface, ArrayValueInterface { public function __construct( - private array $data, - private PathInterface $path, - private NodeValueFactoryInterface $valueFactory + private readonly array $data, + private readonly PathInterface $path, + private readonly NodeValueFactoryInterface $valueFactory, ) { } diff --git a/src/Value/DecodedJson/NodeObjectValue.php b/src/Value/DecodedJson/NodeObjectValue.php index 4a910a1..2b56a2f 100644 --- a/src/Value/DecodedJson/NodeObjectValue.php +++ b/src/Value/DecodedJson/NodeObjectValue.php @@ -12,9 +12,9 @@ final class NodeObjectValue implements NodeValueInterface, ObjectValueInterface { public function __construct( - private object $data, - private PathInterface $path, - private NodeValueFactoryInterface $valueFactory, + private readonly object $data, + private readonly PathInterface $path, + private readonly NodeValueFactoryInterface $valueFactory, ) { } diff --git a/src/Value/DecodedJson/NodeScalarValue.php b/src/Value/DecodedJson/NodeScalarValue.php index e48a795..04347de 100644 --- a/src/Value/DecodedJson/NodeScalarValue.php +++ b/src/Value/DecodedJson/NodeScalarValue.php @@ -16,7 +16,7 @@ final class NodeScalarValue implements NodeValueInterface, ScalarValueInterface public function __construct( mixed $data, - private PathInterface $path, + private readonly PathInterface $path, ) { $this->data = null === $data || is_scalar($data) ? $data diff --git a/src/Value/EncodedJson/Exception/JsonNotDecodedException.php b/src/Value/EncodedJson/Exception/JsonNotDecodedException.php index 12867cd..5d71077 100644 --- a/src/Value/EncodedJson/Exception/JsonNotDecodedException.php +++ b/src/Value/EncodedJson/Exception/JsonNotDecodedException.php @@ -10,10 +10,10 @@ final class JsonNotDecodedException extends RuntimeException implements ExceptionInterface { public function __construct( - private string $json, + private readonly string $json, ?Throwable $previous = null, ) { - parent::__construct("Failed to decode JSON", 0, $previous); + parent::__construct("Failed to decode JSON", previous: $previous); } public function getJson(): string diff --git a/src/Value/EncodedJson/NodeValueFactory.php b/src/Value/EncodedJson/NodeValueFactory.php index d94119c..1b8a1d8 100644 --- a/src/Value/EncodedJson/NodeValueFactory.php +++ b/src/Value/EncodedJson/NodeValueFactory.php @@ -21,7 +21,7 @@ public static function create(): NodeValueFactoryInterface } public function __construct( - private DecodedJson\NodeValueFactoryInterface $decodedJsonNodeValueFactory, + private readonly DecodedJson\NodeValueFactoryInterface $decodedJsonNodeValueFactory, ) { } diff --git a/src/Walker/Exception/UnexpectedEntityException.php b/src/Walker/Exception/UnexpectedEntityException.php index 4b8deb1..15daff8 100644 --- a/src/Walker/Exception/UnexpectedEntityException.php +++ b/src/Walker/Exception/UnexpectedEntityException.php @@ -10,10 +10,10 @@ final class UnexpectedEntityException extends LogicException implements ExceptionInterface { public function __construct( - private mixed $entity, + private readonly mixed $entity, ?Throwable $previous = null, ) { - parent::__construct("Invalid entity", 0, $previous); + parent::__construct("Invalid entity", previous: $previous); } public function getEntity(): mixed diff --git a/tests/Comparator/ContainsValueComparatorTest.php b/tests/Comparator/ContainsValueComparatorTest.php index 6f1553f..53c064e 100644 --- a/tests/Comparator/ContainsValueComparatorTest.php +++ b/tests/Comparator/ContainsValueComparatorTest.php @@ -6,6 +6,8 @@ use Collator; use Generator; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Comparator\ContainsValueComparator; use Remorhaz\JSON\Data\Value\EncodedJson\NodeValueFactory; @@ -13,23 +15,17 @@ use Remorhaz\JSON\Data\Value\ScalarValueInterface; use Remorhaz\JSON\Data\Value\ValueInterface; -/** - * @covers \Remorhaz\JSON\Data\Comparator\ContainsValueComparator - */ +#[CoversClass(ContainsValueComparator::class)] class ContainsValueComparatorTest extends TestCase { - /** - * @param string $data - * @param string $containedData - * @dataProvider providerMatchingValues - */ + #[DataProvider('providerMatchingValues')] public function testCompare_MatchingValues_ReturnsTrue(string $data, string $containedData): void { $comparator = new ContainsValueComparator(new Collator('UTF-8')); $nodeValueFactory = NodeValueFactory::create(); $actualValue = $comparator->compare( $nodeValueFactory->createValue($data), - $nodeValueFactory->createValue($containedData) + $nodeValueFactory->createValue($containedData), ); self::assertTrue($actualValue); } @@ -58,18 +54,14 @@ public static function providerMatchingValues(): iterable ]; } - /** - * @param string $data - * @param string $containedData - * @dataProvider providerNonMatchingValues - */ + #[DataProvider('providerNonMatchingValues')] public function testCompare_NonMatchingValues_ReturnsFalse(string $data, string $containedData): void { $comparator = new ContainsValueComparator(new Collator('UTF-8')); $nodeValueFactory = NodeValueFactory::create(); $actualValue = $comparator->compare( $nodeValueFactory->createValue($data), - $nodeValueFactory->createValue($containedData) + $nodeValueFactory->createValue($containedData), ); self::assertFalse($actualValue); } @@ -95,7 +87,7 @@ public static function providerNonMatchingValues(): iterable public function testCompare_DuplicatedPropertyInLeftValue_ReturnsFalse(): void { $comparator = new ContainsValueComparator(new Collator('UTF-8')); - $value = $this->createMock(ScalarValueInterface::class); + $value = self::createStub(ScalarValueInterface::class); $value ->method('getData') ->willReturn('b'); @@ -109,7 +101,7 @@ public function testCompare_DuplicatedPropertyInRightValue_ReturnsFalse(): void { $comparator = new ContainsValueComparator(new Collator('UTF-8')); $leftValue = NodeValueFactory::create()->createValue('{"a":"b"}'); - $value = $this->createMock(ScalarValueInterface::class); + $value = self::createStub(ScalarValueInterface::class); $value ->method('getData') ->willReturn('b'); @@ -120,7 +112,7 @@ public function testCompare_DuplicatedPropertyInRightValue_ReturnsFalse(): void private function createObjectWithDuplicatedProperty(string $name, ValueInterface $value): ValueInterface { - $object = $this->createMock(ObjectValueInterface::class); + $object = self::createStub(ObjectValueInterface::class); $generator = function () use ($name, $value): Generator { yield $name => $value; yield $name => $value; diff --git a/tests/Comparator/EqualValueComparatorTest.php b/tests/Comparator/EqualValueComparatorTest.php index a3d0b09..850aef9 100644 --- a/tests/Comparator/EqualValueComparatorTest.php +++ b/tests/Comparator/EqualValueComparatorTest.php @@ -6,6 +6,8 @@ use Collator; use Generator; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Comparator\EqualValueComparator; use Remorhaz\JSON\Data\Value\EncodedJson\NodeValueFactory; @@ -13,27 +15,24 @@ use Remorhaz\JSON\Data\Value\ScalarValueInterface; use Remorhaz\JSON\Data\Value\ValueInterface; -/** - * @covers \Remorhaz\JSON\Data\Comparator\EqualValueComparator - */ +#[CoversClass(EqualValueComparator::class)] class EqualValueComparatorTest extends TestCase { - /** - * @param string $data - * @param string $equalData - * @dataProvider providerMatchingValues - */ + #[DataProvider('providerMatchingValues')] public function testCompare_MatchingValues_ReturnsTrue(string $data, string $equalData): void { $comparator = new EqualValueComparator(new Collator('UTF-8')); $nodeValueFactory = NodeValueFactory::create(); $actualValue = $comparator->compare( $nodeValueFactory->createValue($data), - $nodeValueFactory->createValue($equalData) + $nodeValueFactory->createValue($equalData), ); self::assertTrue($actualValue); } + /** + * @return iterable + */ public static function providerMatchingValues(): iterable { return [ @@ -50,23 +49,22 @@ public static function providerMatchingValues(): iterable ]; } - /** - * @param string $data - * @param string $equalData - * @dataProvider providerNonMatchingValues - */ + #[DataProvider('providerNonMatchingValues')] public function testCompare_NonMatchingValues_ReturnsFalse(string $data, string $equalData): void { $comparator = new EqualValueComparator(new Collator('UTF-8')); $nodeValueFactory = NodeValueFactory::create(); $actualValue = $comparator->compare( $nodeValueFactory->createValue($data), - $nodeValueFactory->createValue($equalData) + $nodeValueFactory->createValue($equalData), ); self::assertFalse($actualValue); } - public function providerNonMatchingValues(): array + /** + * @return iterable + */ + public static function providerNonMatchingValues(): iterable { return [ 'Array and scalar' => ['["a"]', '"a"'], @@ -85,7 +83,7 @@ public function providerNonMatchingValues(): array public function testCompare_DuplicatedPropertyInLeftValue_ReturnsFalse(): void { $comparator = new EqualValueComparator(new Collator('UTF-8')); - $value = $this->createMock(ScalarValueInterface::class); + $value = self::createStub(ScalarValueInterface::class); $value ->method('getData') ->willReturn('b'); @@ -99,7 +97,7 @@ public function testCompare_DuplicatedPropertyInRightValue_ReturnsFalse(): void { $comparator = new EqualValueComparator(new Collator('UTF-8')); $leftValue = NodeValueFactory::create()->createValue('{"a":"b"}'); - $value = $this->createMock(ScalarValueInterface::class); + $value = self::createStub(ScalarValueInterface::class); $value ->method('getData') ->willReturn('b'); @@ -110,7 +108,7 @@ public function testCompare_DuplicatedPropertyInRightValue_ReturnsFalse(): void private function createObjectWithDuplicatedProperty(string $name, ValueInterface $value): ValueInterface { - $object = $this->createMock(ObjectValueInterface::class); + $object = self::createStub(ObjectValueInterface::class); $generator = function () use ($name, $value): Generator { yield $name => $value; yield $name => $value; diff --git a/tests/Comparator/GreaterValueComparatorTest.php b/tests/Comparator/GreaterValueComparatorTest.php index 34cb5bb..9644d02 100644 --- a/tests/Comparator/GreaterValueComparatorTest.php +++ b/tests/Comparator/GreaterValueComparatorTest.php @@ -5,32 +5,31 @@ namespace Remorhaz\JSON\Data\Test\Comparator; use Collator; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Comparator\GreaterValueComparator; use Remorhaz\JSON\Data\Value\EncodedJson\NodeValueFactory; -/** - * @covers \Remorhaz\JSON\Data\Comparator\GreaterValueComparator - */ +#[CoversClass(GreaterValueComparator::class)] class GreaterValueComparatorTest extends TestCase { - /** - * @param string $leftData - * @param string $rightData - * @dataProvider providerMatchingValues - */ + #[DataProvider('providerMatchingValues')] public function testCompare_MatchingValues_ReturnsTrue(string $leftData, string $rightData): void { $comparator = new GreaterValueComparator(new Collator('UTF-8')); $nodeValueFactory = NodeValueFactory::create(); $actualValue = $comparator->compare( $nodeValueFactory->createValue($leftData), - $nodeValueFactory->createValue($rightData) + $nodeValueFactory->createValue($rightData), ); self::assertTrue($actualValue); } - public function providerMatchingValues(): array + /** + * @return iterable + */ + public static function providerMatchingValues(): iterable { return [ 'Left string is greater' => ['"b"', '"a"'], @@ -40,23 +39,22 @@ public function providerMatchingValues(): array ]; } - /** - * @param string $leftData - * @param string $rightData - * @dataProvider providerNonMatchingValues - */ + #[DataProvider('providerNonMatchingValues')] public function testCompare_NonMatchingValues_ReturnsFalse(string $leftData, string $rightData): void { $comparator = new GreaterValueComparator(new Collator('UTF-8')); $nodeValueFactory = NodeValueFactory::create(); $actualValue = $comparator->compare( $nodeValueFactory->createValue($leftData), - $nodeValueFactory->createValue($rightData) + $nodeValueFactory->createValue($rightData), ); self::assertFalse($actualValue); } - public function providerNonMatchingValues(): array + /** + * @return iterable + */ + public static function providerNonMatchingValues(): iterable { return [ 'Same string' => ['"a"', '"b"'], diff --git a/tests/Event/AfterArrayEventTest.php b/tests/Event/AfterArrayEventTest.php index 5a99ccb..0695b3d 100644 --- a/tests/Event/AfterArrayEventTest.php +++ b/tests/Event/AfterArrayEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\AfterArrayEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\AfterArrayEvent - */ +#[CoversClass(AfterArrayEvent::class)] class AfterArrayEventTest extends TestCase { public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void diff --git a/tests/Event/AfterElementEventTest.php b/tests/Event/AfterElementEventTest.php index 39eefc9..03b9569 100644 --- a/tests/Event/AfterElementEventTest.php +++ b/tests/Event/AfterElementEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\AfterElementEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\AfterElementEvent - */ +#[CoversClass(AfterElementEvent::class)] class AfterElementEventTest extends TestCase { public function testGetIndex_ConstructedWithIndex_ReturnsSameIndex(): void diff --git a/tests/Event/AfterObjectEventTest.php b/tests/Event/AfterObjectEventTest.php index fbac171..1729442 100644 --- a/tests/Event/AfterObjectEventTest.php +++ b/tests/Event/AfterObjectEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\AfterObjectEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\AfterObjectEvent - */ +#[CoversClass(AfterObjectEvent::class)] class AfterObjectEventTest extends TestCase { public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void diff --git a/tests/Event/AfterPropertyEventTest.php b/tests/Event/AfterPropertyEventTest.php index 383e78b..690033b 100644 --- a/tests/Event/AfterPropertyEventTest.php +++ b/tests/Event/AfterPropertyEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\AfterPropertyEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\AfterPropertyEvent - */ +#[CoversClass(AfterPropertyEvent::class)] class AfterPropertyEventTest extends TestCase { public function testGetName_ConstructedWithName_ReturnsSameIndex(): void diff --git a/tests/Event/BeforeArrayEventTest.php b/tests/Event/BeforeArrayEventTest.php index 37973ab..091605f 100644 --- a/tests/Event/BeforeArrayEventTest.php +++ b/tests/Event/BeforeArrayEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\BeforeArrayEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\BeforeArrayEvent - */ +#[CoversClass(BeforeArrayEvent::class)] class BeforeArrayEventTest extends TestCase { public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void diff --git a/tests/Event/BeforeElementEventTest.php b/tests/Event/BeforeElementEventTest.php index df74982..8727e1e 100644 --- a/tests/Event/BeforeElementEventTest.php +++ b/tests/Event/BeforeElementEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\BeforeElementEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\BeforeElementEvent - */ +#[CoversClass(BeforeElementEvent::class)] class BeforeElementEventTest extends TestCase { public function testGetIndex_ConstructedWithIndex_ReturnsSameIndex(): void diff --git a/tests/Event/BeforeObjectEventTest.php b/tests/Event/BeforeObjectEventTest.php index 7b4a86b..cc5abe6 100644 --- a/tests/Event/BeforeObjectEventTest.php +++ b/tests/Event/BeforeObjectEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\BeforeObjectEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\BeforeObjectEvent - */ +#[CoversClass(BeforeObjectEvent::class)] class BeforeObjectEventTest extends TestCase { public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void diff --git a/tests/Event/BeforePropertyEventTest.php b/tests/Event/BeforePropertyEventTest.php index 60b07af..30b1453 100644 --- a/tests/Event/BeforePropertyEventTest.php +++ b/tests/Event/BeforePropertyEventTest.php @@ -4,13 +4,12 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\BeforePropertyEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\BeforePropertyEvent - */ +#[CoversClass(BeforePropertyEvent::class)] class BeforePropertyEventTest extends TestCase { public function testGetName_ConstructedWithName_ReturnsSameIndex(): void diff --git a/tests/Event/Exception/InvalidScalarDataExceptionTest.php b/tests/Event/Exception/InvalidScalarDataExceptionTest.php index 96317b9..3922fc4 100644 --- a/tests/Event/Exception/InvalidScalarDataExceptionTest.php +++ b/tests/Event/Exception/InvalidScalarDataExceptionTest.php @@ -5,12 +5,11 @@ namespace Remorhaz\JSON\Data\Test\Event\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\Exception\InvalidScalarDataException; -/** - * @covers \Remorhaz\JSON\Data\Event\Exception\InvalidScalarDataException - */ +#[CoversClass(InvalidScalarDataException::class)] class InvalidScalarDataExceptionTest extends TestCase { public function testGetMessage_Constructed_ReturnsMatchingValue(): void @@ -25,15 +24,9 @@ public function testGetData_ConstructedWithData_ReturnsSameValue(): void self::assertSame('a', $exception->getData()); } - public function testGetCode_Always_ReturnsZero(): void - { - $exception = new InvalidScalarDataException(null); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { - $exception = new InvalidScalarDataException(null); + $exception = new InvalidScalarDataException(1); self::assertNull($exception->getPrevious()); } diff --git a/tests/Event/ScalarEventTest.php b/tests/Event/ScalarEventTest.php index 18c0129..09b02b5 100644 --- a/tests/Event/ScalarEventTest.php +++ b/tests/Event/ScalarEventTest.php @@ -4,14 +4,14 @@ namespace Remorhaz\JSON\Data\Test\Event; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\Exception\InvalidScalarDataException; use Remorhaz\JSON\Data\Event\ScalarEvent; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Event\ScalarEvent - */ +#[CoversClass(ScalarEvent::class)] class ScalarEventTest extends TestCase { public function testConstruct_NonScalarData_ThrowsException(): void @@ -20,9 +20,7 @@ public function testConstruct_NonScalarData_ThrowsException(): void new ScalarEvent([], new Path()); } - /** - * @dataProvider providerGetData - */ + #[DataProvider('providerGetData')] public function testGetData_ConstructedWithScalarData_ReturnsSameValue(mixed $data, mixed $expectedValue): void { $event = new ScalarEvent($data, new Path()); diff --git a/tests/Export/Exception/EncodingFailedExceptionTest.php b/tests/Export/Exception/EncodingFailedExceptionTest.php index 908babb..1244da1 100644 --- a/tests/Export/Exception/EncodingFailedExceptionTest.php +++ b/tests/Export/Exception/EncodingFailedExceptionTest.php @@ -5,12 +5,11 @@ namespace Remorhaz\JSON\Data\Test\Export\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Export\Exception\EncodingFailedException; -/** - * @covers \Remorhaz\JSON\Data\Export\Exception\EncodingFailedException - */ +#[CoversClass(EncodingFailedException::class)] class EncodingFailedExceptionTest extends TestCase { public function testGetMessage_Constructed_ReturnsMatchingValue(): void @@ -25,12 +24,6 @@ public function testGetData_ConstructedWithData_ReturnsSameValue(): void self::assertSame('a', $exception->getData()); } - public function testGetCode_Always_ReturnsZero(): void - { - $exception = new EncodingFailedException('a'); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { $exception = new EncodingFailedException('a'); diff --git a/tests/Export/Exception/NoValueToExportExceptionTest.php b/tests/Export/Exception/NoValueToExportExceptionTest.php index 068afe7..fe1aa0d 100644 --- a/tests/Export/Exception/NoValueToExportExceptionTest.php +++ b/tests/Export/Exception/NoValueToExportExceptionTest.php @@ -5,12 +5,11 @@ namespace Remorhaz\JSON\Data\Test\Export\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Export\Exception\NoValueToExportException; -/** - * @covers \Remorhaz\JSON\Data\Export\Exception\NoValueToExportException - */ +#[CoversClass(NoValueToExportException::class)] class NoValueToExportExceptionTest extends TestCase { public function testGetMessage_Constructed_ReturnsMatchingValue(): void diff --git a/tests/Export/Exception/UnexpectedValueExceptionTest.php b/tests/Export/Exception/UnexpectedValueExceptionTest.php index b9be11f..51ecbce 100644 --- a/tests/Export/Exception/UnexpectedValueExceptionTest.php +++ b/tests/Export/Exception/UnexpectedValueExceptionTest.php @@ -5,37 +5,30 @@ namespace Remorhaz\JSON\Data\Test\Export\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Export\Exception\UnexpectedValueException; use Remorhaz\JSON\Data\Value\ValueInterface; -/** - * @covers \Remorhaz\JSON\Data\Export\Exception\UnexpectedValueException - */ +#[CoversClass(UnexpectedValueException::class)] class UnexpectedValueExceptionTest extends TestCase { public function testGetMessage_Constructed_ReturnsMatchingValue(): void { - $exception = new UnexpectedValueException($this->createMock(ValueInterface::class)); + $exception = new UnexpectedValueException(self::createStub(ValueInterface::class)); self::assertSame('Unexpected value', $exception->getMessage()); } public function testGetValue_ConstructedWithData_ReturnsSameValue(): void { - $value = $this->createMock(ValueInterface::class); + $value = self::createStub(ValueInterface::class); $exception = new UnexpectedValueException($value); self::assertSame($value, $exception->getValue()); } - public function testGetCode_Always_ReturnsZero(): void - { - $exception = new UnexpectedValueException($this->createMock(ValueInterface::class)); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { - $exception = new UnexpectedValueException($this->createMock(ValueInterface::class)); + $exception = new UnexpectedValueException(self::createStub(ValueInterface::class)); self::assertNull($exception->getPrevious()); } @@ -43,7 +36,7 @@ public function testGetPrevious_ConstructedWithPrevious_ReturnsSameInstance(): v { $previous = new Exception(); $exception = new UnexpectedValueException( - $this->createMock(ValueInterface::class), + self::createStub(ValueInterface::class), $previous, ); self::assertSame($previous, $exception->getPrevious()); diff --git a/tests/Export/Exception/UnknownEventExceptionTest.php b/tests/Export/Exception/UnknownEventExceptionTest.php index 9fe43bb..24cd99b 100644 --- a/tests/Export/Exception/UnknownEventExceptionTest.php +++ b/tests/Export/Exception/UnknownEventExceptionTest.php @@ -5,37 +5,30 @@ namespace Remorhaz\JSON\Data\Test\Export\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Event\EventInterface; use Remorhaz\JSON\Data\Export\Exception\UnknownEventException; -/** - * @covers \Remorhaz\JSON\Data\Export\Exception\UnknownEventException - */ +#[CoversClass(UnknownEventException::class)] class UnknownEventExceptionTest extends TestCase { public function testGetMessage_Constructed_ReturnsMatchingValue(): void { - $exception = new UnknownEventException($this->createMock(EventInterface::class)); + $exception = new UnknownEventException(self::createStub(EventInterface::class)); self::assertSame('Unknown event', $exception->getMessage()); } public function testGetEvent_ConstructedWithData_ReturnsSameValue(): void { - $event = $this->createMock(EventInterface::class); + $event = self::createStub(EventInterface::class); $exception = new UnknownEventException($event); self::assertSame($event, $exception->getEvent()); } - public function testGetCode_Always_ReturnsZero(): void - { - $exception = new UnknownEventException($this->createMock(EventInterface::class)); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { - $exception = new UnknownEventException($this->createMock(EventInterface::class)); + $exception = new UnknownEventException(self::createStub(EventInterface::class)); self::assertNull($exception->getPrevious()); } @@ -43,7 +36,7 @@ public function testGetPrevious_ConstructedWithPrevious_ReturnsSameInstance(): v { $previous = new Exception(); $exception = new UnknownEventException( - $this->createMock(EventInterface::class), + self::createStub(EventInterface::class), $previous, ); self::assertSame($previous, $exception->getPrevious()); diff --git a/tests/Path/Exception/ParentNotFoundExceptionTest.php b/tests/Path/Exception/ParentNotFoundExceptionTest.php index 3a400bc..481558f 100644 --- a/tests/Path/Exception/ParentNotFoundExceptionTest.php +++ b/tests/Path/Exception/ParentNotFoundExceptionTest.php @@ -5,13 +5,13 @@ namespace Remorhaz\JSON\Data\Test\Path\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Path\Exception\ParentNotFoundException; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Path\Exception\ParentNotFoundException - */ +#[CoversClass(ParentNotFoundException::class)] class ParentNotFoundExceptionTest extends TestCase { public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void @@ -24,8 +24,8 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void /** * @param list $pathElements * @param string $expectedValue - * @dataProvider providerGetMessage */ + #[DataProvider('providerGetMessage')] public function testGetMessage(array $pathElements, string $expectedValue): void { $path = new Path(...$pathElements); @@ -44,12 +44,6 @@ public static function providerGetMessage(): iterable ]; } - public function testGetCode_Always_ReturnsZero(): void - { - $exception = new ParentNotFoundException(new Path()); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { $exception = new ParentNotFoundException(new Path()); diff --git a/tests/Path/PathTest.php b/tests/Path/PathTest.php index c36e232..1bbd1e9 100644 --- a/tests/Path/PathTest.php +++ b/tests/Path/PathTest.php @@ -4,13 +4,13 @@ namespace Remorhaz\JSON\Data\Test\Path; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Path\Exception\ParentNotFoundException; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Path\Path - */ +#[CoversClass(Path::class)] class PathTest extends TestCase { public function testGetElements_ConstructedWithGivenElements_ReturnsSameValues(): void @@ -46,8 +46,8 @@ public function testCopyWithProperty_Constructed_ResultContainsMatchingElements( /** * @param list $firstElements * @param list $secondElements - * @dataProvider providerEquals */ + #[DataProvider('providerEquals')] public function testEquals_EqualPath_ReturnsTrue(array $firstElements, array $secondElements): void { $firstPath = new Path(...$firstElements); @@ -70,8 +70,8 @@ public static function providerEquals(): iterable /** * @param list $firstElements * @param list $secondElements - * @dataProvider providerNotEquals */ + #[DataProvider('providerNotEquals')] public function testEquals_NotEqualPath_ReturnsFalse(array $firstElements, array $secondElements): void { $firstPath = new Path(...$firstElements); @@ -94,8 +94,8 @@ public static function providerNotEquals(): iterable /** * @param list $pathElements * @param list $containedPathElements - * @dataProvider providerContains */ + #[DataProvider('providerContains')] public function testContains_ContainedPath_ReturnsTrue(array $pathElements, array $containedPathElements): void { $path = new Path(...$pathElements); @@ -122,10 +122,10 @@ public function testCopyParent_NonEmptyPath_ReturnsNewInstance(): void } /** - * @dataProvider providerCopyExistingParent * @param list $pathElements * @param list $expectedElements */ + #[DataProvider('providerCopyExistingParent')] public function testCopyParent_NonEmptyPath_ReturnsMatchingPath(array $pathElements, array $expectedElements): void { $path = new Path(...$pathElements); diff --git a/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php b/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php index 4b6c455..8221dbb 100644 --- a/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php +++ b/tests/Value/DecodedJson/Exception/InvalidElementKeyExceptionTest.php @@ -5,21 +5,21 @@ namespace Remorhaz\JSON\Data\Test\Value\DecodedJson; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Value\DecodedJson\Exception\InvalidElementKeyException; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Value\DecodedJson\Exception\InvalidElementKeyException - */ +#[CoversClass(InvalidElementKeyException::class)] class InvalidElementKeyExceptionTest extends TestCase { /** * @param mixed $key * @param list $pathElements * @param string $expectedValue - * @dataProvider providerKeyMessage */ + #[DataProvider('providerKeyMessage')] public function testGetMessage_Constructed_ReturnsMatchingValue( mixed $key, array $pathElements, @@ -49,9 +49,7 @@ public function testGetPath_ConstructedWithGivenPath_ReturnsSameInstance(): void self::assertSame($path, $exception->getPath()); } - /** - * @dataProvider providerKey - */ + #[DataProvider('providerKey')] public function testGetKey_ConstructedWithGivenKey_ReturnsSameValue(mixed $key, mixed $expectedValue): void { $exception = new InvalidElementKeyException($key, new Path()); @@ -69,12 +67,6 @@ public static function providerKey(): iterable ]; } - public function testGetCode_Always_ReturnZero(): void - { - $exception = new InvalidElementKeyException(0, new Path()); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { $exception = new InvalidElementKeyException(0, new Path()); diff --git a/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php b/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php index ca3282f..36304f6 100644 --- a/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php +++ b/tests/Value/DecodedJson/Exception/InvalidNodeDataExceptionTest.php @@ -5,20 +5,20 @@ namespace Remorhaz\JSON\Data\Test\Value\DecodedJson\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Value\DecodedJson\Exception\InvalidNodeDataException; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Value\DecodedJson\Exception\InvalidNodeDataException - */ +#[CoversClass(InvalidNodeDataException::class)] class InvalidNodeDataExceptionTest extends TestCase { /** * @param list $elements * @param string $expectedValue - * @dataProvider providerGetMessage */ + #[DataProvider('providerGetMessage')] public function testGetMessage_Constructed_ReturnsMatchingValue(array $elements, string $expectedValue): void { $exception = new InvalidNodeDataException(null, new Path(...$elements)); @@ -50,12 +50,6 @@ public function testGetPath_ConstructedWithGivenPath_ReturnsSameInstance(): void self::assertSame($path, $exception->getPath()); } - public function testGetCode_Always_ReturnZero(): void - { - $exception = new InvalidNodeDataException(0, new Path()); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { $exception = new InvalidNodeDataException(0, new Path()); diff --git a/tests/Value/DecodedJson/NodeArrayValueTest.php b/tests/Value/DecodedJson/NodeArrayValueTest.php index 228c4a0..a3a35ef 100644 --- a/tests/Value/DecodedJson/NodeArrayValueTest.php +++ b/tests/Value/DecodedJson/NodeArrayValueTest.php @@ -4,7 +4,8 @@ namespace Remorhaz\JSON\Data\Test\Value\DecodedJson; -use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use Remorhaz\JSON\Data\Path\PathInterface; use Remorhaz\JSON\Data\Value\DecodedJson\NodeValueFactoryInterface; use Remorhaz\JSON\Data\Value\NodeValueInterface; @@ -16,14 +17,10 @@ use function iterator_to_array; -/** - * @covers \Remorhaz\JSON\Data\Value\DecodedJson\NodeArrayValue - */ +#[CoversClass(NodeArrayValue::class)] class NodeArrayValueTest extends TestCase { - /** - * @dataProvider providerArrayWithInvalidIndex - */ + #[DataProvider('providerArrayWithInvalidIndex')] public function testCreateChildIterator_ArrayDataWithInvalidIndex_ThrowsException(array $data): void { $value = new NodeArrayValue($data, new Path(), NodeValueFactory::create()); @@ -52,7 +49,7 @@ public function testCreateChildIterator_EmptyArrayData_ReturnsEmptyIterator(): v public function testCreateChildIterator_NotEmptyArrayData_CallsFactoryForEachElement(): void { - $nodeValueFactory = $this->createMock(NodeValueFactoryInterface::class); + $nodeValueFactory = self::createStub(NodeValueFactoryInterface::class); $value = new NodeArrayValue(['a', 1], new Path('b'), $nodeValueFactory); $interceptedArguments = []; @@ -63,7 +60,7 @@ function (mixed $data, ?PathInterface $path) use (&$interceptedArguments): NodeV /** @psalm-var array $interceptedArguments */ $interceptedArguments[] = [$data, $path?->getElements() ?? []]; - return $this->createStub(NodeValueInterface::class); + return self::createStub(NodeValueInterface::class); } ); iterator_to_array($value->createChildIterator(), true); @@ -74,22 +71,13 @@ function (mixed $data, ?PathInterface $path) use (&$interceptedArguments): NodeV self::assertSame($expectedValue, $interceptedArguments); } - private function isArgEqualPath(int|string ...$elements): Callback - { - $callback = function (PathInterface $path) use ($elements): bool { - return $path->equals(new Path(...$elements)); - }; - - return self::callback($callback); - } - public function testCreateChildIterator_NodeFactoryReturnsValues_ReturnsSameValuesWithMatchingIndexes(): void { - $nodeValueFactory = $this->createMock(NodeValueFactoryInterface::class); + $nodeValueFactory = self::createStub(NodeValueFactoryInterface::class); $value = new NodeArrayValue(['a', 1], new Path('b'), $nodeValueFactory); - $firstNode = $this->createMock(NodeValueInterface::class); - $secondNode = $this->createMock(NodeValueInterface::class); + $firstNode = self::createStub(NodeValueInterface::class); + $secondNode = self::createStub(NodeValueInterface::class); $nodeValueFactory ->method('createValue') ->willReturnOnConsecutiveCalls($firstNode, $secondNode); diff --git a/tests/Value/DecodedJson/NodeObjectValueTest.php b/tests/Value/DecodedJson/NodeObjectValueTest.php index 58a6ccc..829f0c9 100644 --- a/tests/Value/DecodedJson/NodeObjectValueTest.php +++ b/tests/Value/DecodedJson/NodeObjectValueTest.php @@ -4,7 +4,7 @@ namespace Remorhaz\JSON\Data\Test\Value\DecodedJson; -use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\Attributes\CoversClass; use Remorhaz\JSON\Data\Path\PathInterface; use Remorhaz\JSON\Data\Value\DecodedJson\NodeObjectValue; use Remorhaz\JSON\Data\Value\DecodedJson\NodeValueFactoryInterface; @@ -15,9 +15,7 @@ use function iterator_to_array; -/** - * @covers \Remorhaz\JSON\Data\Value\DecodedJson\NodeObjectValue - */ +#[CoversClass(NodeObjectValue::class)] class NodeObjectValueTest extends TestCase { public function testCreateChildIterator_EmptyObjectData_ReturnsEmptyIterator(): void @@ -29,7 +27,7 @@ public function testCreateChildIterator_EmptyObjectData_ReturnsEmptyIterator(): public function testCreateChildIterator_NotEmptyObjectData_CallsFactoryForEachElement(): void { - $nodeValueFactory = $this->createStub(NodeValueFactoryInterface::class); + $nodeValueFactory = self::createStub(NodeValueFactoryInterface::class); $value = new NodeObjectValue((object) ['a' => 'b', 'c' => 1], new Path('d'), $nodeValueFactory); $interceptedArgs = []; @@ -40,7 +38,7 @@ function (mixed $data, ?PathInterface $path) use (&$interceptedArgs): NodeValueI /** @psalm-var array $interceptedArgs */ $interceptedArgs[] = [$data, $path?->getElements() ?? []]; - return $this->createStub(NodeValueInterface::class); + return self::createStub(NodeValueInterface::class); }, ); iterator_to_array($value->createChildIterator(), true); @@ -51,20 +49,13 @@ function (mixed $data, ?PathInterface $path) use (&$interceptedArgs): NodeValueI self::assertSame($expectedValue, $interceptedArgs); } - private static function isArgEqualPath(...$elements): Callback - { - return self::callback( - fn (PathInterface $path): bool => $path->equals(new Path(...$elements)), - ); - } - public function testCreateChildIterator_NodeFactoryReturnsValues_ReturnsSameValuesWithMatchingIndexes(): void { - $nodeValueFactory = $this->createMock(NodeValueFactoryInterface::class); + $nodeValueFactory = self::createStub(NodeValueFactoryInterface::class); $value = new NodeObjectValue((object) ['a' => 'b', 'c' => 1], new Path('d'), $nodeValueFactory); - $firstNode = $this->createMock(NodeValueInterface::class); - $secondNode = $this->createMock(NodeValueInterface::class); + $firstNode = self::createStub(NodeValueInterface::class); + $secondNode = self::createStub(NodeValueInterface::class); $nodeValueFactory ->method('createValue') ->willReturnOnConsecutiveCalls($firstNode, $secondNode); diff --git a/tests/Value/DecodedJson/NodeScalarValueTest.php b/tests/Value/DecodedJson/NodeScalarValueTest.php index 40edc9c..6e5d993 100644 --- a/tests/Value/DecodedJson/NodeScalarValueTest.php +++ b/tests/Value/DecodedJson/NodeScalarValueTest.php @@ -4,19 +4,17 @@ namespace Remorhaz\JSON\Data\Test\Value\DecodedJson; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Value\DecodedJson\NodeScalarValue; use Remorhaz\JSON\Data\Value\DecodedJson\Exception\InvalidNodeDataException; use Remorhaz\JSON\Data\Path\Path; -/** - * @covers \Remorhaz\JSON\Data\Value\DecodedJson\NodeScalarValue - */ +#[CoversClass(NodeScalarValue::class)] class NodeScalarValueTest extends TestCase { - /** - * @dataProvider providerInvalidData - */ + #[DataProvider('providerInvalidData')] public function testConstruct_InvalidData_ThrowsMatchingException(mixed $data): void { $this->expectException(InvalidNodeDataException::class); diff --git a/tests/Value/DecodedJson/NodeValueFactoryTest.php b/tests/Value/DecodedJson/NodeValueFactoryTest.php index 0b8287f..8385f6d 100644 --- a/tests/Value/DecodedJson/NodeValueFactoryTest.php +++ b/tests/Value/DecodedJson/NodeValueFactoryTest.php @@ -4,6 +4,8 @@ namespace Remorhaz\JSON\Data\Test\Value\DecodedJson; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Value\DecodedJson\Exception\InvalidNodeDataException; use Remorhaz\JSON\Data\Value\DecodedJson\NodeArrayValue; @@ -15,14 +17,10 @@ use const STDOUT; -/** - * @covers \Remorhaz\JSON\Data\Value\DecodedJson\NodeValueFactory - */ +#[CoversClass(NodeValueFactory::class)] class NodeValueFactoryTest extends TestCase { - /** - * @dataProvider providerScalarDataOrNull - */ + #[DataProvider('providerScalarDataOrNull')] public function testCreateValue_ScalarDataOrNull_ReturnsNodeScalarValue(mixed $data): void { $actualValue = NodeValueFactory::create()->createValue($data, new Path()); @@ -43,9 +41,7 @@ public static function providerScalarDataOrNull(): iterable ]; } - /** - * @dataProvider providerScalarDataOrNull - */ + #[DataProvider('providerScalarDataOrNull')] public function testCreateValue_ScalarValueAndGivenPath_ResultHasSamePathInstance(mixed $data): void { $path = new Path(); @@ -53,18 +49,14 @@ public function testCreateValue_ScalarValueAndGivenPath_ResultHasSamePathInstanc self::assertSame($path, $actualValue->getPath()); } - /** - * @dataProvider providerScalarDataOrNull - */ + #[DataProvider('providerScalarDataOrNull')] public function testCreateValue_ScalarValueAndNoPath_ResultHasEmptyPath(mixed $data): void { $actualValue = NodeValueFactory::create()->createValue($data); self::assertEmpty($actualValue->getPath()->getElements()); } - /** - * @dataProvider providerScalarDataOrNull - */ + #[DataProvider('providerScalarDataOrNull')] public function testCreateValue_ScalarValue_ResultHasMatchingData(mixed $data, mixed $expectedValue): void { $path = new Path(); diff --git a/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php b/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php index 8d65a6c..c339188 100644 --- a/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php +++ b/tests/Value/EncodedJson/Exception/JsonNotDecodedExceptionTest.php @@ -5,12 +5,11 @@ namespace Remorhaz\JSON\Data\Test\Value\EncodedJson\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Value\EncodedJson\Exception\JsonNotDecodedException; -/** - * @covers \Remorhaz\JSON\Data\Value\EncodedJson\Exception\JsonNotDecodedException - */ +#[CoversClass(JsonNotDecodedException::class)] class JsonNotDecodedExceptionTest extends TestCase { public function testGetMessage_Constructed_ReturnsMatchingValue(): void @@ -25,12 +24,6 @@ public function testGetJson_ConstructedWithJson_ReturnsSameValue(): void self::assertSame('a', $exception->getJson()); } - public function testGetCode_Always_ReturnsZero(): void - { - $exception = new JsonNotDecodedException('a'); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { $exception = new JsonNotDecodedException('a'); diff --git a/tests/Value/EncodedJson/NodeValueFactoryTest.php b/tests/Value/EncodedJson/NodeValueFactoryTest.php index 7ac9d7a..27a3edf 100644 --- a/tests/Value/EncodedJson/NodeValueFactoryTest.php +++ b/tests/Value/EncodedJson/NodeValueFactoryTest.php @@ -4,6 +4,7 @@ namespace Remorhaz\JSON\Data\Test\Value\EncodedJson; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Path\Path; use Remorhaz\JSON\Data\Value\DecodedJson\NodeValueFactoryInterface; @@ -11,9 +12,7 @@ use Remorhaz\JSON\Data\Value\EncodedJson\NodeValueFactory; use Remorhaz\JSON\Data\Value\NodeValueInterface; -/** - * @covers \Remorhaz\JSON\Data\Value\EncodedJson\NodeValueFactory - */ +#[CoversClass(NodeValueFactory::class)] class NodeValueFactoryTest extends TestCase { public function testCreate_Always_ReturnsNodeValueInstance(): void @@ -30,7 +29,7 @@ public function testCreateValue_InvalidJson_ThrowsException(): void public function testCreateValue_ValidJsonNoPath_PassesDecodedJsonAndNullToDecodedJsonFactory(): void { - $decodedJsonFactory = $this->createMock(NodeValueFactoryInterface::class); + $decodedJsonFactory = self::createMock(NodeValueFactoryInterface::class); $encodedJsonFactory = new NodeValueFactory($decodedJsonFactory); $decodedJsonFactory @@ -42,7 +41,7 @@ public function testCreateValue_ValidJsonNoPath_PassesDecodedJsonAndNullToDecode public function testCreateValue_ValidJsonWithPath_PassesDecodedJsonAndSamePathInstanceToDecodedJsonFactory(): void { - $decodedJsonFactory = $this->createMock(NodeValueFactoryInterface::class); + $decodedJsonFactory = self::createMock(NodeValueFactoryInterface::class); $encodedJsonFactory = new NodeValueFactory($decodedJsonFactory); $path = new Path(); @@ -55,10 +54,10 @@ public function testCreateValue_ValidJsonWithPath_PassesDecodedJsonAndSamePathIn public function testCreateValue_DecodedJsonFactoryReturnsInstanceReturnsSameInstance(): void { - $decodedJsonFactory = $this->createMock(NodeValueFactoryInterface::class); + $decodedJsonFactory = self::createStub(NodeValueFactoryInterface::class); $encodedJsonFactory = new NodeValueFactory($decodedJsonFactory); - $nodeValue = $this->createMock(NodeValueInterface::class); + $nodeValue = self::createStub(NodeValueInterface::class); $decodedJsonFactory ->method('createValue') ->willReturn($nodeValue); diff --git a/tests/Walker/Exception/UnexpectedEntityExceptionTest.php b/tests/Walker/Exception/UnexpectedEntityExceptionTest.php index 21db604..5049e16 100644 --- a/tests/Walker/Exception/UnexpectedEntityExceptionTest.php +++ b/tests/Walker/Exception/UnexpectedEntityExceptionTest.php @@ -5,12 +5,11 @@ namespace Remorhaz\JSON\Data\Test\Walker\Exception; use Exception; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use Remorhaz\JSON\Data\Walker\Exception\UnexpectedEntityException; -/** - * @covers \Remorhaz\JSON\Data\Walker\Exception\UnexpectedEntityException - */ +#[CoversClass(UnexpectedEntityException::class)] class UnexpectedEntityExceptionTest extends TestCase { public function testGetMessage_Constructed_ReturnsMatchingValue(): void @@ -25,12 +24,6 @@ public function testGetEntity_ConstructedWithEntity_ReturnsSameValue(): void self::assertSame('a', $exception->getEntity()); } - public function testGetCode_Always_ReturnsZero(): void - { - $exception = new UnexpectedEntityException('a'); - self::assertSame(0, $exception->getCode()); - } - public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void { $exception = new UnexpectedEntityException('a'); diff --git a/vendor-bin/cs/composer.json b/vendor-bin/cs/composer.json new file mode 100644 index 0000000..31bfe6e --- /dev/null +++ b/vendor-bin/cs/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "squizlabs/php_codesniffer": "^3.8" + } +} diff --git a/vendor-bin/psalm/composer.json b/vendor-bin/psalm/composer.json new file mode 100644 index 0000000..83fd035 --- /dev/null +++ b/vendor-bin/psalm/composer.json @@ -0,0 +1,9 @@ +{ + "require-dev": { + "vimeo/psalm": "^5.21.1", + "psalm/plugin-phpunit": "^0.18.4" + }, + "conflict": { + "netresearch/jsonmapper": "<4.4.1" + } +} From 4ff9d7c0f3de063435d40162bc4d0d48ab81f2c4 Mon Sep 17 00:00:00 2001 From: remorhaz Date: Sun, 11 Feb 2024 11:40:58 +0200 Subject: [PATCH 5/8] Release 0.6.1 --- CHANGELOG.md | 2 +- src/Walker/EventGenerator.php | 3 +- tests/Walker/EventGeneratorTest.php | 180 ++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 tests/Walker/EventGeneratorTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ecb3f7d..949e135 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.6.1] - 2024-02-11 ### Added - Added PHP 8.3 support. ### Removed diff --git a/src/Walker/EventGenerator.php b/src/Walker/EventGenerator.php index 837c670..543c277 100644 --- a/src/Walker/EventGenerator.php +++ b/src/Walker/EventGenerator.php @@ -4,7 +4,6 @@ namespace Remorhaz\JSON\Data\Walker; -use Generator; use Iterator; use Remorhaz\JSON\Data\Event\AfterArrayEvent; use Remorhaz\JSON\Data\Event\AfterElementEvent; @@ -126,7 +125,7 @@ private function onArrayValue(ArrayValueInterface $value): Iterator $localStack, new BeforeElementEvent($index, $elementPath), $child, - new AfterElementEvent($index, $elementPath) + new AfterElementEvent($index, $elementPath), ); } array_push( diff --git a/tests/Walker/EventGeneratorTest.php b/tests/Walker/EventGeneratorTest.php new file mode 100644 index 0000000..72ad95e --- /dev/null +++ b/tests/Walker/EventGeneratorTest.php @@ -0,0 +1,180 @@ + $expectedEvents + */ + #[DataProvider('providerValueEvents')] + public function testInvoke_ConstructedWithValue_IteratesMatchingEvents(mixed $value, array $expectedEvents): void + { + $nodeFactory = new NodeValueFactory(); + $value = $nodeFactory->createValue($value, new Path(1)); + $generator = new EventGenerator($value, new Path(2)); + $events = iterator_to_array($generator(), false); + self::assertSame($expectedEvents, $this->exportEvents(...$events)); + } + + /** + * @return iterable}> + */ + public static function providerValueEvents(): iterable + { + return [ + 'Scalar value' => [ + 'a', + [ + [ + 'class' => ScalarEvent::class, + 'path' => [2], + 'data' => 'a', + ], + ], + ], + 'Array with two scalars' => [ + ['a', 'b'], + [ + [ + 'class' => BeforeArrayEvent::class, + 'path' => [2], + ], + [ + 'class' => BeforeElementEvent::class, + 'path' => [2, 0], + 'index' => 0, + ], + [ + 'class' => ScalarEvent::class, + 'path' => [2, 0], + 'data' => 'a', + ], + [ + 'class' => AfterElementEvent::class, + 'path' => [2, 0], + 'index' => 0, + ], + [ + 'class' => BeforeElementEvent::class, + 'path' => [2, 1], + 'index' => 1, + ], + [ + 'class' => ScalarEvent::class, + 'path' => [2, 1], + 'data' => 'b', + ], + [ + 'class' => AfterElementEvent::class, + 'path' => [2, 1], + 'index' => 1, + ], + [ + 'class' => AfterArrayEvent::class, + 'path' => [2], + ], + ], + ], + 'Object with two properties' => [ + (object) ['a' => 'b', 'c' => 'd'], + [ + [ + 'class' => BeforeObjectEvent::class, + 'path' => [2], + ], + [ + 'class' => BeforePropertyEvent::class, + 'path' => [2, 'a'], + 'name' => 'a', + ], + [ + 'class' => ScalarEvent::class, + 'path' => [2, 'a'], + 'data' => 'b', + ], + [ + 'class' => AfterPropertyEvent::class, + 'path' => [2, 'a'], + 'name' => 'a', + ], + [ + 'class' => BeforePropertyEvent::class, + 'path' => [2, 'c'], + 'name' => 'c', + ], + [ + 'class' => ScalarEvent::class, + 'path' => [2, 'c'], + 'data' => 'd', + ], + [ + 'class' => AfterPropertyEvent::class, + 'path' => [2, 'c'], + 'name' => 'c', + ], + [ + 'class' => AfterObjectEvent::class, + 'path' => [2], + ], + ], + ], + ]; + } + + private function exportEvents(EventInterface ...$events): array + { + return array_map($this->exportEvent(...), $events); + } + + private function exportEvent(EventInterface $event): array + { + return [ + 'class' => $event::class, + 'path' => $event->getPath()->getElements(), + ...match (true) { + $event instanceof ScalarEventInterface => ['data' => $event->getData()], + $event instanceof ElementEventInterface => ['index' => $event->getIndex()], + $event instanceof PropertyEventInterface => ['name' => $event->getName()], + default => [], + }, + ]; + } + + public function testInvoke_ConstructedWithInvalidValue_ThrowsException(): void + { + $value = self::createStub(NodeValueInterface::class); + $generator = new EventGenerator($value, new Path()); + $this->expectException(UnexpectedEntityException::class); + iterator_to_array($generator()); + } +} From 59fad6890175e65fb7cb5acadd74084af1237217 Mon Sep 17 00:00:00 2001 From: remorhaz Date: Sun, 11 Feb 2024 13:54:24 +0200 Subject: [PATCH 6/8] Fix sending infection report to Stryker dashboard --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5ff14f..8a60024 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,7 +58,7 @@ jobs: - name: Run infection run: composer infection env: - INFECTION_DASHBOARD_API_KEY: ${{ secrets.INFECTION_DASHBOARD_API_KEY }} + STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} - name: Upload coverage to Codecov.io run: bash <(curl -s https://codecov.io/bash -s "build/logs") From 0b02c918ae5dc480247c54ce2a4e5ed917ff910b Mon Sep 17 00:00:00 2001 From: remorhaz Date: Sat, 17 Feb 2024 14:45:51 +0200 Subject: [PATCH 7/8] Cloning setters in events --- CHANGELOG.md | 4 ++ composer.json | 11 +---- php-8.1.Dockerfile | 2 +- php-8.2.Dockerfile | 2 +- php-8.3.Dockerfile | 2 +- src/Event/AfterArrayEvent.php | 7 +++ src/Event/AfterArrayEventInterface.php | 3 ++ src/Event/AfterElementEvent.php | 8 ++++ src/Event/AfterElementEventInterface.php | 3 ++ src/Event/AfterObjectEvent.php | 7 +++ src/Event/AfterObjectEventInterface.php | 3 ++ src/Event/AfterPropertyEvent.php | 8 ++++ src/Event/AfterPropertyEventInterface.php | 3 ++ src/Event/BeforeArrayEvent.php | 7 +++ src/Event/BeforeArrayEventInterface.php | 3 ++ src/Event/BeforeElementEvent.php | 8 ++++ src/Event/BeforeElementEventInterface.php | 3 ++ src/Event/BeforeObjectEvent.php | 7 +++ src/Event/BeforeObjectEventInterface.php | 3 ++ src/Event/BeforePropertyEvent.php | 8 ++++ src/Event/BeforePropertyEventInterface.php | 3 ++ src/Event/ElementEventInterface.php | 4 ++ src/Event/EventInterface.php | 2 + src/Event/PropertyEventInterface.php | 4 ++ src/Event/ScalarEvent.php | 11 +++++ src/Event/ScalarEventInterface.php | 8 ++++ tests/Event/AfterArrayEventTest.php | 23 ++++++++++ tests/Event/AfterElementEventTest.php | 37 ++++++++++++++++ tests/Event/AfterObjectEventTest.php | 23 ++++++++++ tests/Event/AfterPropertyEventTest.php | 37 ++++++++++++++++ tests/Event/BeforeArrayEventTest.php | 24 ++++++++++ tests/Event/BeforeElementEventTest.php | 37 ++++++++++++++++ tests/Event/BeforeObjectEventTest.php | 23 ++++++++++ tests/Event/BeforePropertyEventTest.php | 37 ++++++++++++++++ tests/Event/ScalarEventTest.php | 51 ++++++++++++++++++++++ 35 files changed, 413 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 949e135..62ce1ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Added +- Cloning setters added to events to make stream modification easier. + ## [0.6.1] - 2024-02-11 ### Added - Added PHP 8.3 support. diff --git a/composer.json b/composer.json index 3a7ff0f..254303b 100644 --- a/composer.json +++ b/composer.json @@ -44,20 +44,12 @@ "test-unit": [ "vendor/bin/phpunit --coverage-xml=build/log/coverage-xml --coverage-clover=build/log/clover.xml --log-junit=build/log/junit.xml" ], - "test-unit-9": [ - "vendor/bin/phpunit --configuration=phpunit-9.xml --coverage-xml=build/log/coverage-xml --coverage-clover=build/log/clover.xml --log-junit=build/log/junit.xml" - ], "test-psalm": "vendor-bin/psalm/vendor/bin/psalm --threads=4 --shepherd", "test": [ "@test-cs", "@test-unit", "@test-psalm" ], - "test-8.0": [ - "@test-cs", - "@test-unit-9", - "@test-psalm" - ], "infection": [ "mkdir -p build/log/infection", "tools/infection --threads=4 --coverage=build/log --no-progress --skip-initial-tests" @@ -69,8 +61,7 @@ }, "config": { "allow-plugins": { - "bamarni/composer-bin-plugin": true, - "infection/extension-installer": true + "bamarni/composer-bin-plugin": true }, "sort-packages": true }, diff --git a/php-8.1.Dockerfile b/php-8.1.Dockerfile index eb2ffdf..5df62cd 100644 --- a/php-8.1.Dockerfile +++ b/php-8.1.Dockerfile @@ -7,9 +7,9 @@ RUN apt-get update && apt-get install -y \ gpg \ libicu-dev && \ pecl install xdebug && \ + docker-php-ext-enable xdebug && \ docker-php-ext-configure intl --enable-intl && \ docker-php-ext-install intl pcntl && \ - docker-php-ext-enable xdebug && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ diff --git a/php-8.2.Dockerfile b/php-8.2.Dockerfile index 8ac0caa..5794eeb 100644 --- a/php-8.2.Dockerfile +++ b/php-8.2.Dockerfile @@ -7,9 +7,9 @@ RUN apt-get update && apt-get install -y \ gpg \ libicu-dev && \ pecl install xdebug && \ + docker-php-ext-enable xdebug && \ docker-php-ext-configure intl --enable-intl && \ docker-php-ext-install intl pcntl && \ - docker-php-ext-enable xdebug && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ diff --git a/php-8.3.Dockerfile b/php-8.3.Dockerfile index f83e2e2..6a6bc0d 100644 --- a/php-8.3.Dockerfile +++ b/php-8.3.Dockerfile @@ -7,9 +7,9 @@ RUN apt-get update && apt-get install -y \ gpg \ libicu-dev && \ pecl install xdebug && \ + docker-php-ext-enable xdebug && \ docker-php-ext-configure intl --enable-intl && \ docker-php-ext-install intl pcntl && \ - docker-php-ext-enable xdebug && \ echo "xdebug.mode = develop,coverage,debug" >> "$PHP_INI_DIR/conf.d/docker-php-ext-xdebug.ini" ENV COMPOSER_ALLOW_SUPERUSER=1 \ diff --git a/src/Event/AfterArrayEvent.php b/src/Event/AfterArrayEvent.php index 9cf10be..ae8b627 100644 --- a/src/Event/AfterArrayEvent.php +++ b/src/Event/AfterArrayEvent.php @@ -17,4 +17,11 @@ public function getPath(): PathInterface { return $this->path; } + + public function with(?PathInterface $path = null): AfterArrayEventInterface + { + return new self( + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/AfterArrayEventInterface.php b/src/Event/AfterArrayEventInterface.php index e2b12ed..aeda584 100644 --- a/src/Event/AfterArrayEventInterface.php +++ b/src/Event/AfterArrayEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface AfterArrayEventInterface extends EventInterface { + public function with(?PathInterface $path = null): AfterArrayEventInterface; } diff --git a/src/Event/AfterElementEvent.php b/src/Event/AfterElementEvent.php index b2858b2..ee5eed1 100644 --- a/src/Event/AfterElementEvent.php +++ b/src/Event/AfterElementEvent.php @@ -23,4 +23,12 @@ public function getIndex(): int { return $this->index; } + + public function with(?PathInterface $path = null, ?int $index = null): AfterElementEventInterface + { + return new self( + index: $index ?? $this->index, + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/AfterElementEventInterface.php b/src/Event/AfterElementEventInterface.php index 73b1a6d..e131250 100644 --- a/src/Event/AfterElementEventInterface.php +++ b/src/Event/AfterElementEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface AfterElementEventInterface extends ElementEventInterface { + public function with(?PathInterface $path = null, ?int $index = null,): AfterElementEventInterface; } diff --git a/src/Event/AfterObjectEvent.php b/src/Event/AfterObjectEvent.php index c03dcb6..965b099 100644 --- a/src/Event/AfterObjectEvent.php +++ b/src/Event/AfterObjectEvent.php @@ -17,4 +17,11 @@ public function getPath(): PathInterface { return $this->path; } + + public function with(?PathInterface $path = null): AfterObjectEventInterface + { + return new self( + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/AfterObjectEventInterface.php b/src/Event/AfterObjectEventInterface.php index bff27f1..f0b6964 100644 --- a/src/Event/AfterObjectEventInterface.php +++ b/src/Event/AfterObjectEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface AfterObjectEventInterface extends EventInterface { + public function with(?PathInterface $path = null): AfterObjectEventInterface; } diff --git a/src/Event/AfterPropertyEvent.php b/src/Event/AfterPropertyEvent.php index 2ca32de..6d1526d 100644 --- a/src/Event/AfterPropertyEvent.php +++ b/src/Event/AfterPropertyEvent.php @@ -23,4 +23,12 @@ public function getPath(): PathInterface { return $this->path; } + + public function with(?PathInterface $path = null, ?string $name = null): AfterPropertyEventInterface + { + return new self( + name: $name ?? $this->name, + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/AfterPropertyEventInterface.php b/src/Event/AfterPropertyEventInterface.php index a022948..e8b6eb6 100644 --- a/src/Event/AfterPropertyEventInterface.php +++ b/src/Event/AfterPropertyEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface AfterPropertyEventInterface extends PropertyEventInterface { + public function with(?PathInterface $path = null, ?string $name = null): AfterPropertyEventInterface; } diff --git a/src/Event/BeforeArrayEvent.php b/src/Event/BeforeArrayEvent.php index 5230aa4..cc723e9 100644 --- a/src/Event/BeforeArrayEvent.php +++ b/src/Event/BeforeArrayEvent.php @@ -17,4 +17,11 @@ public function getPath(): PathInterface { return $this->path; } + + public function with(?PathInterface $path = null): BeforeArrayEventInterface + { + return new self( + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/BeforeArrayEventInterface.php b/src/Event/BeforeArrayEventInterface.php index dd32c4c..8ee5700 100644 --- a/src/Event/BeforeArrayEventInterface.php +++ b/src/Event/BeforeArrayEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface BeforeArrayEventInterface extends EventInterface { + public function with(?PathInterface $path = null): BeforeArrayEventInterface; } diff --git a/src/Event/BeforeElementEvent.php b/src/Event/BeforeElementEvent.php index 3b8b313..bc4e53a 100644 --- a/src/Event/BeforeElementEvent.php +++ b/src/Event/BeforeElementEvent.php @@ -23,4 +23,12 @@ public function getPath(): PathInterface { return $this->path; } + + public function with(?PathInterface $path = null, ?int $index = null): BeforeElementEventInterface + { + return new self( + index: $index ?? $this->index, + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/BeforeElementEventInterface.php b/src/Event/BeforeElementEventInterface.php index 86328ba..eb634fc 100644 --- a/src/Event/BeforeElementEventInterface.php +++ b/src/Event/BeforeElementEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface BeforeElementEventInterface extends ElementEventInterface { + public function with(?PathInterface $path = null, ?int $index = null,): BeforeElementEventInterface; } diff --git a/src/Event/BeforeObjectEvent.php b/src/Event/BeforeObjectEvent.php index 4923cb4..a0f86ac 100644 --- a/src/Event/BeforeObjectEvent.php +++ b/src/Event/BeforeObjectEvent.php @@ -17,4 +17,11 @@ public function getPath(): PathInterface { return $this->path; } + + public function with(?PathInterface $path = null): BeforeObjectEventInterface + { + return new self( + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/BeforeObjectEventInterface.php b/src/Event/BeforeObjectEventInterface.php index 5f5cc7c..3d3b24d 100644 --- a/src/Event/BeforeObjectEventInterface.php +++ b/src/Event/BeforeObjectEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface BeforeObjectEventInterface extends EventInterface { + public function with(?PathInterface $path = null): BeforeObjectEventInterface; } diff --git a/src/Event/BeforePropertyEvent.php b/src/Event/BeforePropertyEvent.php index 6274320..987896f 100644 --- a/src/Event/BeforePropertyEvent.php +++ b/src/Event/BeforePropertyEvent.php @@ -23,4 +23,12 @@ public function getPath(): PathInterface { return $this->path; } + + public function with(?PathInterface $path = null, ?string $name = null): BeforePropertyEventInterface + { + return new self( + name: $name ?? $this->name, + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/BeforePropertyEventInterface.php b/src/Event/BeforePropertyEventInterface.php index 2b62982..904b708 100644 --- a/src/Event/BeforePropertyEventInterface.php +++ b/src/Event/BeforePropertyEventInterface.php @@ -4,6 +4,9 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface BeforePropertyEventInterface extends PropertyEventInterface { + public function with(?PathInterface $path = null, ?string $name = null): BeforePropertyEventInterface; } diff --git a/src/Event/ElementEventInterface.php b/src/Event/ElementEventInterface.php index ef41547..261adaf 100644 --- a/src/Event/ElementEventInterface.php +++ b/src/Event/ElementEventInterface.php @@ -4,7 +4,11 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface ElementEventInterface extends EventInterface { public function getIndex(): int; + + public function with(?PathInterface $path = null, ?int $index = null,): ElementEventInterface; } diff --git a/src/Event/EventInterface.php b/src/Event/EventInterface.php index a66e9d2..a491bfd 100644 --- a/src/Event/EventInterface.php +++ b/src/Event/EventInterface.php @@ -9,4 +9,6 @@ interface EventInterface { public function getPath(): PathInterface; + + public function with(?PathInterface $path = null): EventInterface; } diff --git a/src/Event/PropertyEventInterface.php b/src/Event/PropertyEventInterface.php index f866f75..a68afd4 100644 --- a/src/Event/PropertyEventInterface.php +++ b/src/Event/PropertyEventInterface.php @@ -4,7 +4,11 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface PropertyEventInterface extends EventInterface { public function getName(): string; + + public function with(?PathInterface $path = null, ?string $name = null): PropertyEventInterface; } diff --git a/src/Event/ScalarEvent.php b/src/Event/ScalarEvent.php index 792524c..934648d 100644 --- a/src/Event/ScalarEvent.php +++ b/src/Event/ScalarEvent.php @@ -30,4 +30,15 @@ public function getPath(): PathInterface { return $this->path; } + + public function with( + ?PathInterface $path = null, + float|bool|int|string|null $data = null, + bool $forceData = false, + ): ScalarEventInterface { + return new self( + data: $forceData ? $data : ($data ?? $this->data), + path: $path ?? $this->path, + ); + } } diff --git a/src/Event/ScalarEventInterface.php b/src/Event/ScalarEventInterface.php index 405bd8d..7fabd38 100644 --- a/src/Event/ScalarEventInterface.php +++ b/src/Event/ScalarEventInterface.php @@ -4,7 +4,15 @@ namespace Remorhaz\JSON\Data\Event; +use Remorhaz\JSON\Data\Path\PathInterface; + interface ScalarEventInterface extends EventInterface { public function getData(): int|string|float|bool|null; + + public function with( + ?PathInterface $path = null, + int|string|float|bool|null $data = null, + bool $forceData = false, + ): ScalarEventInterface; } diff --git a/tests/Event/AfterArrayEventTest.php b/tests/Event/AfterArrayEventTest.php index 0695b3d..6e0e31e 100644 --- a/tests/Event/AfterArrayEventTest.php +++ b/tests/Event/AfterArrayEventTest.php @@ -18,4 +18,27 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new AfterArrayEvent($path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new AfterArrayEvent($path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new AfterArrayEvent($oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new AfterArrayEvent(new Path()); + self::assertNotSame($event, $event->with()); + } } diff --git a/tests/Event/AfterElementEventTest.php b/tests/Event/AfterElementEventTest.php index 03b9569..37ddbf1 100644 --- a/tests/Event/AfterElementEventTest.php +++ b/tests/Event/AfterElementEventTest.php @@ -24,4 +24,41 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new AfterElementEvent(1, $path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new AfterElementEvent(1, $path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new AfterElementEvent(1, $oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new AfterElementEvent(1, new Path()); + self::assertNotSame($event, $event->with()); + } + + public function testWith_GivenNoIndex_ResultHasOldIndex(): void + { + $event = new AfterElementEvent(1, new Path()); + $clone = $event->with(); + self::assertSame(1, $clone->getIndex()); + } + + public function testWith_GivenNewIndex_ResultHasNewIndex(): void + { + $event = new AfterElementEvent(1, new Path()); + $clone = $event->with(index: 2); + self::assertSame(2, $clone->getIndex()); + } } diff --git a/tests/Event/AfterObjectEventTest.php b/tests/Event/AfterObjectEventTest.php index 1729442..a02f878 100644 --- a/tests/Event/AfterObjectEventTest.php +++ b/tests/Event/AfterObjectEventTest.php @@ -18,4 +18,27 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new AfterObjectEvent($path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new AfterObjectEvent($path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new AfterObjectEvent($oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new AfterObjectEvent(new Path()); + self::assertNotSame($event, $event->with()); + } } diff --git a/tests/Event/AfterPropertyEventTest.php b/tests/Event/AfterPropertyEventTest.php index 690033b..f404fc6 100644 --- a/tests/Event/AfterPropertyEventTest.php +++ b/tests/Event/AfterPropertyEventTest.php @@ -24,4 +24,41 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new AfterPropertyEvent('a', $path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new AfterPropertyEvent('a', $path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new AfterPropertyEvent('a', $oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new AfterPropertyEvent('a', new Path()); + self::assertNotSame($event, $event->with()); + } + + public function testWith_GivenNoName_ResultHasOldName(): void + { + $event = new AfterPropertyEvent('a', new Path()); + $clone = $event->with(); + self::assertSame('a', $clone->getName()); + } + + public function testWith_GivenNewName_ResultHasNewName(): void + { + $event = new AfterPropertyEvent('a', new Path()); + $clone = $event->with(name: 'b'); + self::assertSame('b', $clone->getName()); + } } diff --git a/tests/Event/BeforeArrayEventTest.php b/tests/Event/BeforeArrayEventTest.php index 091605f..f20ed9d 100644 --- a/tests/Event/BeforeArrayEventTest.php +++ b/tests/Event/BeforeArrayEventTest.php @@ -18,4 +18,28 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new BeforeArrayEvent($path); self::assertSame($path, $event->getPath()); } + + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new BeforeArrayEvent($path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new BeforeArrayEvent($oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new BeforeArrayEvent(new Path()); + self::assertNotSame($event, $event->with()); + } } diff --git a/tests/Event/BeforeElementEventTest.php b/tests/Event/BeforeElementEventTest.php index 8727e1e..cfd90c3 100644 --- a/tests/Event/BeforeElementEventTest.php +++ b/tests/Event/BeforeElementEventTest.php @@ -24,4 +24,41 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new BeforeElementEvent(1, $path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new BeforeElementEvent(1, $path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new BeforeElementEvent(1, $oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new BeforeElementEvent(1, new Path()); + self::assertNotSame($event, $event->with()); + } + + public function testWith_GivenNoIndex_ResultHasOldIndex(): void + { + $event = new BeforeElementEvent(1, new Path()); + $clone = $event->with(); + self::assertSame(1, $clone->getIndex()); + } + + public function testWith_GivenNewIndex_ResultHasNewIndex(): void + { + $event = new BeforeElementEvent(1, new Path()); + $clone = $event->with(index: 2); + self::assertSame(2, $clone->getIndex()); + } } diff --git a/tests/Event/BeforeObjectEventTest.php b/tests/Event/BeforeObjectEventTest.php index cc5abe6..239c47e 100644 --- a/tests/Event/BeforeObjectEventTest.php +++ b/tests/Event/BeforeObjectEventTest.php @@ -18,4 +18,27 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new BeforeObjectEvent($path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new BeforeObjectEvent($path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new BeforeObjectEvent($oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new BeforeObjectEvent(new Path()); + self::assertNotSame($event, $event->with()); + } } diff --git a/tests/Event/BeforePropertyEventTest.php b/tests/Event/BeforePropertyEventTest.php index 30b1453..e6c011e 100644 --- a/tests/Event/BeforePropertyEventTest.php +++ b/tests/Event/BeforePropertyEventTest.php @@ -24,4 +24,41 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new BeforePropertyEvent('a', $path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new BeforePropertyEvent('a', $path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new BeforePropertyEvent('a', $oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new BeforePropertyEvent('a', new Path()); + self::assertNotSame($event, $event->with()); + } + + public function testWith_GivenNoName_ResultHasOldName(): void + { + $event = new BeforePropertyEvent('a', new Path()); + $clone = $event->with(); + self::assertSame('a', $clone->getName()); + } + + public function testWith_GivenNewName_ResultHasNewName(): void + { + $event = new BeforePropertyEvent('a', new Path()); + $clone = $event->with(name: 'b'); + self::assertSame('b', $clone->getName()); + } } diff --git a/tests/Event/ScalarEventTest.php b/tests/Event/ScalarEventTest.php index 09b02b5..0d48ff1 100644 --- a/tests/Event/ScalarEventTest.php +++ b/tests/Event/ScalarEventTest.php @@ -47,4 +47,55 @@ public function testGetPath_ConstructedWithPath_ReturnsSameInstance(): void $event = new ScalarEvent(null, $path); self::assertSame($path, $event->getPath()); } + + public function testWith_GivenNoPath_ResultHasOldPath(): void + { + $path = new Path(); + $event = new ScalarEvent(null, $path); + $clone = $event->with(); + self::assertSame($path, $clone->getPath()); + } + + public function testWith_GivenNewPath_ResultHasNewPath(): void + { + $oldPath = new Path(); + $event = new ScalarEvent(null, $oldPath); + $newPath = new Path(); + $clone = $event->with(path: $newPath); + self::assertSame($newPath, $clone->getPath()); + } + + public function testWith_Called_ResultIsNewInstance(): void + { + $event = new ScalarEvent(null, new Path()); + self::assertNotSame($event, $event->with()); + } + + public function testWith_GivenNoData_ResultHasOldData(): void + { + $event = new ScalarEvent('a', new Path()); + $clone = $event->with(); + self::assertSame('a', $clone->getData()); + } + + public function testWith_GivenNewNonNullData_ResultHasNewData(): void + { + $event = new ScalarEvent('a', new Path()); + $clone = $event->with(data: 'b'); + self::assertSame('b', $clone->getData()); + } + + public function testWith_GivenNewNullDataWithoutForceFlag_ResultHasOldData(): void + { + $event = new ScalarEvent('a', new Path()); + $clone = $event->with(data: null); + self::assertSame('a', $clone->getData()); + } + + public function testWith_GivenNewNullDataWithForceFlag_ResultHasNewData(): void + { + $event = new ScalarEvent('a', new Path()); + $clone = $event->with(data: null, forceData: true); + self::assertSame(null, $clone->getData()); + } } From 22dec196c4336fb45e752521f57aab61151187ac Mon Sep 17 00:00:00 2001 From: remorhaz Date: Sat, 17 Feb 2024 14:52:51 +0200 Subject: [PATCH 8/8] Release 0.7.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62ce1ca..b76120a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.7.0] - 2024-02-17 ### Added - Cloning setters added to events to make stream modification easier.