diff --git a/.cs.php b/.cs.php index 2bba5e9..52c4c3e 100644 --- a/.cs.php +++ b/.cs.php @@ -19,7 +19,7 @@ 'array_syntax' => ['syntax' => 'short'], 'cast_spaces' => ['space' => 'none'], 'concat_space' => ['spacing' => 'one'], - 'compact_nullable_typehint' => true, + 'compact_nullable_type_declaration' => true, 'declare_equal_normalize' => ['space' => 'single'], 'general_phpdoc_annotation_remove' => [ 'annotations' => [ @@ -36,7 +36,11 @@ 'phpdoc_order' => true, // psr-5 'phpdoc_no_useless_inheritdoc' => false, 'protected_to_private' => false, - 'yoda_style' => false, + 'yoda_style' => [ + 'equal' => false, + 'identical' => false, + 'less_and_greater' => false + ], 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'], 'ordered_imports' => [ 'sort_algorithm' => 'alpha', diff --git a/LICENSE b/LICENSE index bf7a9a3..bfcf021 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2023 odan +Copyright (c) 2025 odan 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 4e9451d..0878f4f 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,6 @@ [![Latest Version on Packagist](https://img.shields.io/github/release/selective-php/container.svg)](https://packagist.org/packages/selective/container) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE) [![Build Status](https://github.com/selective-php/container/workflows/build/badge.svg)](https://github.com/selective-php/container/actions) -[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/selective-php/container.svg)](https://scrutinizer-ci.com/g/selective-php/container/code-structure) -[![Quality Score](https://img.shields.io/scrutinizer/quality/g/selective-php/container.svg)](https://scrutinizer-ci.com/g/selective-php/container/?branch=master) [![Total Downloads](https://img.shields.io/packagist/dt/selective/container.svg)](https://packagist.org/packages/selective/container/stats) ## Description @@ -13,11 +11,11 @@ A PSR-11 container implementation with optional **autowiring**. ## Requirements - * PHP 8.1+ + * PHP 8.1 - 8.4 ## Installation -``` +```bash composer require selective/container ``` diff --git a/composer.json b/composer.json index 1c3c3cb..25c0282 100644 --- a/composer.json +++ b/composer.json @@ -7,12 +7,12 @@ "psr-11" ], "require": { - "php": "^8.1", + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*", "psr/container": "^2.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3", - "phpstan/phpstan": "^1", + "phpstan/phpstan": "^2", "phpunit/phpunit": "^10", "squizlabs/php_codesniffer": "^3", "symfony/event-dispatcher": "^5 || 6.0.*" @@ -32,12 +32,10 @@ }, "scripts": { "cs:check": [ - "@putenv PHP_CS_FIXER_IGNORE_ENV=1", - "php-cs-fixer fix --dry-run --format=txt --verbose --diff --config=.cs.php --ansi" + "php-cs-fixer fix --dry-run --format=txt --verbose --diff --config=.cs.php --ansi --allow-unsupported-php-version=yes" ], "cs:fix": [ - "@putenv PHP_CS_FIXER_IGNORE_ENV=1", - "php-cs-fixer fix --config=.cs.php --ansi --verbose" + "php-cs-fixer fix --config=.cs.php --ansi --verbose --allow-unsupported-php-version=yes" ], "sniffer:check": "phpcs --standard=phpcs.xml", "sniffer:fix": "phpcbf --standard=phpcs.xml", @@ -49,6 +47,9 @@ "@stan", "@test" ], - "test:coverage": "php -d xdebug.mode=coverage -r \"require 'vendor/bin/phpunit';\" -- --configuration phpunit.xml --do-not-cache-result --colors=always --coverage-clover build/logs/clover.xml --coverage-html build/coverage" + "test:coverage": [ + "@putenv XDEBUG_MODE=coverage", + "phpunit --configuration phpunit.xml --do-not-cache-result --colors=always --display-warnings --display-deprecations --coverage-clover build/coverage/clover.xml --coverage-html build/coverage --coverage-text" + ] } } diff --git a/src/Exceptions/InvalidDefinitionException.php b/src/Exceptions/InvalidDefinitionException.php index 69202ea..25a1364 100644 --- a/src/Exceptions/InvalidDefinitionException.php +++ b/src/Exceptions/InvalidDefinitionException.php @@ -19,7 +19,7 @@ class InvalidDefinitionException extends Exception implements ContainerException * * @return self */ - public static function create(string $message, Throwable $previous = null): self + public static function create(string $message, ?Throwable $previous = null): self { return new self($message, 0, $previous); } diff --git a/src/Resolver/ConstructorResolver.php b/src/Resolver/ConstructorResolver.php index 81ad25e..2ffa762 100644 --- a/src/Resolver/ConstructorResolver.php +++ b/src/Resolver/ConstructorResolver.php @@ -78,7 +78,7 @@ public function resolve(string $id) * * @return array The resolved parameters */ - private function resolveParameters(string $id, ReflectionMethod $method = null): array + private function resolveParameters(string $id, ?ReflectionMethod $method = null): array { if ($method === null) { return []; diff --git a/tests/TestCase/ContainerTest.php b/tests/TestCase/ContainerTest.php index 6c9801a..f63e52c 100644 --- a/tests/TestCase/ContainerTest.php +++ b/tests/TestCase/ContainerTest.php @@ -12,6 +12,7 @@ use Selective\Container\Exceptions\InvalidDefinitionException; use Selective\Container\Exceptions\NotFoundException; use Selective\Container\Resolver\ConstructorResolver; +use Selective\Container\Resolver\DefinitionResolverInterface; use Selective\Container\Test\TestCase\Service\MyAbstractService; use Selective\Container\Test\TestCase\Service\MyService; use Selective\Container\Test\TestCase\Service\MyServiceA; @@ -290,16 +291,7 @@ public function testAutowireWithInvalidInternalClass(): void $container = new Container(); $container->addResolver(new ConstructorResolver($container)); - // https://3v4l.org/1AXpr - if (version_compare(PHP_VERSION, '8.0.0') >= 0) { - // PHP 8+ - $this->assertInstanceOf(Exception::class, $container->get(Exception::class)); - } else { - // PHP 7.x - // Cannot determine default value for internal functions - $this->expectException(InvalidDefinitionException::class); - $container->get(Exception::class); - } + $this->assertInstanceOf(Exception::class, $container->get(Exception::class)); } /** @@ -312,15 +304,7 @@ public function testAutowireWithInvalidInternalInterface(): void $container = new Container(); $container->addResolver(new ConstructorResolver($container)); - if (version_compare(PHP_VERSION, '8.0.0') >= 0) { - // PHP 8+ - $this->assertInstanceOf(NotFoundException::class, $container->get(NotFoundException::class)); - } else { - // PHP 7.x - // Cannot determine default value for internal functions - $this->expectException(InvalidDefinitionException::class); - $container->get(NotFoundException::class); - } + $this->assertInstanceOf(NotFoundException::class, $container->get(NotFoundException::class)); } /** @@ -353,4 +337,25 @@ public function testAutowireWithNotExistingClass(): void $container->addResolver(new ConstructorResolver($container)); $container->get('Nada\Foo'); } + + /** + * Test. + * + * @return void + */ + public function testAutowireReturnsNull(): void + { + $container = new Container(); + + $resolver = $this->createMock(DefinitionResolverInterface::class); + $resolver->method('isResolvable')->willReturn(false); + $resolver->expects($this->once()) + ->method('resolve') + ->with(stdClass::class) + ->willReturn(null); + + $container->addResolver($resolver); + + $this->assertNull($container->get(stdClass::class)); + } } diff --git a/tests/TestCase/Resolver/ConstructorResolverTest.php b/tests/TestCase/Resolver/ConstructorResolverTest.php index 33279a9..f6a3fd4 100644 --- a/tests/TestCase/Resolver/ConstructorResolverTest.php +++ b/tests/TestCase/Resolver/ConstructorResolverTest.php @@ -3,12 +3,19 @@ namespace Selective\Container\Test\Resolver\TestCase; use PHPUnit\Framework\TestCase; +use ReflectionMethod; use Selective\Container\Container; use Selective\Container\Exceptions\InvalidDefinitionException; use Selective\Container\Resolver\ConstructorResolver; +use stdClass; final class ConstructorResolverTest extends TestCase { + /** + * Test. + * + * @return void + */ public function testResolveOnInvalidDefinition(): void { $this->expectException(InvalidDefinitionException::class); @@ -19,4 +26,25 @@ public function testResolveOnInvalidDefinition(): void $constructorResolver = new ConstructorResolver($container); $constructorResolver->resolve($invalidId); } + + /** + * Resolve parameters returns empty array when method is null. + * + * @return void + */ + public function testResolveParametersReturnsEmptyArrayWhenMethodIsNull(): void + { + $container = new Container(); + $resolver = new ConstructorResolver($container); + + $ref = new ReflectionMethod( + ConstructorResolver::class, + 'resolveParameters' + ); + $ref->setAccessible(true); + + $result = $ref->invoke($resolver, stdClass::class, null); + + $this->assertSame([], $result); + } }