From 2e4cb81a87673b2bb3ec37ab1604f2a60275793d Mon Sep 17 00:00:00 2001 From: Michael Diodone Date: Tue, 10 May 2022 13:18:17 +0200 Subject: [PATCH] Add support for PHP 8.0 Set min PHP version to 7.4 --- .github/workflows/tests.yml | 2 +- README.md | 14 ++ composer.json | 8 +- .../injektor/DependencyInjectionContainer.php | 120 +++++++----------- src/rg/injektor/ReflectionClassHelper.php | 40 ++++++ src/rg/injektor/SimpleAnnotationReader.php | 6 +- .../generators/InjectionParameter.php | 69 +++++----- .../injektor/generators/InjectionProperty.php | 35 +++-- .../DependencyInjectionContainerTest.php | 45 ++++--- ...ryOnlyDependencyInjectionContainerTest.php | 28 ++-- .../generators/FactoryGeneratorTest.php | 21 --- test/rg/injektor/test_classes.php | 20 ++- ...asses_php74.php => test_classes_php80.php} | 10 +- 13 files changed, 229 insertions(+), 189 deletions(-) create mode 100644 src/rg/injektor/ReflectionClassHelper.php rename test/rg/injektor/{test_classes_php74.php => test_classes_php80.php} (62%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2851d72..9939033 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ jobs: tests: strategy: matrix: - php-versions: ['7.3', '7.4'] + php-versions: ['7.4', '8.0'] runs-on: ubuntu-latest diff --git a/README.md b/README.md index 2ea1797..c317d5c 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,20 @@ class GenerateDependencyInjectionFactories extends \Symfony\Component\Console\Co require_once $fullpath; + $astLocator = (new \Roave\BetterReflection\BetterReflection())->astLocator(); + + // for roave/better-reflection 4.x (PHP 7.4) + $reflector = new \Roave\BetterReflection\Reflector\ClassReflector(new Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator($fileName, $astLocator)); + $classes = $reflector->getAllClasses(); + + // for roave/better-reflection 5.x (PHP 8.0) + $reflector = new \Roave\BetterReflection\Reflector\DefaultReflector(new Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator($fileName, $astLocator)); + $classes = $reflector->reflectAllClasses(); + + foreach ($classes as $class) { + $generator->processFileForClass($class->getName()); + } + $fileReflection = new \Laminas\Code\Reflection\FileReflection($fullpath); $classes = $fileReflection->getClasses(); foreach ($classes as $class) { diff --git a/composer.json b/composer.json index 62cff5c..62e6519 100644 --- a/composer.json +++ b/composer.json @@ -16,15 +16,15 @@ } ], "require": { - "php": "^7.2", - "laminas/laminas-code": "^3.0.0", + "php": "^7.4 || ^8.0", "doctrine/annotations": "^1.0.0", + "laminas/laminas-code": "^4.0.0", "psr/log": "^1.0.0" }, "require-dev": { - "composer/package-versions-deprecated": "^1.0", + "ocramius/proxy-manager": "^2.1.0", "phpunit/phpunit": "^9.0.0", - "ocramius/proxy-manager": "^2.1.0" + "roave/better-reflection": "^4.0.0 || ^5.0.0" }, "suggest": { "ocramius/proxy-manager": "For lazy loading" diff --git a/src/rg/injektor/DependencyInjectionContainer.php b/src/rg/injektor/DependencyInjectionContainer.php index 207bed6..4d68d4e 100644 --- a/src/rg/injektor/DependencyInjectionContainer.php +++ b/src/rg/injektor/DependencyInjectionContainer.php @@ -16,8 +16,12 @@ use ProxyManager\Proxy\LazyLoadingInterface; use Psr\Log\LoggerInterface; use ReflectionNamedType; +use ReflectionParameter; use ReflectionProperty; use rg\injektor\annotations\Named; +use UnexpectedValueException; +use function get_class; +use function method_exists; use const PHP_VERSION_ID; /** @@ -26,61 +30,33 @@ */ class DependencyInjectionContainer { - public static $CLASS = __CLASS__; + public static string $CLASS = __CLASS__; - /** - * @var Configuration - */ - protected $config; + protected Configuration $config; - /** - * @var array - */ - private $instances = []; + private array $instances = []; - /** - * @var DependencyInjectionContainer - */ - private static $defaultInstance; + private static ?DependencyInjectionContainer $defaultInstance = null; - /** - * @var SimpleAnnotationReader - */ - private $annotationReader; + private SimpleAnnotationReader $annotationReader; /** * iteration depth used for intelligent logging, makes it easier to detect circular iterations - * - * @var int */ - private $iterationDepth = 0; + private int $iterationDepth = 0; - /** - * @var LoggerInterface - */ - private $logger; + private ?LoggerInterface $logger = null; - /** - * @var bool - */ - private $supportsLazyLoading = false; + private bool $supportsLazyLoading; - /** - * @var LazyLoadingValueHolderFactory|null - */ - private $lazyProxyFactory; + private ?LazyLoadingValueHolderFactory $lazyProxyFactory = null; /** * used for injection loop detection - * - * @var array */ - protected $alreadyVisitedClasses = []; + protected array $alreadyVisitedClasses = []; - /** - * @param Configuration $config - */ - public function __construct(Configuration $config = null) { + public function __construct(?Configuration $config = null) { $this->config = $config ? : new Configuration(); if (!self::$defaultInstance) { @@ -92,11 +68,9 @@ public function __construct(Configuration $config = null) { } /** - * @static * @throws InjectionException - * @return DependencyInjectionContainer */ - public static function getDefaultInstance() { + public static function getDefaultInstance(): DependencyInjectionContainer { if (self::$defaultInstance) { return self::$defaultInstance; } @@ -104,32 +78,22 @@ public static function getDefaultInstance() { throw new InjectionException('dependency injection container was not instantiated yet'); } - /** - * @param DependencyInjectionContainer $instance - */ public static function setDefaultInstance(DependencyInjectionContainer $instance) { self::$defaultInstance = $instance; } - /** - * @param LoggerInterface $logger - */ public function setLogger(LoggerInterface $logger) { $this->logger = $logger; } - /** - * @return Configuration - */ - public function getConfig() { + public function getConfig(): Configuration { return $this->config; } /** - * @param string $className * @throws InjectionLoopException */ - protected function checkForInjectionLoop($className) { + protected function checkForInjectionLoop(string $className) { if ($this->iterationDepth > 1000) { throw new InjectionLoopException( 'Injection loop detected ' . $className . ' ' . $this->iterationDepth . PHP_EOL . print_r( @@ -431,12 +395,12 @@ private function injectProperty($property, $instance) { * @param string $fullClassName * @return string */ - public function getFullClassNameBecauseOfImports($property, $fullClassName) { + public function getFullClassNameBecauseOfImports(ReflectionProperty $property, string $fullClassName) { // only process names which are not fully qualified, yet // fully qualified names must start with a \ if ('\\' !== $fullClassName[0]) { $parser = new PhpParser(); - $useStatements = $parser->parseClass($property->getDeclaringClass()); + $useStatements = $parser->parseUseStatements($property->getDeclaringClass()); if ($property->getDeclaringClass()->inNamespace()) { $parentNamespace = $property->getDeclaringClass()->getNamespaceName(); } @@ -456,17 +420,20 @@ public function getFullClassNameBecauseOfImports($property, $fullClassName) { return trim($fullClassName, '\\'); } - /** - * @param ReflectionProperty $property - * @return string|null - */ - public function getClassFromProperty($property) { + public function getClassFromProperty(ReflectionProperty $property): ?string { $fullClassName = $this->annotationReader->getClassFromVarTypeHint($property->getDocComment()); - if (!$fullClassName && PHP_VERSION_ID >= 70400) { - $namedType = $property->getType(); - if ($namedType instanceof ReflectionNamedType && $namedType->getName()) { - $fullClassName = '\\' . $namedType->getName(); + if (!$fullClassName) { + $type = $property->getType(); + if ($type instanceof ReflectionNamedType && $type->isBuiltin() === false && $type->getName()) { + $fullClassName = '\\' . $type->getName(); + } elseif ($type !== null && method_exists($type, 'getTypes')) { + foreach ($type->getTypes() as $namedType) { + if ($namedType->isBuiltin() === false && $namedType->getName()) { + $fullClassName = '\\' . $namedType->getName(); + } + break; + } } } @@ -788,7 +755,7 @@ public function getMethodArguments(\ReflectionMethod $methodReflection, array $d $isNumericDefaultArguments = !(bool) count(array_filter(array_keys($defaultArguments), 'is_string')); foreach ($arguments as $key => $argument) { - /** @var \ReflectionParameter $argument */ + /** @var ReflectionParameter $argument */ if ($isNumericDefaultArguments && array_key_exists($key, $defaultArguments)) { $argumentValues[$argument->name] = $this->getValueOfDefaultArgument($defaultArguments[$key]); } else if (array_key_exists($argument->name, $defaultArguments)) { @@ -823,41 +790,42 @@ private function getValueOfDefaultArgument($argumentConfig) { } /** - * @param \ReflectionParameter $argument + * @param ReflectionParameter $argument * @return object - * @throws InjectionException + * @throws InjectionException|UnexpectedValueException */ - private function getInstanceOfArgument(\ReflectionParameter $argument) { - if (!$argument->getClass()) { + private function getInstanceOfArgument(ReflectionParameter $argument) { + $className = ReflectionClassHelper::getClassNameFromReflectionParameter($argument); + if (!$className) { if ($argument->isOptional()) { return $argument->getDefaultValue(); } throw new InjectionException('Invalid argument without class typehint class: [' . $argument->getDeclaringClass()->name . '] method: [' . $argument->getDeclaringFunction()->name . '] argument: [' . $argument->name . ']'); } - $argumentClassConfig = $this->config->getClassConfig($argument->getClass()->name); + $argumentClassConfig = $this->config->getClassConfig($className); $arguments = $this->getParamsFromTypeHint($argument); - $providedInstance = $this->getNamedProvidedInstance($argument->getClass()->name, $argumentClassConfig, $argument->getDeclaringFunction()->getDocComment(), $argument->name, $arguments); + $providedInstance = $this->getNamedProvidedInstance($className, $argumentClassConfig, $argument->getDeclaringFunction()->getDocComment(), $argument->name, $arguments); if ($providedInstance) { return $providedInstance; } - $namedClassName = $this->getNamedClassOfArgument($argument->getClass()->name, $argument->getDeclaringFunction()->getDocComment(), $argument->name); + $namedClassName = $this->getNamedClassOfArgument($className, $argument->getDeclaringFunction()->getDocComment(), $argument->name); if ($namedClassName) { return $this->getInstanceOfClass($namedClassName, $arguments); } - return $this->getInstanceOfClass($argument->getClass()->name, $arguments); + return $this->getInstanceOfClass($className, $arguments); } /** - * @param \ReflectionParameter $argument + * @param ReflectionParameter $argument * @return array */ - public function getParamsFromTypeHint(\ReflectionParameter $argument) { + public function getParamsFromTypeHint(ReflectionParameter $argument) { return $this->annotationReader->getParamsFromTypeHint($argument->getDeclaringFunction()->getDocComment(), $argument->name, 'param'); } diff --git a/src/rg/injektor/ReflectionClassHelper.php b/src/rg/injektor/ReflectionClassHelper.php new file mode 100644 index 0000000..3a8d5cc --- /dev/null +++ b/src/rg/injektor/ReflectionClassHelper.php @@ -0,0 +1,40 @@ +getType(); + if ($reflectionType === null) { + return null; + } elseif ($reflectionType instanceof ReflectionNamedType) { + if ($reflectionType->isBuiltin() === false) { + return $reflectionType->getName(); + } + } elseif (method_exists($reflectionType, 'getTypes')) { + foreach($reflectionType->getTypes() as $type) { + if ($type->isBuiltin() === false) { + return $type->getName(); + } + } + } else { + throw new UnexpectedValueException('Unsupported Reflection type: ' . get_class($reflectionType)); + } + + return null; + } +} diff --git a/src/rg/injektor/SimpleAnnotationReader.php b/src/rg/injektor/SimpleAnnotationReader.php index e492170..8dac1e2 100644 --- a/src/rg/injektor/SimpleAnnotationReader.php +++ b/src/rg/injektor/SimpleAnnotationReader.php @@ -22,11 +22,11 @@ public function getClassFromVarTypeHint($docComment) { /** * @param string $docComment * @param string $tag - * @return string mixed + * @return string|null */ - private function getClassFromTypeHint($docComment, $tag) { + private function getClassFromTypeHint($docComment, $tag): ?string { $matches = array(); - preg_match('/' . $tag . '\s([a-zA-Z0-9\_\\\\\[\\]]+)/', $docComment, $matches); + preg_match('/' . $tag . '\s([a-zA-Z0-9_\\\\\[\\]]+)/', $docComment, $matches); if (isset($matches[1])) { return $matches[1]; } diff --git a/src/rg/injektor/generators/InjectionParameter.php b/src/rg/injektor/generators/InjectionParameter.php index 9e792f5..b0a324f 100644 --- a/src/rg/injektor/generators/InjectionParameter.php +++ b/src/rg/injektor/generators/InjectionParameter.php @@ -9,7 +9,14 @@ */ namespace rg\injektor\generators; +use ReflectionClass; +use ReflectionException; +use ReflectionParameter; +use rg\injektor\Configuration; +use rg\injektor\DependencyInjectionContainer; +use rg\injektor\FactoryDependencyInjectionContainer; use rg\injektor\InjectionException; +use rg\injektor\ReflectionClassHelper; class InjectionParameter { @@ -17,35 +24,20 @@ class InjectionParameter { const MODE_NUMERIC = 'numeric'; const MODE_STRING = 'string'; - /** - * @var \ReflectionParameter - */ - private $parameter; + private ReflectionParameter $parameter; - /** - * @var array - */ - protected $classConfig; + protected array $classConfig; - /** - * @var \rg\injektor\Configuration - */ - protected $config; + protected Configuration $config; /** - * @var \rg\injektor\FactoryDependencyInjectionContainer + * @var FactoryDependencyInjectionContainer */ protected $dic; - /** - * @var string - */ - protected $factoryName; + protected ?string $factoryName = null; - /** - * @var string - */ - protected $className; + protected ?string $className = null; protected $defaultValue; @@ -59,10 +51,13 @@ class InjectionParameter { protected $mode; - public function __construct(\ReflectionParameter $parameter, array $classConfig, - \rg\injektor\Configuration $config, - \rg\injektor\DependencyInjectionContainer $dic, - $mode) { + public function __construct( + ReflectionParameter $parameter, + array $classConfig, + Configuration $config, + DependencyInjectionContainer $dic, + $mode) + { $this->parameter = $parameter; $this->classConfig = $classConfig; $this->config = $config; @@ -81,7 +76,7 @@ public function getName() { return $this->name; } - public function getProcessingBody() { + public function getProcessingBody(): string { if ($this->mode === self::MODE_NO_ARGUMENTS) { return '$' . $this->name . ' = ' . $this->defaultValue . ';' . PHP_EOL; } else if ($this->mode === self::MODE_NUMERIC) { @@ -90,7 +85,7 @@ public function getProcessingBody() { return '$' . $this->name . ' = array_key_exists(\'' . $this->name . '\', $parameters) ? $parameters[\'' . $this->name . '\'] : ' . $this->defaultValue . ';' . PHP_EOL; } - public function getDefaultProcessingBody() { + public function getDefaultProcessingBody(): string { if ($this->mode === self::MODE_NO_ARGUMENTS) { return '$' . $this->name . ' = null;' . PHP_EOL; } else if ($this->mode === self::MODE_NUMERIC) { @@ -99,6 +94,9 @@ public function getDefaultProcessingBody() { return '$' . $this->name . ' = array_key_exists(\'' . $this->name . '\', $parameters) ? $parameters[\'' . $this->name . '\'] : null;' . PHP_EOL; } + /** + * @throws ReflectionException + */ protected function analyze() { $argumentClass = null; @@ -128,7 +126,7 @@ protected function analyze() { if ($argumentClass === 'rg\injektor\DependencyInjectionContainer') { $this->defaultValue = '\\' . $argumentClass . '::getDefaultInstance()'; } else { - $providerClassName = $this->dic->getProviderClassName($this->config->getClassConfig($argumentClass), new \ReflectionClass($argumentClass), + $providerClassName = $this->dic->getProviderClassName($this->config->getClassConfig($argumentClass), new ReflectionClass($argumentClass), $this->dic->getImplementationName($this->docComment, $this->nameForAnnotationParsing)); if ($providerClassName && $providerClassName->getClassName()) { $argumentFactory = $this->dic->getFullFactoryClassName($providerClassName->getClassName()); @@ -136,9 +134,9 @@ protected function analyze() { $this->factoryName = $argumentFactory; $this->defaultValue = '\\' . $argumentFactory . '::getInstance(' . var_export(array_merge($providerClassName->getParameters(), $this->additionalArguments), true) . ')->get()'; } else { - $argumentClass = $this->dic->getRealConfiguredClassName($this->config->getClassConfig($argumentClass), new \ReflectionClass($argumentClass)); + $argumentClass = $this->dic->getRealConfiguredClassName($this->config->getClassConfig($argumentClass), new ReflectionClass($argumentClass)); - $argumentClassReflection = new \ReflectionClass($argumentClass); + $argumentClassReflection = new ReflectionClass($argumentClass); if (! $argumentClassReflection->isInstantiable() && ! $argumentClassReflection->hasMethod('getInstance')) { $this->setParameterToDefault(); return; @@ -172,16 +170,19 @@ protected function hasDefaultValue() { return $this->parameter->isDefaultValueAvailable(); } + /** + * @throws ReflectionException + */ protected function getDefaultValue() { return $this->parameter->getDefaultValue(); } - protected function hasClass() { - return $this->parameter->getClass(); + protected function hasClass(): bool { + return ReflectionClassHelper::getClassNameFromReflectionParameter($this->parameter) !== null; } - protected function getClass() { - return $this->parameter->getClass()->name; + protected function getClass(): ?string { + return ReflectionClassHelper::getClassNameFromReflectionParameter($this->parameter); } public function getFactoryName() { diff --git a/src/rg/injektor/generators/InjectionProperty.php b/src/rg/injektor/generators/InjectionProperty.php index 7805320..5ac0215 100644 --- a/src/rg/injektor/generators/InjectionProperty.php +++ b/src/rg/injektor/generators/InjectionProperty.php @@ -9,19 +9,22 @@ */ namespace rg\injektor\generators; -use rg\injektor\InjectionException; +use ReflectionProperty; +use rg\injektor\Configuration; +use rg\injektor\DependencyInjectionContainer; +use const PHP_VERSION_ID; class InjectionProperty extends InjectionParameter { - /** - * @var \ReflectionProperty - */ - private $property; + private ReflectionProperty $property; - - public function __construct(\ReflectionProperty $property, array $classConfig, - \rg\injektor\Configuration $config, - \rg\injektor\DependencyInjectionContainer $dic) { + public function __construct( + ReflectionProperty $property, + array $classConfig, + Configuration $config, + DependencyInjectionContainer $dic + ) + { $this->property = $property; $this->classConfig = $classConfig; $this->config = $config; @@ -33,23 +36,27 @@ public function __construct(\ReflectionProperty $property, array $classConfig, $this->analyze(); } - protected function hasDefaultValue() { + protected function hasDefaultValue(): bool { return (boolean) $this->getDefaultValue(); } protected function getDefaultValue() { - return $this->property->getValue(); + if (PHP_VERSION_ID >= 80000) { + return $this->property->getDefaultValue(); + } else { + return $this->property->getValue(); + } } - protected function hasClass() { + protected function hasClass(): bool { return (boolean) $this->getClass(); } - protected function getClass() { + protected function getClass(): ?string { return $this->dic->getFullClassNameBecauseOfImports($this->property, $this->dic->getClassFromProperty($this->property)); } - public function getProcessingBody() { + public function getProcessingBody(): string { return '$this->' . $this->name . ' = ' . $this->defaultValue . ';' . PHP_EOL; } diff --git a/test/rg/injektor/DependencyInjectionContainerTest.php b/test/rg/injektor/DependencyInjectionContainerTest.php index 994e7a1..2308054 100644 --- a/test/rg/injektor/DependencyInjectionContainerTest.php +++ b/test/rg/injektor/DependencyInjectionContainerTest.php @@ -9,11 +9,12 @@ */ namespace rg\injektor; +use PHPUnit\Framework\TestCase; use const PHP_VERSION_ID; include_once 'test_classes.php'; -class DependencyInjectionContainerTest extends \PHPUnit\Framework\TestCase { +class DependencyInjectionContainerTest extends TestCase { public function testGetInstance() { $config = new Configuration(null, __DIR__ . '/_factories'); @@ -328,13 +329,6 @@ public function testGetInstanceWithConfiguredParameter() { ], ]); - [ - 'keywords' => [ - 123, - 456 - ] - ]; - $dic = $this->getContainer($config); $instance = $dic->getInstanceOfClass('rg\injektor\DICTestClassNoTypeHint'); @@ -488,7 +482,7 @@ public function testCallMethodWithoutParametersOnObject() { public function testAnnotatedSingleton() { $config = new Configuration(null, __DIR__ . '/_factories'); - ; + $dic = $this->getContainer($config); $instanceOne = $dic->getInstanceOfClass('rg\injektor\DICTestAnnotatedSingleton'); @@ -836,11 +830,6 @@ public function testPropertyInjectionWithUseStatement() { } public function test_getInstanceOfClass_givenClassWithTypedProperties_injectsCorrectClassesIntoProperties() { - if (PHP_VERSION_ID < 70400) { - $this->markTestSkipped('Needs PHP 7.4 or higher'); - } - include_once 'test_classes_php74.php'; - $config = new Configuration(null, __DIR__ . '/_factories'); $dic = $this->getContainer($config); @@ -854,18 +843,34 @@ public function test_getInstanceOfClass_givenClassWithTypedProperties_injectsCor $this->assertInstanceOf('rg\injektor\DICTestClassThree', $instance->three); } + public function test_getInstanceOfClass_givenClassWithUnionTypedProperties_injectsCorrectClassesIntoProperties() { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Needs PHP 8.0 or higher'); + } + include_once 'test_classes_php80.php'; + + $config = new Configuration(null, __DIR__ . '/_factories'); + + $dic = $this->getContainer($config); + + $instance = $dic->getInstanceOfClass('rg\injektor\DICTestClassWithUnionTypedProperties'); + + $this->assertInstanceOf('rg\injektor\DICTestClassWithUnionTypedProperties', $instance); + + $this->assertInstanceOf('rg\injektor\DICTestClassOne', $instance->one); + $this->assertInstanceOf('rg\injektor\DICTestClassTwo', $instance->two); + $this->assertInstanceOf('rg\injektor\DICTestClassThree', $instance->three); + } + public function testClearDoesNotThrow() { $config = new Configuration(null, __DIR__ . '/_factories'); $dic = $this->getContainer($config); - $this->assertNull($dic->clear()); + $dic->clear(); + $this->assertTrue(true); } - /** - * @param Configuration $config - * @return DependencyInjectionContainer - */ - public function getContainer(Configuration $config) { + public function getContainer(Configuration $config): DependencyInjectionContainer { return new DependencyInjectionContainer($config); } } diff --git a/test/rg/injektor/FactoryOnlyDependencyInjectionContainerTest.php b/test/rg/injektor/FactoryOnlyDependencyInjectionContainerTest.php index 288bcdf..130843f 100644 --- a/test/rg/injektor/FactoryOnlyDependencyInjectionContainerTest.php +++ b/test/rg/injektor/FactoryOnlyDependencyInjectionContainerTest.php @@ -9,9 +9,10 @@ */ namespace rg\injektor; -use Laminas\Code\Reflection\FileReflection; use rg\injektor\generators\WritingFactoryGenerator; -use const PHP_VERSION_ID; +use Roave\BetterReflection\BetterReflection; +use Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator; +use function class_exists; require_once 'DependencyInjectionContainerTest.php'; @@ -25,17 +26,13 @@ public function setUp(): void { FactoryDependencyInjectionContainer::$prefix = 'a' . uniqid(); } - /** - * @param Configuration $config - * @return FactoryDependencyInjectionContainer - */ - public function getContainer(Configuration $config) { + public function getContainer(Configuration $config): FactoryOnlyDependencyInjectionContainer { $generator = new WritingFactoryGenerator($config, __DIR__ . '/_factories'); $this->processClassesOfFile(__DIR__ . '/test_classes.php', $generator); - if (PHP_VERSION_ID >= 70400) { - $this->processClassesOfFile(__DIR__ . '/test_classes_php74.php', $generator); + if (PHP_VERSION_ID >= 80000) { + $this->processClassesOfFile(__DIR__ . '/test_classes_php80.php', $generator); } return new FactoryOnlyDependencyInjectionContainer($config); @@ -51,8 +48,17 @@ public static function tearDownAfterClass(): void { private function processClassesOfFile(string $fileName, WritingFactoryGenerator $generator): void { - $fileReflection = new FileReflection($fileName); - $classes = $fileReflection->getClasses(); + require_once $fileName; + + $astLocator = (new BetterReflection())->astLocator(); + // bc break between v4 and v5. Can be switched to DefaultReflector fully when min version is PHP 8.0 + if (class_exists(\Roave\BetterReflection\Reflector\ClassReflector::class)) { + $reflector = new \Roave\BetterReflection\Reflector\ClassReflector(new SingleFileSourceLocator($fileName, $astLocator)); + $classes = $reflector->getAllClasses(); + } else { + $reflector = new \Roave\BetterReflection\Reflector\DefaultReflector(new SingleFileSourceLocator($fileName, $astLocator)); + $classes = $reflector->reflectAllClasses(); + } foreach ($classes as $class) { $generator->processFileForClass($class->getName()); } diff --git a/test/rg/injektor/generators/FactoryGeneratorTest.php b/test/rg/injektor/generators/FactoryGeneratorTest.php index dc1467f..42d9308 100644 --- a/test/rg/injektor/generators/FactoryGeneratorTest.php +++ b/test/rg/injektor/generators/FactoryGeneratorTest.php @@ -58,7 +58,6 @@ public function provider() { class rg_injektor_generators_FGTestClassSimpleFactory { - public static function getInstance(array \$parameters = []) { \$i = 0; @@ -66,8 +65,6 @@ public static function getInstance(array \$parameters = []) \$instance = new \\rg\\injektor\\generators\\FGTestClassSimple(); return \$instance; } - - } @@ -82,19 +79,15 @@ public static function getInstance(array \$parameters = []) class rg_injektor_generators_FGTestClassFourProxy extends \\rg\injektor\generators\\FGTestClassFour { - public function propertyInjectioninjectedProperty() { \$this->injectedProperty = \\rg\injektor\\generated\\rg_injektor_generators_FGTestClassSimpleFactory::getInstance(array ( )); } - - } class rg_injektor_generators_FGTestClassFourFactory { - private static \$instance = []; public static function getInstance(array \$parameters = []) @@ -145,8 +138,6 @@ public static function callGetInstance(\$object, array \$parameters = []) return \$result; } - - } @@ -161,7 +152,6 @@ public static function callGetInstance(\$object, array \$parameters = []) class rg_injektor_generators_FGTestClassThreeFactory { - public static function getInstance(array \$parameters = []) { \$i = 0; @@ -193,8 +183,6 @@ public static function callGetSomething(\$object) return \$result; } - - } @@ -210,7 +198,6 @@ public static function callGetSomething(\$object) class rg_injektor_generators_FGTestClassTwoFactory { - public static function getInstance(array \$parameters = []) { \$i = 0; @@ -239,8 +226,6 @@ public static function callGetSomething(\$object) return \$result; } - - } @@ -256,19 +241,15 @@ public static function callGetSomething(\$object) class rg_injektor_generators_FGTestClassOneProxy extends \\rg\\injektor\\generators\\FGTestClassOne { - public function propertyInjectionfour() { \$this->four = \\rg\injektor\\generated\\rg_injektor_generators_FGTestClassThreeFactory::getInstance(array ( )); } - - } class rg_injektor_generators_FGTestClassOneFactory { - private static \$instance = []; public static function getInstance(array \$parameters = []) @@ -397,8 +378,6 @@ public static function callMethodRestriction(\$object, array \$parameters = []) return \$result; } - - } diff --git a/test/rg/injektor/test_classes.php b/test/rg/injektor/test_classes.php index 20e2fd0..b6545e7 100644 --- a/test/rg/injektor/test_classes.php +++ b/test/rg/injektor/test_classes.php @@ -411,7 +411,7 @@ private function __construct($foo, $instance) { * @inject * @static * @param DICTestClassNoConstructor $instance - * @return Singleton + * @return DICTestSingleton */ public static function getInstance(DICTestClassNoConstructor $instance) { return new static('foo', $instance); @@ -705,6 +705,24 @@ public function __construct(DICTestInterface $interface = null) { $this->interface = $interface; } } + + class DICTestClassWithTypedProperties { + + /** + * @inject + */ + public DICTestClassOne $one; + + /** + * @inject + */ + public \rg\injektor\DICTestClassTwo $two; + + /** + * @inject + */ + public ?DICTestClassThree $three; + } } namespace { diff --git a/test/rg/injektor/test_classes_php74.php b/test/rg/injektor/test_classes_php80.php similarity index 62% rename from test/rg/injektor/test_classes_php74.php rename to test/rg/injektor/test_classes_php80.php index dc24e36..eb904d8 100644 --- a/test/rg/injektor/test_classes_php74.php +++ b/test/rg/injektor/test_classes_php80.php @@ -9,23 +9,25 @@ */ namespace rg\injektor { + use PHPUnit\Framework\MockObject\MockObject; + require_once 'test_classes.php'; - class DICTestClassWithTypedProperties { + class DICTestClassWithUnionTypedProperties { /** * @inject */ - public DICTestClassOne $one; + public DICTestClassOne|MockObject $one; /** * @inject */ - public \rg\injektor\DICTestClassTwo $two; + public \rg\injektor\DICTestClassTwo|MockObject $two; /** * @inject */ - public ?DICTestClassThree $three; + public DICTestClassThree|MockObject|null $three; } }