Skip to content

Commit

Permalink
Support injection into typed properties
Browse files Browse the repository at this point in the history
  • Loading branch information
mdio committed Feb 1, 2022
1 parent 4e7165c commit 9a386c0
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 16 deletions.
25 changes: 18 additions & 7 deletions src/rg/injektor/DependencyInjectionContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
use ProxyManager\Proxy\LazyLoadingInterface;
use Psr\Log\LoggerInterface;
use ReflectionNamedType;
use ReflectionProperty;
use rg\injektor\annotations\Named;
use const PHP_VERSION_ID;

/**
* @implementedBy rg\injektor\FactoryDependencyInjectionContainer
Expand Down Expand Up @@ -400,9 +403,9 @@ public function getInjectableProperties($classReflection) {
* @throws InjectionException
*/
private function injectProperty($property, $instance) {
$fullClassName = $this->getClassFromVarTypeHint($property->getDocComment());
$fullClassName = $this->getClassFromProperty($property);
if (!$fullClassName) {
throw new InjectionException('Expected tag @var not found in doc comment.');
throw new InjectionException('Expected tag @var not found in doc comment. A typed property was also not found.');
}

$fullClassName = $this->getFullClassNameBecauseOfImports($property, $fullClassName);
Expand Down Expand Up @@ -454,12 +457,20 @@ public function getFullClassNameBecauseOfImports($property, $fullClassName) {
}

/**
* @param string $docComment
* @return string
* @throws InjectionException
* @param ReflectionProperty $property
* @return string|null
*/
public function getClassFromVarTypeHint($docComment) {
return $this->annotationReader->getClassFromVarTypeHint($docComment);
public function getClassFromProperty($property) {
$fullClassName = $this->annotationReader->getClassFromVarTypeHint($property->getDocComment());

if (!$fullClassName && PHP_VERSION_ID >= 70400) {
$namedType = $property->getType();
if ($namedType instanceof ReflectionNamedType && $namedType->getName()) {
$fullClassName = '\\' . $namedType->getName();
}
}

return $fullClassName;
}

/**
Expand Down
2 changes: 0 additions & 2 deletions src/rg/injektor/SimpleAnnotationReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class SimpleAnnotationReader {
/**
* @param string $docComment
* @return string
* @throws InjectionException
*/
public function getClassFromVarTypeHint($docComment) {
return $this->getClassFromTypeHint($docComment, '@var');
Expand All @@ -24,7 +23,6 @@ public function getClassFromVarTypeHint($docComment) {
* @param string $docComment
* @param string $tag
* @return string mixed
* @throws InjectionException
*/
private function getClassFromTypeHint($docComment, $tag) {
$matches = array();
Expand Down
2 changes: 1 addition & 1 deletion src/rg/injektor/generators/FileGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ private function injectProperties(array $classConfig, \ReflectionClass $classRef
$this->injectableProperties = $this->dic->getInjectableProperties($classReflection);
foreach ($this->injectableProperties as $key => $injectableProperty) {
/** @var \ReflectionProperty $injectableProperty */
$propertyClass = $this->dic->getClassFromVarTypeHint($injectableProperty->getDocComment());
$propertyClass = $this->dic->getClassFromProperty($injectableProperty);
if (!$propertyClass) {
unset($this->injectableProperties[$key]);
continue;
Expand Down
2 changes: 1 addition & 1 deletion src/rg/injektor/generators/InjectionProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected function hasClass() {
}

protected function getClass() {
return $this->dic->getFullClassNameBecauseOfImports($this->property, $this->dic->getClassFromVarTypeHint($this->docComment));
return $this->dic->getFullClassNameBecauseOfImports($this->property, $this->dic->getClassFromProperty($this->property));
}

public function getProcessingBody() {
Expand Down
21 changes: 21 additions & 0 deletions test/rg/injektor/DependencyInjectionContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
namespace rg\injektor;

use const PHP_VERSION_ID;

include_once 'test_classes.php';

class DependencyInjectionContainerTest extends \PHPUnit\Framework\TestCase {
Expand Down Expand Up @@ -833,6 +835,25 @@ public function testPropertyInjectionWithUseStatement() {
$this->assertInstanceOf('rg\injektor\DICTestClassThatAlsoExistsInPublicNamespace', $instance->dependencyWithOtherClassInPublicNamespace);
}

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);

$instance = $dic->getInstanceOfClass('rg\injektor\DICTestClassWithTypedProperties');

$this->assertInstanceOf('rg\injektor\DICTestClassWithTypedProperties', $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);
Expand Down
20 changes: 15 additions & 5 deletions test/rg/injektor/FactoryOnlyDependencyInjectionContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
*/
namespace rg\injektor;

use Laminas\Code\Reflection\FileReflection;
use rg\injektor\generators\WritingFactoryGenerator;
use const PHP_VERSION_ID;

require_once 'DependencyInjectionContainerTest.php';

Expand All @@ -30,11 +32,10 @@ public function setUp(): void {
public function getContainer(Configuration $config) {
$generator = new WritingFactoryGenerator($config, __DIR__ . '/_factories');

$fileReflection = new \Laminas\Code\Reflection\FileReflection(__DIR__ . '/test_classes.php');
$classes = $fileReflection->getClasses();
foreach ($classes as $class) {
/** @var \ReflectionClass $class */
$generator->processFileForClass($class->getName());
$this->processClassesOfFile(__DIR__ . '/test_classes.php', $generator);

if (PHP_VERSION_ID >= 70400) {
$this->processClassesOfFile(__DIR__ . '/test_classes_php74.php', $generator);
}

return new FactoryOnlyDependencyInjectionContainer($config);
Expand All @@ -47,4 +48,13 @@ public function tearDown(): void {
public static function tearDownAfterClass(): void {
WritingFactoryGenerator::cleanUpGenerationDirectory(__DIR__ . '/_factories');
}

private function processClassesOfFile(string $fileName, WritingFactoryGenerator $generator): void
{
$fileReflection = new FileReflection($fileName);
$classes = $fileReflection->getClasses();
foreach ($classes as $class) {
$generator->processFileForClass($class->getName());
}
}
}
31 changes: 31 additions & 0 deletions test/rg/injektor/test_classes_php74.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/*
* This file is part of rg\injektor.
*
* (c) ResearchGate GmbH <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace rg\injektor {

require_once 'test_classes.php';

class DICTestClassWithTypedProperties {

/**
* @inject
*/
public DICTestClassOne $one;

/**
* @inject
*/
public \rg\injektor\DICTestClassTwo $two;

/**
* @inject
*/
public ?DICTestClassThree $three;
}
}

0 comments on commit 9a386c0

Please sign in to comment.