From 64c8a784c5bcd712049253b4ea492e7c0bcf6b24 Mon Sep 17 00:00:00 2001
From: Alexander Schnitzler <git@alexanderschnitzler.de>
Date: Wed, 23 Sep 2020 13:07:51 +0200
Subject: [PATCH] [TASK] Deprecate @Extbase\Inject

Since core dependency injection is in place and is about to
replace the extbase dependency injection, marking properties
with the @Extbase\Inject annotation to invoke property injection is
deprecated and must be replaced by one of the following di
methods:

- constructor injection: works both with core and extbase di
  and is well suited to make extensions compatible for multiple
  TYPO3 versions.

- setter injection: Basically the same like constructor injection.
  Both the core and extbase di can handle setter injection and
  both are supported in different TYPO3 versions.

- (core) property injection: This kind of injection can be used
  but it requires the configuration of services via a Services.yaml
  in the Configuration folder of an extension.

The recommended way is constructor injection. Not only is it the
most compatible version of di, it also brings the advantage of
clearly showing dependencies of a class. Also, it quickly shows
if dependencies stack up which indicates that the service should
be refactored.

Releases: master
Resolves: #92386
Change-Id: I61afbb6bb15b136c200849c6c8f2cd6211d4c306
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65835
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Benjamin Franzke <bfr@qbus.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Benjamin Franzke <bfr@qbus.de>
---
 composer.json                                 |  1 +
 ...6-ExtbasePropertyInjectionIsDeprecated.rst | 68 +++++++++++++++
 .../Classes/Controller/AbstractController.php |  7 +-
 .../Classes/Controller/ContentController.php  | 12 ++-
 .../Classes/Controller/QueueController.php    | 13 ++-
 .../irre_tutorial/Configuration/Services.yaml |  9 ++
 .../extbase/Classes/Annotation/Inject.php     |  1 +
 .../Classes/Reflection/ClassSchema.php        |  4 +
 .../Classes/Controller/BlogController.php     | 15 ++--
 .../Classes/Controller/ContentController.php  | 15 ++--
 .../blog_example/Configuration/Services.yaml  |  9 ++
 .../Unit/Object/Container/ContainerTest.php   | 11 ---
 .../Reflection/ClassSchema/PropertyTest.php   | 11 ---
 .../Tests/Unit/Reflection/ClassSchemaTest.php | 23 ------
 .../DummyClassWithAllTypesOfProperties.php    |  1 -
 .../Object/Container/ContainerTest.php        | 82 +++++++++++++++++++
 .../ContainerPropertyInjectionTestClasses.php |  6 +-
 .../Reflection/ClassSchema/PropertyTest.php   | 39 +++++++++
 .../Reflection/ClassSchemaTest.php            | 48 +++++++++++
 .../DummyClassWithAllTypesOfProperties.php}   | 17 ++--
 ...DummyClassWithInjectDoctrineAnnotation.php |  8 +-
 .../fluid_test/Configuration/Services.yaml    |  9 ++
 22 files changed, 330 insertions(+), 79 deletions(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Deprecation-92386-ExtbasePropertyInjectionIsDeprecated.rst
 create mode 100644 typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/Services.yaml
 create mode 100644 typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/Services.yaml
 create mode 100644 typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/ContainerTest.php
 rename typo3/sysext/extbase/Tests/{Unit => UnitDeprecated}/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php (71%)
 create mode 100644 typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchema/PropertyTest.php
 create mode 100644 typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchemaTest.php
 rename typo3/sysext/extbase/Tests/{Fixture/ClassWithInjectProperties.php => UnitDeprecated/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php} (61%)
 rename typo3/sysext/extbase/Tests/{Unit => UnitDeprecated}/Reflection/Fixture/DummyClassWithInjectDoctrineAnnotation.php (75%)
 create mode 100644 typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test/Configuration/Services.yaml

diff --git a/composer.json b/composer.json
index 5e7b3d52c8b6..4b72ec730681 100644
--- a/composer.json
+++ b/composer.json
@@ -267,6 +267,7 @@
 			"typo3/sysext/core/Tests/Unit/Core/Fixtures/test_extension/",
 			"typo3/sysext/core/Tests/Functional/Fixtures/",
 			"typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/",
+			"typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/Fixtures/",
 			"typo3/sysext/extbase/Tests/Functional/Fixtures/",
 			"typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test/Classes/"
 		],
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-92386-ExtbasePropertyInjectionIsDeprecated.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-92386-ExtbasePropertyInjectionIsDeprecated.rst
new file mode 100644
index 000000000000..715c53e636b8
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-92386-ExtbasePropertyInjectionIsDeprecated.rst
@@ -0,0 +1,68 @@
+.. include:: ../../Includes.txt
+
+==============================================================
+Deprecation: #92386 - Extbase property injection is deprecated
+==============================================================
+
+See :issue:`92386`
+
+Description
+===========
+
+Since core dependency injection is in place and is about to replace the extbase dependency injection completely, using property injection via the :php:`@Extbase\Inject` is deprecated.
+
+
+Impact
+======
+
+Classes that use extbase property injection will experience non injected services for properties that have a :php:`@Extbase\Inject` annotation.
+
+
+Affected Installations
+======================
+
+All installations that use extbase property injection via annotation :php:`@Extbase\Inject`.
+
+
+Migration
+=========
+
+Extbase property injection can be replaced by one of the following methods:
+
+- constructor injection: works both with core and extbase dependency injection and is well suited to make extensions compatible for multiple TYPO3 versions.
+
+- setter injection: Basically the same like constructor injection. Both the core and extbase di can handle setter injection and both are supported in different TYPO3 versions.
+
+- (core) property injection: This kind of injection can be used but it requires the configuration of services via a `Services.yaml` in the Configuration folder of an extension.
+
+
+Given the following example for a :php:`@Extbase\Inject` annotation based injection:
+
+.. code-block:: php
+
+   /**
+    * @var MyService
+    * @Extbase\Inject
+    */
+   protected $myService;
+
+
+This service injection can be changed to constructor injection by adding the
+service as constructor argument and removing the :php:`@Extbase\Inject` annoation:
+
+.. code-block:: php
+
+   /**
+    @var MyService
+    */
+   protected $MyService;
+
+   public function __construct(MyService $MyService) {
+      $this->myService = $myService;
+   }
+
+Please consult the dependency-injection_ documentation for more information.
+
+.. _dependency-injection https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/DependencyInjection/Index.html
+
+.. index:: PHP-API, FullyScanned, ext:extbase
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php
index d4dd2ac276bd..f114dfc17c85 100644
--- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php
+++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/AbstractController.php
@@ -17,7 +17,6 @@ namespace OliverHader\IrreTutorial\Controller;
 
 use OliverHader\IrreTutorial\Service\QueueService;
 use Psr\Http\Message\ResponseInterface;
-use TYPO3\CMS\Extbase\Annotation as Extbase;
 use TYPO3\CMS\Extbase\Http\ForwardResponse;
 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
 use TYPO3\CMS\Extbase\Mvc\RequestInterface;
@@ -31,11 +30,15 @@ use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
 abstract class AbstractController extends ActionController
 {
     /**
-     * @Extbase\Inject
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
     public $dataMapFactory;
 
+    public function __construct(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory)
+    {
+        $this->dataMapFactory = $dataMapFactory;
+    }
+
     /**
      * @param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request
      * @return \Psr\Http\Message\ResponseInterface
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php
index 2de355bf39e2..fd72d43dca08 100644
--- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php
+++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/ContentController.php
@@ -25,10 +25,18 @@ use TYPO3\CMS\Extbase\Mvc\View\JsonView;
 class ContentController extends AbstractController
 {
     /**
-     * @Extbase\Inject
      * @var \OliverHader\IrreTutorial\Domain\Repository\ContentRepository
      */
-    public $contentRepository;
+    private $contentRepository;
+
+    public function __construct(
+        \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory,
+        \OliverHader\IrreTutorial\Domain\Repository\ContentRepository $contentRepository
+    ) {
+        parent::__construct($dataMapFactory);
+
+        $this->contentRepository = $contentRepository;
+    }
 
     /**
      * @var string
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
index b1d386d4d609..9d1c909ab0ee 100644
--- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
+++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Classes/Controller/QueueController.php
@@ -15,7 +15,6 @@
 
 namespace OliverHader\IrreTutorial\Controller;
 
-use TYPO3\CMS\Extbase\Annotation as Extbase;
 use TYPO3\CMS\Extbase\Http\ForwardResponse;
 use TYPO3\CMS\Extbase\Mvc\Controller\ControllerInterface;
 use TYPO3\CMS\Extbase\Mvc\Exception\InvalidControllerException;
@@ -28,10 +27,18 @@ use TYPO3\CMS\Extbase\Mvc\View\JsonView;
 class QueueController extends AbstractController
 {
     /**
-     * @Extbase\Inject
      * @var \OliverHader\IrreTutorial\Domain\Repository\ContentRepository
      */
-    public $contentRepository;
+    private $contentRepository;
+
+    public function __construct(
+        \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory,
+        \OliverHader\IrreTutorial\Domain\Repository\ContentRepository $contentRepository
+    ) {
+        parent::__construct($dataMapFactory);
+
+        $this->contentRepository = $contentRepository;
+    }
 
     /**
      * @var string
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/Services.yaml b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/Services.yaml
new file mode 100644
index 000000000000..71146cd373b7
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/Services.yaml
@@ -0,0 +1,9 @@
+services:
+  _defaults:
+    autowire: true
+    autoconfigure: true
+    public: false
+
+  OliverHader\IrreTutorial\:
+    resource: '../Classes/*'
+    exclude: '../Classes/Domain/Model'
diff --git a/typo3/sysext/extbase/Classes/Annotation/Inject.php b/typo3/sysext/extbase/Classes/Annotation/Inject.php
index bfbd4c5c4349..2abe1ce93525 100644
--- a/typo3/sysext/extbase/Classes/Annotation/Inject.php
+++ b/typo3/sysext/extbase/Classes/Annotation/Inject.php
@@ -20,6 +20,7 @@ namespace TYPO3\CMS\Extbase\Annotation;
 /**
  * @Annotation
  * @Target({"PROPERTY"})
+ * @deprecated since v11, will be removed in v12
  */
 class Inject
 {
diff --git a/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php b/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php
index 6ec0dede8420..c4deaea75b08 100644
--- a/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php
+++ b/typo3/sysext/extbase/Classes/Reflection/ClassSchema.php
@@ -249,6 +249,10 @@ class ClassSchema
                 && ($annotationReader->getPropertyAnnotation($reflectionProperty, Inject::class) instanceof Inject);
 
             if ($isInjectProperty) {
+                trigger_error(
+                    sprintf('Property "%s" of class "%s" uses Extbase\' property injection which is deprecated.', $propertyName, $reflectionClass->getName()),
+                    E_USER_DEPRECATED
+                );
                 $propertyCharacteristicsBit += PropertyCharacteristics::ANNOTATED_INJECT;
                 $classHasInjectProperties = true;
             }
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/BlogController.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/BlogController.php
index 55ca44ba78e8..a5c69886beeb 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/BlogController.php
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/BlogController.php
@@ -17,7 +17,6 @@ namespace ExtbaseTeam\BlogExample\Controller;
 
 use ExtbaseTeam\BlogExample\Domain\Model\Blog;
 use Psr\Http\Message\ResponseInterface;
-use TYPO3\CMS\Extbase\Annotation as Extbase;
 use TYPO3\CMS\Extbase\Annotation\IgnoreValidation;
 use TYPO3\CMS\Extbase\Http\ForwardResponse;
 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
@@ -32,10 +31,9 @@ use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
 class BlogController extends ActionController
 {
     /**
-     * @Extbase\Inject
      * @var \ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository
      */
-    public $blogRepository;
+    private $blogRepository;
 
     /**
      * @var string
@@ -43,10 +41,17 @@ class BlogController extends ActionController
     protected $defaultViewObjectName = JsonView::class;
 
     /**
-     * @Extbase\Inject
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    public $dataMapFactory;
+    private $dataMapFactory;
+
+    public function __construct(
+        \ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository $blogRepository,
+        \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory
+    ) {
+        $this->blogRepository = $blogRepository;
+        $this->dataMapFactory = $dataMapFactory;
+    }
 
     public function listAction(): ResponseInterface
     {
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php
index 0c632bc47712..5e6caa9f100c 100644
--- a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Controller/ContentController.php
@@ -18,7 +18,6 @@ declare(strict_types=1);
 namespace ExtbaseTeam\BlogExample\Controller;
 
 use Psr\Http\Message\ResponseInterface;
-use TYPO3\CMS\Extbase\Annotation as Extbase;
 use TYPO3\CMS\Extbase\Domain\Model\FileReference;
 use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
 use TYPO3\CMS\Extbase\Mvc\RequestInterface;
@@ -32,10 +31,9 @@ use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
 class ContentController extends ActionController
 {
     /**
-     * @Extbase\Inject
      * @var \ExtbaseTeam\BlogExample\Domain\Repository\TtContentRepository
      */
-    public $contentRepository;
+    private $contentRepository;
 
     /**
      * @var string
@@ -43,10 +41,17 @@ class ContentController extends ActionController
     protected $defaultViewObjectName = JsonView::class;
 
     /**
-     * @Extbase\Inject
      * @var \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory
      */
-    public $dataMapFactory;
+    private $dataMapFactory;
+
+    public function __construct(
+        \ExtbaseTeam\BlogExample\Domain\Repository\TtContentRepository $contentRepository,
+        \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory $dataMapFactory
+    ) {
+        $this->contentRepository = $contentRepository;
+        $this->dataMapFactory = $dataMapFactory;
+    }
 
     /**
      * @return array
diff --git a/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/Services.yaml b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/Services.yaml
new file mode 100644
index 000000000000..a25ecf3bb32f
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Configuration/Services.yaml
@@ -0,0 +1,9 @@
+services:
+  _defaults:
+    autowire: true
+    autoconfigure: true
+    public: false
+
+  ExtbaseTeam\BlogExample\:
+    resource: '../Classes/*'
+    exclude: '../Classes/Domain/{Model,Validator}'
diff --git a/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php b/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php
index 4b25b3b8b1f5..68280909a1ef 100644
--- a/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Object/Container/ContainerTest.php
@@ -25,12 +25,10 @@ use TYPO3\CMS\Extbase\Object\Exception\CannotBuildObjectException;
 use TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException;
 use TYPO3\CMS\Extbase\Reflection\ReflectionService;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ArgumentTestClass;
-use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\MandatoryConstructorArgument;
 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\PublicPropertyInjectClass;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\SimpleTypeConstructorArgument;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\TwoConstructorArgumentsBothOptional;
 use TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\TwoConstructorArgumentsFirstOptional;
@@ -958,13 +956,4 @@ class ContainerTest extends UnitTestCase
             $object->argumentTestClassTwo
         );
     }
-
-    /**
-     * @test
-     */
-    public function getInstanceInjectsPublicProperties()
-    {
-        $object = $this->subject->getInstance(PublicPropertyInjectClass::class);
-        self::assertInstanceOf(ArgumentTestClassForPublicPropertyInjection::class, $object->foo);
-    }
 }
diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchema/PropertyTest.php b/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchema/PropertyTest.php
index 317817bc9cc5..e2054479eb5a 100644
--- a/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchema/PropertyTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchema/PropertyTest.php
@@ -64,17 +64,6 @@ class PropertyTest extends UnitTestCase
         self::assertTrue($property->isPrivate());
     }
 
-    /**
-     * @test
-     */
-    public function classSchemaDetectsInjectProperty(): void
-    {
-        $property = (new ClassSchema(DummyClassWithAllTypesOfProperties::class))
-            ->getProperty('propertyWithInjectAnnotation');
-
-        self::assertTrue($property->isInjectProperty());
-    }
-
     /**
      * @test
      */
diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php b/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php
index a26ff1c49d4e..bf124a7269fa 100644
--- a/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Reflection/ClassSchemaTest.php
@@ -21,7 +21,6 @@ use TYPO3\CMS\Extbase\Reflection\ReflectionService;
 use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithAllTypesOfMethods;
 use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithAllTypesOfProperties;
 use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithConstructorAndConstructorArguments;
-use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithInjectDoctrineAnnotation;
 use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyControllerWithValidateAnnotationWithoutParam;
 use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyControllerWithValidateAnnotationWithoutParamTypeHint;
 use TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyEntity;
@@ -127,28 +126,6 @@ class ClassSchemaTest extends UnitTestCase
         );
     }
 
-    /**
-     * @test
-     */
-    public function classSchemaDetectsInjectProperties()
-    {
-        $classSchema = new ClassSchema(DummyClassWithInjectDoctrineAnnotation::class);
-        self::assertTrue($classSchema->hasInjectProperties());
-
-        $injectProperties = $classSchema->getInjectProperties();
-        self::assertArrayHasKey('propertyWithFullQualifiedClassName', $injectProperties);
-        self::assertSame(DummyClassWithInjectDoctrineAnnotation::class, $injectProperties['propertyWithFullQualifiedClassName']->getType());
-
-        self::assertArrayHasKey('propertyWithRelativeClassName', $injectProperties);
-        self::assertSame(DummyClassWithInjectDoctrineAnnotation::class, $injectProperties['propertyWithRelativeClassName']->getType());
-
-        self::assertArrayHasKey('propertyWithImportedClassName', $injectProperties);
-        self::assertSame(self::class, $injectProperties['propertyWithImportedClassName']->getType());
-
-        self::assertArrayHasKey('propertyWithImportedAndAliasedClassName', $injectProperties);
-        self::assertSame(self::class, $injectProperties['propertyWithImportedAndAliasedClassName']->getType());
-    }
-
     /**
      * @test
      */
diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php
index 65e55ea5a975..8647df3512ab 100644
--- a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php
+++ b/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php
@@ -54,7 +54,6 @@ class DummyClassWithAllTypesOfProperties extends AbstractEntity
     public $propertyWithIgnoredTags;
 
     /**
-     * @Extbase\Inject
      * @var DummyClassWithAllTypesOfProperties
      */
     public $propertyWithInjectAnnotation;
diff --git a/typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/ContainerTest.php b/typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/ContainerTest.php
new file mode 100644
index 000000000000..e9f2bf94baf9
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/ContainerTest.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Extbase\Tests\UnitDeprecated\Object\Container;
+
+use Psr\Container\ContainerInterface;
+use Psr\Container\NotFoundExceptionInterface;
+use Psr\Log\LoggerInterface;
+use TYPO3\CMS\Core\Log\Logger;
+use TYPO3\CMS\Extbase\Object\Container\Container;
+use TYPO3\CMS\Extbase\Reflection\ReflectionService;
+use TYPO3\CMS\Extbase\Tests\UnitDeprecated\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection;
+use TYPO3\CMS\Extbase\Tests\UnitDeprecated\Object\Container\Fixtures\PublicPropertyInjectClass;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Test case
+ */
+class ContainerTest extends UnitTestCase
+{
+    /**
+     * @var bool Reset singletons created by subject
+     */
+    protected $resetSingletonInstances = true;
+
+    /**
+     * @var Container
+     */
+    protected $subject;
+
+    /**
+     * @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject
+     */
+    protected $logger;
+
+    protected function setUp(): void
+    {
+        parent::setUp();
+        $this->logger = $this->getMockBuilder(Logger::class)
+            ->setMethods(['notice'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $reflectionService = new ReflectionService();
+
+        $notFoundException = new class() extends \Exception implements NotFoundExceptionInterface {
+        };
+
+        $psrContainer = $this->getMockBuilder(ContainerInterface::class)
+            ->setMethods(['has', 'get'])
+            ->getMock();
+        $psrContainer->expects(self::any())->method('has')->willReturn(false);
+        $psrContainer->expects(self::any())->method('get')->will(self::throwException($notFoundException));
+
+        $this->subject = $this->getMockBuilder(Container::class)
+            ->setConstructorArgs([$psrContainer])
+            ->setMethods(['getLogger', 'getReflectionService'])
+            ->getMock();
+        $this->subject->setLogger($this->logger);
+        $this->subject->expects(self::any())->method('getReflectionService')->willReturn($reflectionService);
+    }
+
+    /**
+     * @test
+     */
+    public function getInstanceInjectsPublicProperties()
+    {
+        $object = $this->subject->getInstance(PublicPropertyInjectClass::class);
+        self::assertInstanceOf(ArgumentTestClassForPublicPropertyInjection::class, $object->foo);
+    }
+}
diff --git a/typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php b/typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php
similarity index 71%
rename from typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php
rename to typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php
index 7ae52d94e66b..78fb589553b3 100644
--- a/typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php
+++ b/typo3/sysext/extbase/Tests/UnitDeprecated/Object/Container/Fixtures/ContainerPropertyInjectionTestClasses.php
@@ -15,7 +15,7 @@ declare(strict_types=1);
  * The TYPO3 project - inspiring people to share!
  */
 
-namespace TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures;
+namespace TYPO3\CMS\Extbase\Tests\UnitDeprecated\Object\Container\Fixtures;
 
 use TYPO3\CMS\Extbase\Annotation as Extbase;
 
@@ -23,7 +23,7 @@ class PublicPropertyInjectClass
 {
     /**
      * @Extbase\Inject
-     * @var \TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection
+     * @var \TYPO3\CMS\Extbase\Tests\UnitDeprecated\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection
      */
     public $foo;
 }
@@ -37,7 +37,7 @@ class ProtectedPropertyInjectClass
 
     /**
      * @Extbase\Inject
-     * @var \TYPO3\CMS\Extbase\Tests\Unit\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection
+     * @var \TYPO3\CMS\Extbase\Tests\UnitDeprecated\Object\Container\Fixtures\ArgumentTestClassForPublicPropertyInjection
      */
     protected $foo;
 
diff --git a/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchema/PropertyTest.php b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchema/PropertyTest.php
new file mode 100644
index 000000000000..1fa1aea7bcef
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchema/PropertyTest.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\ClassSchema;
+
+use TYPO3\CMS\Extbase\Reflection\ClassSchema;
+use TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\Fixture\DummyClassWithAllTypesOfProperties;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Class TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\PropertyTest
+ */
+class PropertyTest extends UnitTestCase
+{
+    /**
+     * @test
+     */
+    public function classSchemaDetectsInjectProperty(): void
+    {
+        $property = (new ClassSchema(DummyClassWithAllTypesOfProperties::class))
+            ->getProperty('propertyWithInjectAnnotation');
+
+        self::assertTrue($property->isInjectProperty());
+    }
+}
diff --git a/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchemaTest.php b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchemaTest.php
new file mode 100644
index 000000000000..454df166e07a
--- /dev/null
+++ b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/ClassSchemaTest.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection;
+
+use TYPO3\CMS\Extbase\Reflection\ClassSchema;
+use TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\Fixture\DummyClassWithInjectDoctrineAnnotation;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Test case
+ */
+class ClassSchemaTest extends UnitTestCase
+{
+    /**
+     * @test
+     */
+    public function classSchemaDetectsInjectProperties()
+    {
+        $classSchema = new ClassSchema(DummyClassWithInjectDoctrineAnnotation::class);
+        self::assertTrue($classSchema->hasInjectProperties());
+
+        $injectProperties = $classSchema->getInjectProperties();
+        self::assertArrayHasKey('propertyWithFullQualifiedClassName', $injectProperties);
+        self::assertSame(DummyClassWithInjectDoctrineAnnotation::class, $injectProperties['propertyWithFullQualifiedClassName']->getType());
+
+        self::assertArrayHasKey('propertyWithRelativeClassName', $injectProperties);
+        self::assertSame(DummyClassWithInjectDoctrineAnnotation::class, $injectProperties['propertyWithRelativeClassName']->getType());
+
+        self::assertArrayHasKey('propertyWithImportedClassName', $injectProperties);
+        self::assertSame(self::class, $injectProperties['propertyWithImportedClassName']->getType());
+
+        self::assertArrayHasKey('propertyWithImportedAndAliasedClassName', $injectProperties);
+        self::assertSame(self::class, $injectProperties['propertyWithImportedAndAliasedClassName']->getType());
+    }
+}
diff --git a/typo3/sysext/extbase/Tests/Fixture/ClassWithInjectProperties.php b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php
similarity index 61%
rename from typo3/sysext/extbase/Tests/Fixture/ClassWithInjectProperties.php
rename to typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php
index 88b0e57e1794..a5df288a9eba 100644
--- a/typo3/sysext/extbase/Tests/Fixture/ClassWithInjectProperties.php
+++ b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/Fixture/DummyClassWithAllTypesOfProperties.php
@@ -13,20 +13,19 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-namespace TYPO3\CMS\Extbase\Tests\Fixture;
+namespace TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\Fixture;
 
 use TYPO3\CMS\Extbase\Annotation as Extbase;
+use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
 
-class ClassWithInjectProperties
+/**
+ * Fixture class with getters and setters
+ */
+class DummyClassWithAllTypesOfProperties extends AbstractEntity
 {
     /**
-     * @var \TYPO3\CMS\Extbase\Tests\Fixture\DummyClass
-     */
-    protected $dummyClass;
-
-    /**
-     * @var \TYPO3\CMS\Extbase\Tests\Fixture\SecondDummyClass
      * @Extbase\Inject
+     * @var DummyClassWithAllTypesOfProperties
      */
-    protected $secondDummyClass;
+    public $propertyWithInjectAnnotation;
 }
diff --git a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithInjectDoctrineAnnotation.php b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/Fixture/DummyClassWithInjectDoctrineAnnotation.php
similarity index 75%
rename from typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithInjectDoctrineAnnotation.php
rename to typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/Fixture/DummyClassWithInjectDoctrineAnnotation.php
index 433c8620b7e7..e5b89deec126 100644
--- a/typo3/sysext/extbase/Tests/Unit/Reflection/Fixture/DummyClassWithInjectDoctrineAnnotation.php
+++ b/typo3/sysext/extbase/Tests/UnitDeprecated/Reflection/Fixture/DummyClassWithInjectDoctrineAnnotation.php
@@ -15,11 +15,11 @@ declare(strict_types=1);
  * The TYPO3 project - inspiring people to share!
  */
 
-namespace TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture;
+namespace TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\Fixture;
 
 use TYPO3\CMS\Extbase\Annotation as Extbase;
-use TYPO3\CMS\Extbase\Tests\Unit\Reflection\ClassSchemaTest;
-use TYPO3\CMS\Extbase\Tests\Unit\Reflection\ClassSchemaTest as AliasedClassSchemaTest;
+use TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\ClassSchemaTest;
+use TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\ClassSchemaTest as AliasedClassSchemaTest;
 
 /**
  * Fixture class with absolute inject annotation
@@ -28,7 +28,7 @@ class DummyClassWithInjectDoctrineAnnotation
 {
     /**
      * @Extbase\Inject
-     * @var \TYPO3\CMS\Extbase\Tests\Unit\Reflection\Fixture\DummyClassWithInjectDoctrineAnnotation
+     * @var \TYPO3\CMS\Extbase\Tests\UnitDeprecated\Reflection\Fixture\DummyClassWithInjectDoctrineAnnotation
      */
     public $propertyWithFullQualifiedClassName;
 
diff --git a/typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test/Configuration/Services.yaml b/typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test/Configuration/Services.yaml
new file mode 100644
index 000000000000..659380f7e8f8
--- /dev/null
+++ b/typo3/sysext/fluid/Tests/Functional/Fixtures/Extensions/fluid_test/Configuration/Services.yaml
@@ -0,0 +1,9 @@
+services:
+  _defaults:
+    autowire: true
+    autoconfigure: true
+    public: false
+
+  TYPO3Fluid\FluidTest\:
+    resource: '../Classes/*'
+    exclude: '../Classes/ViewHelpers'
-- 
GitLab