[!!!][TASK] Remove non-public extbase property injection 21/63821/8
authorAlexander Schnitzler <git@alexanderschnitzler.de>
Fri, 20 Mar 2020 16:10:41 +0000 (17:10 +0100)
committerBenni Mack <benni@typo3.org>
Wed, 3 Jun 2020 09:51:29 +0000 (11:51 +0200)
The property injection with non-public properties had been
deprecated with #82975 and has been forgotten to be removed
until now. With this patch only public properties can be
used for extbase dependency injection.

Releases: master
Resolves: #90799
Change-Id: I21d4b8bcdd07a20ba9ad7ebd87465cc291572bba
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63821
Tested-by: Benjamin Franzke <bfr@qbus.de>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Benjamin Franzke <bfr@qbus.de>
Reviewed-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Breaking-90799-DependencyInjectionWithNonPublicPropertiesHasBeenRemoved.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php
typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
typo3/sysext/extbase/Classes/Object/Container/Container.php
typo3/sysext/extbase/Classes/Reflection/ClassSchema.php
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/BlogController.php
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php
typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-90799-DependencyInjectionWithNonPublicPropertiesHasBeenRemoved.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-90799-DependencyInjectionWithNonPublicPropertiesHasBeenRemoved.rst
new file mode 100644 (file)
index 0000000..db15d3c
--- /dev/null
@@ -0,0 +1,63 @@
+.. include:: ../../Includes.txt
+
+===================================================================================
+Breaking: #90799 - Dependency injection with non-public properties has been removed
+===================================================================================
+
+See :issue:`90799`
+
+Description
+===========
+
+In TYPO3 9.5, the (dependency) injection via `@inject` has been deprecated for
+non public properties. The reason was to avoid having the core use the PHP reflection
+api to make non public properties writable from outside the class scope. Since there
+are other methods for dependency injection (constructor/setter injection), injection
+into non public properties has now been removed
+
+
+Impact
+======
+
+Non public properties with inject annotations will no longer trigger extbase
+dependency injection. Those properties will have their default state after object
+instantiation.
+
+
+Affected Installations
+======================
+
+All installations that use non public properties for extbase dependency injection
+as seen in this example:
+
+.. code-block:: php
+
+   class Foo
+   {
+       /**
+        * @var Service
+        * @TYPO3\CMS\Extbase\Annotation\Inject
+        */
+       private $service;
+   }
+
+
+Migration
+=========
+
+When not using constructor/setter injection instead, switch to inject methods
+(recommended for compatibility with symfony depenency injection) or mark the
+property public (works with extbase depenency injection only):
+
+.. code-block:: php
+
+   class Foo
+   {
+       /**
+        * @var Service
+        * @TYPO3\CMS\Extbase\Annotation\Inject
+        */
+       public $service;
+   }
+
+.. index:: PHP-API, NotScanned, ext:extbase
index 562d542..c3d25a6 100644 (file)
@@ -33,7 +33,7 @@ abstract class AbstractController extends ActionController
      * @Extbase\Inject
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    protected $dataMapFactory;
+    public $dataMapFactory;
 
     /**
      * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request
index 436ced9..0b3ee08 100644 (file)
@@ -28,7 +28,7 @@ class ContentController extends AbstractController
      * @Extbase\Inject
      * @var \OliverHader\IrreTutorial\Domain\Repository\ContentRepository
      */
-    protected $contentRepository;
+    public $contentRepository;
 
     /**
      * @var string
index 7307e42..9750371 100644 (file)
@@ -30,7 +30,7 @@ class QueueController extends AbstractController
      * @Extbase\Inject
      * @var \OliverHader\IrreTutorial\Domain\Repository\ContentRepository
      */
-    protected $contentRepository;
+    public $contentRepository;
 
     /**
      * @var string
index 6140684..3a56ed0 100644 (file)
@@ -226,13 +226,7 @@ class Container implements SingletonInterface, LoggerAwareInterface
                 $this->logger->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.');
             }
 
-            if ($classSchema->getProperty($injectPropertyName)->isPublic()) {
-                $instance->{$injectPropertyName} = $instanceToInject;
-            } else {
-                $propertyReflection = new \ReflectionProperty($instance, $injectPropertyName);
-                $propertyReflection->setAccessible(true);
-                $propertyReflection->setValue($instance, $instanceToInject);
-            }
+            $instance->{$injectPropertyName} = $instanceToInject;
         }
     }
 
index eb2d55e..c3d804a 100644 (file)
@@ -244,7 +244,7 @@ class ClassSchema
                 $propertyCharacteristicsBit += PropertyCharacteristics::ANNOTATED_TRANSIENT;
             }
 
-            $isInjectProperty = $propertyName !== 'settings'
+            $isInjectProperty = $propertyName !== 'settings' && $reflectionProperty->isPublic()
                 && ($annotationReader->getPropertyAnnotation($reflectionProperty, Inject::class) instanceof Inject);
 
             if ($isInjectProperty) {
index 6d4739a..d7a4d90 100644 (file)
@@ -34,7 +34,7 @@ class BlogController extends ActionController
      * @Extbase\Inject
      * @var \ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository
      */
-    protected $blogRepository;
+    public $blogRepository;
 
     /**
      * @var string
@@ -45,7 +45,7 @@ class BlogController extends ActionController
      * @Extbase\Inject
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    protected $dataMapFactory;
+    public $dataMapFactory;
 
     public function listAction()
     {
index a422001..8febc3b 100644 (file)
@@ -35,7 +35,7 @@ class ContentController extends ActionController
      * @Extbase\Inject
      * @var \ExtbaseTeam\BlogExample\Domain\Repository\TtContentRepository
      */
-    protected $contentRepository;
+    public $contentRepository;
 
     /**
      * @var string
@@ -46,7 +46,7 @@ class ContentController extends ActionController
      * @Extbase\Inject
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    protected $dataMapFactory;
+    public $dataMapFactory;
 
     /**
      * @return array
index 8db14fb..4b25b3b 100644 (file)
@@ -30,7 +30,6 @@ use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\MandatoryConstructorA
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\MandatoryConstructorArgumentTwo;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\NamespacedClass;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\OptionalConstructorArgument;
-use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ProtectedPropertyInjectClass;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\PublicPropertyInjectClass;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\SimpleTypeConstructorArgument;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\TwoConstructorArgumentsBothOptional;
@@ -968,13 +967,4 @@ class ContainerTest extends UnitTestCase
         $object = $this->subject->getInstance(PublicPropertyInjectClass::class);
         self::assertInstanceOf(ArgumentTestClassForPublicPropertyInjection::class, $object->foo);
     }
-
-    /**
-     * @test
-     */
-    public function getInstanceInjectsProtectedProperties()
-    {
-        $object = $this->subject->getInstance(ProtectedPropertyInjectClass::class);
-        self::assertInstanceOf(ArgumentTestClassForPublicPropertyInjection::class, $object->getFoo());
-    }
 }