diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2927c9..5848358 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ name: "CI Tests" on: pull_request: push: + branches: + - main jobs: php81: @@ -10,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "Checkout" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: fetch-depth: 2 @@ -20,22 +22,17 @@ jobs: php-version: "8.1" - name: "Cache composer packages" - uses: "actions/cache@v3" + uses: "actions/cache@v4" with: - path: "~/.composer/cache" - key: "php-composer-locked-${{ hashFiles('composer.lock') }}" - restore-keys: "php-composer-locked-" + path: "vendor" + key: "php-composer-locked-php-8.1-${{ hashFiles('**/composer.lock') }}" + restore-keys: "php-composer-locked-php-8.1-" - name: "Install dependencies with composer" run: "composer install --no-interaction --prefer-dist" - name: "Run PHPUnit Tests" - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - composer test - composer global require php-coveralls/php-coveralls - php-coveralls --coverage_clover=build/output/tests/coverage.xml --json_path=build/output/tests/coveralls-upload.json -v + run: "composer test-coverage" - name: "Run PHP CS Check" run: "composer cs-check" @@ -50,16 +47,14 @@ jobs: run: "composer lint" - name: "Run infection" - env: - INFECTION_BADGE_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} - run: "composer infection" + run: "composer infection-ci" php82: name: PHP 8.2 runs-on: ubuntu-latest steps: - name: "Checkout" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: fetch-depth: 2 @@ -69,22 +64,17 @@ jobs: php-version: "8.2" - name: "Cache composer packages" - uses: "actions/cache@v3" + uses: "actions/cache@v4" with: - path: "~/.composer/cache" - key: "php-composer-locked-${{ hashFiles('composer.lock') }}" - restore-keys: "php-composer-locked-" + path: "vendor" + key: "php-composer-locked-php-8.2-${{ hashFiles('**/composer.lock') }}" + restore-keys: "php-composer-locked-php-8.2-" - name: "Install dependencies with composer" run: "composer install --no-interaction --prefer-dist" - name: "Run PHPUnit Tests" - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - composer test - composer global require php-coveralls/php-coveralls - php-coveralls --coverage_clover=build/output/tests/coverage.xml --json_path=build/output/tests/coveralls-upload.json -v + run: "composer test-coverage" - name: "Run PHP CS Check" run: "PHP_CS_FIXER_IGNORE_ENV=1 composer cs-check" @@ -99,14 +89,14 @@ jobs: run: "composer lint" - name: "Run infection" - run: "composer infection" + run: "composer infection-ci" php83: name: PHP 8.3 runs-on: ubuntu-latest steps: - name: "Checkout" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: fetch-depth: 2 @@ -116,22 +106,17 @@ jobs: php-version: "8.3" - name: "Cache composer packages" - uses: "actions/cache@v3" + uses: "actions/cache@v4" with: - path: "~/.composer/cache" - key: "php-composer-locked-${{ hashFiles('composer.lock') }}" - restore-keys: "php-composer-locked-" + path: "vendor" + key: "php-composer-locked-php-8.3-${{ hashFiles('**/composer.lock') }}" + restore-keys: "php-composer-locked-php-8.3-" - name: "Install dependencies with composer" run: "composer install --no-interaction --prefer-dist" - name: "Run PHPUnit Tests" - env: - COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - composer test - composer global require php-coveralls/php-coveralls - php-coveralls --coverage_clover=build/output/tests/coverage.xml --json_path=build/output/tests/coveralls-upload.json -v + run: "composer test-coverage" - name: "Run PHP CS Check" run: "PHP_CS_FIXER_IGNORE_ENV=1 composer cs-check" @@ -146,4 +131,6 @@ jobs: run: "composer lint" - name: "Run infection" - run: "composer infection" \ No newline at end of file + env: + INFECTION_BADGE_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} + run: "composer infection-ci" \ No newline at end of file diff --git a/.gitignore b/.gitignore index bf80923..bec9efc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,28 +1,11 @@ -/vendor/ -node_modules/ -npm-debug.log -yarn-error.log - -# Laravel 4 specific -bootstrap/compiled.php -app/storage/ - -# Laravel 5 & Lumen specific -public/storage -public/hot - -# Laravel 5 & Lumen specific with changed public path -public_html/storage -public_html/hot - -storage/*.key -.env -Homestead.yaml -Homestead.json -/.vagrant +# PHPUnit specific .phpunit.result.cache # Composer +/vendor/ composer.lock +# Package specific /tmp +/build +/tests/Http/Responses/metadata diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index e30a4a9..e031ee7 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -25,7 +25,7 @@ 'magic_constant_casing' => true, 'modernize_types_casting' => true, 'native_function_casing' => true, - 'new_with_braces' => true, + 'new_with_parentheses' => true, 'no_alternative_syntax' => true, 'no_closing_tag' => true, 'no_empty_comment' => true, @@ -41,7 +41,7 @@ 'no_superfluous_elseif' => true, 'no_trailing_comma_in_singleline' => true, 'no_unneeded_control_parentheses' => true, - 'no_unneeded_curly_braces' => true, + 'no_unneeded_braces' => true, 'no_unneeded_final_method' => true, 'no_unused_imports' => true, 'no_useless_else' => true, diff --git a/README.md b/README.md index d3d9706..a464f82 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,14 @@ You are also welcome to use the Issue Tracker to set bugs, improvements or upgra ``` composer require dropelikeit/laravel-jms-serializer ``` ### Support note -- Laravel 6 and 7 are no longer supported with release v4.0.0 and higher. -- Laravel 5.* is no longer supported with release v2.0.0 and higher. +| Laravel | PHP | Package Version | Status | +|:-------:|:------------------:|:---------------:|:-------------:| +| 11 | 8.2, 8.3 | v6.x.x | Support | +| 10 | 8.1, 8.2, 8.3 | >=v5.x.x | Support | +| 9 | 8.0, 8.1, 8.2 | v4.x.x - v5.1.0 | Not supported | +| 8 | 7.3, 7.4, 8.0, 8.1 | v3.x.x - v4.0.0 | Not supported | +| 7 | 7.2, 7.3, 7.4, 8.0 | v2.x.x - v3.0.0 | Not supported | +| 6 | 7.2, 7.3, 7.4, 8.0 | v1.x.x - v3.0.0 | Not supported | ### How to use diff --git a/composer.json b/composer.json index 57b55cb..0876212 100644 --- a/composer.json +++ b/composer.json @@ -11,11 +11,11 @@ } ], "require": { - "php": "^8.1", - "illuminate/http": "^9.0|^10.0", - "illuminate/support": "^9.0|^10.0", - "illuminate/contracts": "^9.0|^10.0", - "jms/serializer": "^3.27" + "php": "^8.1|^8.2|^8.3", + "illuminate/http": "^9.0|^10.0|^11.0", + "illuminate/support": "^9.0|^10.0|^11.0", + "illuminate/contracts": "^9.0|^10.0|^11.0", + "jms/serializer": "^3.30" }, "autoload": { "psr-4": { @@ -37,27 +37,28 @@ }, "require-dev": { "roave/security-advisories": "dev-latest", - "friendsofphp/php-cs-fixer": "^3.23", - "phpunit/phpunit": "^10.3", - "nunomaduro/larastan": "^2.6", - "orchestra/testbench": "^8.9", + "friendsofphp/php-cs-fixer": "^3.52", + "phpunit/phpunit": "^10.0", + "larastan/larastan": "^2.9", + "orchestra/testbench": "^8.9|^9.0", "phpstan/phpstan-phpunit": "^1.3", "php-parallel-lint/php-parallel-lint": "^1.3", - "symfony/cache": "^6.3", - "vimeo/psalm": "^5.15", - "psalm/plugin-laravel": "^2.8", - "psalm/plugin-phpunit": "^0.18.4", - "infection/infection": "^0.27.6" + "symfony/cache": "^6.3|^7.0", + "vimeo/psalm": "^5.23", + "psalm/plugin-laravel": "^2.10", + "psalm/plugin-phpunit": "^0.19", + "infection/infection": "^0.27.10" }, "scripts": { "lint": "parallel-lint --exclude .git --exclude vendor .", "cs-check": "php-cs-fixer -v --dry-run --using-cache=no fix", "cs-fix": "php-cs-fixer --using-cache=no fix", "test": "export XDEBUG_MODE=coverage && phpunit", - "test-coverage": "export XDEBUG_MODE=coverage && phpunit --coverage-clover build/logs/clover.xml --coverage-html build/logs/clover.html", + "test-coverage": "export XDEBUG_MODE=coverage && phpunit --coverage-xml build/logs --coverage-clover build/logs/clover.xml --coverage-html build/logs/clover.html --log-junit build/logs/junit.xml", "analyze": "phpstan analyze --no-progress --memory-limit=-1 --xdebug", "psalm": "psalm --no-cache -c psalm.xml", "infection": "infection --threads=4", + "infection-ci": "infection --coverage=build/logs --threads=4", "check": [ "@cs-check", "@analyze", diff --git a/infection.json5 b/infection.json5 index fd7aaae..6b8eef0 100644 --- a/infection.json5 +++ b/infection.json5 @@ -12,14 +12,14 @@ "@default": true }, "logs": { - "html": "infection.html", - "summary": "summary.log", - "json": "infection-log.json", - "perMutator": "per-mutator.md", + "html": "build/infection/infection.html", + "summary": "build/infection/summary.log", + "json": "build/infection/infection-log.json", + "perMutator": "build/infection/per-mutator.md", "github": true, "stryker": { "badge": "master" }, - "summaryJson": "summary.json" + "summaryJson": "build/infection/summary.json" }, } \ No newline at end of file diff --git a/phpstan.neon.dist b/phpstan.neon.dist index ea67adc..de030a2 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,5 @@ includes: - - vendor/nunomaduro/larastan/extension.neon + - vendor/larastan/larastan/extension.neon - vendor/phpstan/phpstan-phpunit/extension.neon - vendor/phpstan/phpstan-phpunit/rules.neon parameters: diff --git a/src/Http/Responses/ResponseFactory.php b/src/Http/Responses/ResponseFactory.php index e4fa03e..d8517b3 100644 --- a/src/Http/Responses/ResponseFactory.php +++ b/src/Http/Responses/ResponseFactory.php @@ -22,7 +22,6 @@ final class ResponseFactory implements Contracts\ResponseBuilder { private const HEADER_NAME_CONTENT_TYPE = 'Content-Type'; - private const HEADER_VALUE_APPLICATION_JSON = 'application/json'; private const HEADER_VALUE_APPLICATION_XML = 'application/xml'; private const SERIALIZER_INITIAL_TYPE_ARRAY = 'array'; @@ -129,7 +128,6 @@ private function getResponse(string $content): Response return new JsonResponse( data: $content, status: $this->status, - headers: [self::HEADER_NAME_CONTENT_TYPE => self::HEADER_VALUE_APPLICATION_JSON], json: true ); } diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index 346f6c0..660ccb3 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -9,6 +9,7 @@ use Dropelikeit\LaravelJmsSerializer\Http\Responses\ResponseFactory; use Dropelikeit\LaravelJmsSerializer\Serializer\Factory; use Illuminate\Config\Repository; +use Illuminate\Foundation\Application; use Illuminate\Support\Facades\Storage; use Illuminate\Support\ServiceProvider as BaseServiceProvider; use function sprintf; @@ -64,9 +65,11 @@ public function register(): void $this->app->bind(ResponseBuilder::class, ResponseFactory::class); - $app = $this->app; - $this->app->bind('ResponseFactory', static function ($app): ResponseFactory { - return $app->get(ResponseFactory::class); + $this->app->bind('ResponseFactory', static function (Application $app): ResponseFactory { + $responseFactory = $app->get(ResponseFactory::class); + Assert::isInstanceOf($responseFactory, ResponseFactory::class); + + return $responseFactory; }); } diff --git a/tests/Http/Responses/ResponseFactoryTest.php b/tests/Http/Responses/ResponseFactoryTest.php index 139d386..2a86c04 100644 --- a/tests/Http/Responses/ResponseFactoryTest.php +++ b/tests/Http/Responses/ResponseFactoryTest.php @@ -8,22 +8,27 @@ use Dropelikeit\LaravelJmsSerializer\Exception\SerializeType; use Dropelikeit\LaravelJmsSerializer\Http\Responses\ResponseFactory; use Dropelikeit\LaravelJmsSerializer\Serializer\Factory; -use Dropelikeit\LaravelJmsSerializer\Tests\ResponseFactory\Dummy; -use Dropelikeit\LaravelJmsSerializer\Tests\ResponseFactory\Response; +use Dropelikeit\LaravelJmsSerializer\Tests\data\ResponseFactory\Dummy; +use Dropelikeit\LaravelJmsSerializer\Tests\data\ResponseFactory\JsonDummy; +use Dropelikeit\LaravelJmsSerializer\Tests\data\ResponseFactory\Response; +use Dropelikeit\LaravelJmsSerializer\Tests\data\ResponseFactory\XmlDummy; use Illuminate\Http\Response as LaravelResponse; +use InvalidArgumentException; use JMS\Serializer\SerializationContext; +use JMS\Serializer\SerializerInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\JsonResponse; /** * @author Marcel Strahl */ final class ResponseFactoryTest extends TestCase { - /** - * @psalm-var MockObject&Contracts\Config - */ - private MockObject $config; + private readonly MockObject&Contracts\Config $config; + private readonly MockObject&SerializerInterface $serializer; public function setUp(): void { @@ -33,11 +38,13 @@ public function setUp(): void ->getMockBuilder(Contracts\Config::class) ->disableOriginalConstructor() ->getMock(); + + $this->serializer = $this + ->getMockBuilder(SerializerInterface::class) + ->getMock(); } - /** - * @test - */ + #[Test] public function canCreateResponse(): void { $this->config @@ -63,9 +70,7 @@ public function canCreateResponse(): void self::assertEquals('{"amount":12,"text":"Hello World!"}', $response->getContent()); } - /** - * @test - */ + #[Test] public function canCreateFromArrayIterator(): void { $this->config @@ -85,15 +90,13 @@ public function canCreateFromArrayIterator(): void $responseFactory = new ResponseFactory((new Factory())->getSerializer($this->config), $this->config); - $response = $responseFactory->create(Response::create([new Response\Item()])); + $response = $responseFactory->create(Response::create([new \Dropelikeit\LaravelJmsSerializer\Tests\data\ResponseFactory\Response\Item()])); self::assertEquals(200, $response->getStatusCode()); self::assertEquals('[{"key":"magic_number","value":12}]', $response->getContent()); } - /** - * @test - */ + #[Test] public function canCreateJsonResponseFromArray(): void { $this->config @@ -113,7 +116,7 @@ public function canCreateJsonResponseFromArray(): void $responseFactory = new ResponseFactory((new Factory())->getSerializer($this->config), $this->config); - $response = $responseFactory->createFromArray(require __DIR__ . '/../../ResponseFactory/dummy_array.php'); + $response = $responseFactory->createFromArray(require __DIR__ . '/../../data/ResponseFactory/dummy_array.php'); self::assertEquals(200, $response->getStatusCode()); self::assertEquals( @@ -122,9 +125,7 @@ public function canCreateJsonResponseFromArray(): void ); } - /** - * @test - */ + #[Test] public function canCreateXmlResponseFromArray(): void { $this->config @@ -140,11 +141,11 @@ public function canCreateXmlResponseFromArray(): void $this->config ->expects(self::once()) ->method('getSerializeType') - ->willReturn(Contracts\Config::SERIALIZE_TYPE_XML); + ->willReturn('xml'); $responseFactory = new ResponseFactory((new Factory())->getSerializer($this->config), $this->config); - $response = $responseFactory->createFromArray(require __DIR__ . '/../../ResponseFactory/dummy_array.php'); + $response = $responseFactory->createFromArray(require __DIR__ . '/../../data/ResponseFactory/dummy_array.php'); self::assertEquals(200, $response->getStatusCode()); self::assertEquals( @@ -165,9 +166,7 @@ public function canCreateXmlResponseFromArray(): void ); } - /** - * @test - */ + #[Test] public function canChangeStatusCode(): void { $this->config @@ -195,9 +194,7 @@ public function canChangeStatusCode(): void self::assertEquals('{"amount":12,"text":"Hello World!"}', $response->getContent()); } - /** - * @test - */ + #[Test] public function canUseGivenContext(): void { $this->config @@ -225,11 +222,9 @@ public function canUseGivenContext(): void /** * @psalm-param Contracts\Config::SERIALIZE_TYPE_* $changeSerializeTypeTo - * @param string $expectedResult - * - * @test - * @dataProvider dataProviderCanSerializeWithSerializeType */ + #[Test] + #[DataProvider(methodName: 'dataProviderCanSerializeWithSerializeType')] public function canSerializeWithSerializeType(string $changeSerializeTypeTo, string $expectedResult): void { $this->config @@ -282,9 +277,7 @@ public static function dataProviderCanSerializeWithSerializeType(): array ]; } - /** - * @test - */ + #[Test] public function canNotCreateWithUnknownSerializeType(): void { $this->expectException(SerializeType::class); @@ -310,9 +303,7 @@ public function canNotCreateWithUnknownSerializeType(): void $responseFactory->withSerializeType('array'); } - /** - * @test - */ + #[Test] public function canCreateQuietResponse(): void { $responseFactory = new ResponseFactory((new Factory())->getSerializer($this->config), $this->config); @@ -321,4 +312,131 @@ public function canCreateQuietResponse(): void $this->assertEquals(new LaravelResponse(status: 204), $response); } + + #[Test] + public function throwInvalidArgumentExceptionIfContentOnCreateMethodIsEmpty(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Expected a different value than "".'); + + $object = new Dummy(); + + $this->config + ->expects(self::never()) + ->method('getCacheDir'); + + $this->config + ->expects(self::never()) + ->method('debug'); + + $this->config + ->expects(self::once()) + ->method('getSerializeType') + ->willReturn(Contracts\Config::SERIALIZE_TYPE_JSON); + + $this->serializer + ->expects(self::once()) + ->method('serialize') + ->with($object, 'json', null, null) + ->wilLReturn(''); + + (new ResponseFactory($this->serializer, $this->config))->create($object); + } + + #[Test] + public function throwInvalidArgumentExceptionIfContentOnCreateFromArrayMethodIsEmpty(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Expected a different value than "".'); + + $object = new Dummy(); + + $this->config + ->expects(self::never()) + ->method('getCacheDir'); + + $this->config + ->expects(self::never()) + ->method('debug'); + + $this->config + ->expects(self::once()) + ->method('getSerializeType') + ->willReturn(Contracts\Config::SERIALIZE_TYPE_JSON); + + $this->serializer + ->expects(self::once()) + ->method('serialize') + ->with([$object], 'json', null) + ->wilLReturn(''); + + (new ResponseFactory($this->serializer, $this->config))->createFromArray([$object]); + } + + #[Test] + public function canDetectIfSerializeTypeIsXmlResultResponseHasXml(): void + { + $expectedResponse = new LaravelResponse( + content: ' + +', + status: 200, + headers: ['Content-Type' => 'application/xml'] + ); + + $this->config + ->expects(self::once()) + ->method('getCacheDir') + ->willReturn(__DIR__); + + $this->config + ->expects(self::once()) + ->method('debug') + ->willReturn(true); + + $this->config + ->expects(self::once()) + ->method('getSerializeType') + ->willReturn('xml'); + + $responseFactory = new ResponseFactory((new Factory())->getSerializer($this->config), $this->config); + + $response = $responseFactory->create(new XmlDummy()); + + $this->assertEquals($expectedResponse, $response); + } + + #[Test] + public function canDetectIfSerializeTypeIsJSONResultResponseHasJSON(): void + { + $expectedResponse = new JsonResponse( + data: '{"title":"My test"}', + status: 200, + headers: ['Content-Type' => 'application/json'], + json: true + ); + + $this->config + ->expects(self::once()) + ->method('getCacheDir') + ->willReturn(__DIR__); + + $this->config + ->expects(self::once()) + ->method('debug') + ->willReturn(true); + + $this->config + ->expects(self::once()) + ->method('getSerializeType') + ->willReturn('json'); + + $responseFactory = new ResponseFactory((new Factory())->getSerializer($this->config), $this->config); + + $response = $responseFactory->create(new JsonDummy()); + + $this->assertEquals($expectedResponse, $response); + } } diff --git a/tests/Serializer/FactoryTest.php b/tests/Serializer/FactoryTest.php index eea904f..b8d2b04 100644 --- a/tests/Serializer/FactoryTest.php +++ b/tests/Serializer/FactoryTest.php @@ -10,9 +10,16 @@ use Dropelikeit\LaravelJmsSerializer\Tests\Serializer\data\CustomHandler; use InvalidArgumentException; use JMS\Serializer\Context; +use JMS\Serializer\Handler\HandlerRegistry; use JMS\Serializer\JsonSerializationVisitor; +use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy; +use JMS\Serializer\Naming\SerializedNameAnnotationStrategy; +use JMS\Serializer\SerializationContext; use JMS\Serializer\Serializer; +use JMS\Serializer\SerializerBuilder; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; +use Webmozart\Assert\Assert; /** * @author Marcel Strahl @@ -138,4 +145,94 @@ public function canNotCreateSerializerWithInvalidCustomHandler(): void ], ])); } + + #[Test] + public function detectIfSerializerHasDefaultListeners(): void + { + $expectedSerializer = $this->getSerializer(); + + /** @var array{serialize_null: bool, cache_dir: string, serialize_type: string, debug: bool, add_default_handlers: bool, custom_handlers: array} $config */ + $config = [ + 'serialize_null' => true, + 'serialize_type' => 'json', + 'cache_dir' => 'tmp', + 'debug' => false, + 'add_default_handlers' => true, + 'custom_handlers' => [ + CustomHandler::class, + ], + ]; + + $serializer = (new Factory())->getSerializer(Config::fromConfig($config)); + + $this->assertEquals($expectedSerializer, $serializer); + } + + private function getSerializer(): Serializer + { + /** @var array{serialize_null: bool, cache_dir: string, serialize_type: string, debug: bool, add_default_handlers: bool, custom_handlers: array} $options */ + $options = [ + 'serialize_null' => true, + 'serialize_type' => 'json', + 'cache_dir' => 'tmp', + 'debug' => false, + 'add_default_handlers' => true, + 'custom_handlers' => [ + CustomHandler::class, + ], + ]; + + $config = Config::fromConfig($options); + + $builder = SerializerBuilder::create() + ->setPropertyNamingStrategy( + new SerializedNameAnnotationStrategy( + new IdenticalPropertyNamingStrategy() + ) + ) + ->addDefaultListeners() + ->setSerializationContextFactory(static function () use ($config): SerializationContext { + return SerializationContext::create()->setSerializeNull($config->shouldSerializeNull()); + }); + + if ($config->shouldAddDefaultHeaders()) { + $builder->addDefaultHandlers(); + } + + $customHandlers = $config->getCustomHandlers(); + if ($customHandlers !== []) { + $builder->configureHandlers(function (HandlerRegistry $registry) use ($customHandlers): void { + foreach ($customHandlers as $customHandler) { + if (is_string($customHandler) && class_exists($customHandler)) { + $customHandler = new $customHandler(); + } + + Assert::implementsInterface( + $customHandler, + CustomHandlerConfiguration::class, + sprintf( + 'Its required to implement the "%s" interface', + CustomHandlerConfiguration::class + ) + ); + /** @phpstan-ignore-next-line */ + assert($customHandler instanceof CustomHandlerConfiguration); + + $registry->registerHandler( + $customHandler->getDirection(), + $customHandler->getTypeName(), + $customHandler->getFormat(), + $customHandler->getCallable(), + ); + } + }); + } + + $cacheDir = $config->getCacheDir(); + if ($cacheDir !== '') { + $builder->setCacheDir($cacheDir); + } + + return $builder->setDebug($config->debug())->build(); + } } diff --git a/tests/ResponseFactory/Dummy.php b/tests/data/ResponseFactory/Dummy.php similarity index 82% rename from tests/ResponseFactory/Dummy.php rename to tests/data/ResponseFactory/Dummy.php index 44d9287..f956957 100644 --- a/tests/ResponseFactory/Dummy.php +++ b/tests/data/ResponseFactory/Dummy.php @@ -1,9 +1,9 @@ ") * @var array|null - * @psalm-param list + * @psalm-param Item */ public ?array $items = null; diff --git a/tests/data/ResponseFactory/JsonDummy.php b/tests/data/ResponseFactory/JsonDummy.php new file mode 100644 index 0000000..b9548cb --- /dev/null +++ b/tests/data/ResponseFactory/JsonDummy.php @@ -0,0 +1,22 @@ +title = 'My test'; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/ResponseFactory/Response.php b/tests/data/ResponseFactory/Response.php similarity index 80% rename from tests/ResponseFactory/Response.php rename to tests/data/ResponseFactory/Response.php index 7332ea1..da9e0bc 100644 --- a/tests/ResponseFactory/Response.php +++ b/tests/data/ResponseFactory/Response.php @@ -1,10 +1,10 @@ $items * @psalm-param list $items - * - * @return self */ public static function create(array $items): self { diff --git a/tests/ResponseFactory/Response/Item.php b/tests/data/ResponseFactory/Response/Item.php similarity index 88% rename from tests/ResponseFactory/Response/Item.php rename to tests/data/ResponseFactory/Response/Item.php index 3b6d5a0..714b365 100644 --- a/tests/ResponseFactory/Response/Item.php +++ b/tests/data/ResponseFactory/Response/Item.php @@ -1,7 +1,7 @@ title = 'My test'; + } + + public function getTitle(): string + { + return $this->title; + } +} diff --git a/tests/ResponseFactory/dummy_array.php b/tests/data/ResponseFactory/dummy_array.php similarity index 100% rename from tests/ResponseFactory/dummy_array.php rename to tests/data/ResponseFactory/dummy_array.php