From 3436317973ad1f703916a0a82ee16d5dd57efeb4 Mon Sep 17 00:00:00 2001 From: Alexander Schnitzler <git@alexanderschnitzler.de> Date: Wed, 29 Nov 2017 11:08:35 +0100 Subject: [PATCH] [BUGFIX] Avoid reflection for public property injection The property injection in the ObjectContainer always did reflect the object and made the property accessible, even if the property was public and therefore accessible by default. With this patch, reflection is avoided for public properties which increases the performance of public property injection a lot. Releases: master, 8.7 Resolves: #83155 Change-Id: I32f7c8e257f65da4a2fce1d7ee515d7954564387 Reviewed-on: https://review.typo3.org/54850 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Claus Due <claus@phpmind.net> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl> Reviewed-by: Susanne Moog <susanne.moog@typo3.org> Tested-by: Susanne Moog <susanne.moog@typo3.org> --- .../Classes/Object/Container/Container.php | 10 ++++-- .../Unit/Object/Container/ContainerTest.php | 24 +++++++++++++ .../ContainerPropertyInjectionTestClasses.php | 34 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php diff --git a/typo3/sysext/extbase/Classes/Object/Container/Container.php b/typo3/sysext/extbase/Classes/Object/Container/Container.php index 4d7682525385..24a86b2bae6f 100644 --- a/typo3/sysext/extbase/Classes/Object/Container/Container.php +++ b/typo3/sysext/extbase/Classes/Object/Container/Container.php @@ -212,10 +212,14 @@ class Container implements \TYPO3\CMS\Core\SingletonInterface if ($classSchema->isSingleton() && !$instanceToInject instanceof \TYPO3\CMS\Core\SingletonInterface) { $this->getLogger()->notice('The singleton "' . $classSchema->getClassName() . '" needs a prototype in "' . $injectPropertyName . '". This is often a bad code smell; often you rather want to inject a singleton.'); } - $propertyReflection = new \ReflectionProperty($instance, $injectPropertyName); - $propertyReflection->setAccessible(true); - $propertyReflection->setValue($instance, $instanceToInject); + if ($classSchema->getProperty($injectPropertyName)['public']) { + $instance->{$injectPropertyName} = $instanceToInject; + } else { + $propertyReflection = new \ReflectionProperty($instance, $injectPropertyName); + $propertyReflection->setAccessible(true); + $propertyReflection->setValue($instance, $instanceToInject); + } } } diff --git a/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php b/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php index 91ef94bb8a03..735093f4841d 100644 --- a/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php @@ -15,9 +15,13 @@ namespace TYPO3\CMS\Extbase\Tests\Unit\Object\Container; */ use Psr\Log\LoggerInterface; use TYPO3\CMS\Core\Log\Logger; +use TYPO3\CMS\Extbase\Object\Container\Container; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Extbase\Object\Exception\CannotBuildObjectException; use TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException; +use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection; +use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ProtectedPropertyInjectClass; +use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\PublicPropertyInjectClass; /** * Test case @@ -953,4 +957,24 @@ class ContainerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $object->argumentTestClassTwo ); } + + /** + * @test + */ + public function getInstanceInjectsPublicProperties() + { + $container = new Container(); + $object = $container->getInstance(PublicPropertyInjectClass::class); + self::assertInstanceOf(ArgumentTestClassForPublicPropertyInjection::class, $object->foo); + } + + /** + * @test + */ + public function getInstanceInjectsProtectedProperties() + { + $container = new Container(); + $object = $container->getInstance(ProtectedPropertyInjectClass::class); + self::assertInstanceOf(ArgumentTestClassForPublicPropertyInjection::class, $object->getFoo()); + } } diff --git a/typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php b/typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php new file mode 100644 index 000000000000..f81af86fc2f1 --- /dev/null +++ b/typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php @@ -0,0 +1,34 @@ +<?php +declare(strict_types=1); + +namespace TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures; + +use TYPO3\CMS\Extbase\Annotation\Inject; + +class PublicPropertyInjectClass +{ + /** + * @Inject + * @var \TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection + */ + public $foo; +} + +class ArgumentTestClassForPublicPropertyInjection +{ +} + +class ProtectedPropertyInjectClass +{ + + /** + * @Inject + * @var \TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection + */ + protected $foo; + + public function getFoo() + { + return $this->foo; + } +} -- GitLab