From 668e08a7bfdb006b67f4b96be707ec657ba4df8f Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Wed, 11 Sep 2019 19:49:40 +1000
Subject: [PATCH] Issue #3052233 by mikelutz, Berdir, alexpott: Properly
 deprecate EntityFormInterface::setEntityManager() and trigger an error on use

---
 core/core.services.yml                        |  3 +-
 core/lib/Drupal/Core/Entity/EntityForm.php    | 36 +++++++++++++--
 .../Core/Entity/EntityFormInterface.php       |  5 ++-
 .../Drupal/Core/Entity/EntityTypeManager.php  |  5 +--
 .../Core/Entity/ContentEntityFormTest.php     |  9 ++--
 .../Tests/Core/Entity/EntityFormTest.php      | 44 +++++++++++++++++++
 6 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/core/core.services.yml b/core/core.services.yml
index f2b22a878048..831eb541add3 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -547,10 +547,9 @@ services:
   # @deprecated in Drupal 8.0.x and will be removed before 9.0.0. Use the other
   #   entity* services instead.
   entity.manager:
-    # We cannot set the deprecated property here because many test cases still
-    # rely on this service and they would fail with deprecation warnings.
     class: Drupal\Core\Entity\EntityManager
     parent: container.trait
+    deprecated: The "%service_id%" service is deprecated. You should use the 'entity_type.manager' service instead.
   entity.memory_cache:
     class: Drupal\Core\Cache\MemoryCache\MemoryCache
   entity_type.manager:
diff --git a/core/lib/Drupal/Core/Entity/EntityForm.php b/core/lib/Drupal/Core/Entity/EntityForm.php
index b90d1d209dc3..462d85b64dc2 100644
--- a/core/lib/Drupal/Core/Entity/EntityForm.php
+++ b/core/lib/Drupal/Core/Entity/EntityForm.php
@@ -35,13 +35,14 @@ class EntityForm extends FormBase implements EntityFormInterface {
   /**
    * The entity manager.
    *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
+   * This member exists for BC reasons and should be removed when the
+   *   drupal:9.0.0 branch opens.
    *
-   * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
+   * @var \Drupal\Core\Entity\EntityManagerInterface
    *
    * @see https://www.drupal.org/node/2549139
    */
-  protected $entityManager;
+  private $privateEntityManager;
 
   /**
    * The entity type manager.
@@ -57,6 +58,32 @@ class EntityForm extends FormBase implements EntityFormInterface {
    */
   protected $entity;
 
+  /**
+   * {@inheritdoc}
+   */
+  public function __get($name) {
+    // Removing core's usage of ::setEntityManager means that this deprecated
+    // service wont be set. We provide it here for backwards compatibility.
+    if ($name === 'entityManager') {
+      @trigger_error('EntityForm::entityManager is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use EntityForm::entityTypeManager instead. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);
+      return $this->privateEntityManager ?: \Drupal::entityManager();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __set($name, $value) {
+    // We've changed the entityManager property from protected to private so
+    // access is funnelled through __get above. This method is provided for BC
+    // purposes, in case any extended class attempts to set the previously
+    // accessible property directly.
+    if ($name === 'entityManager') {
+      @trigger_error('EntityForm::entityManager is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use EntityForm::entityTypeManager instead. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);
+      $this->privateEntityManager = $value;
+    }
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -429,7 +456,8 @@ public function setModuleHandler(ModuleHandlerInterface $module_handler) {
    * {@inheritdoc}
    */
   public function setEntityManager(EntityManagerInterface $entity_manager) {
-    $this->entityManager = $entity_manager;
+    @trigger_error('EntityForm::setEntityTypeManager() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use EntityFormInterface::setEntityTypeManager() instead. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);
+    $this->privateEntityManager = $entity_manager;
     return $this;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityFormInterface.php b/core/lib/Drupal/Core/Entity/EntityFormInterface.php
index 2c29360df75a..9cd1041c8614 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormInterface.php
@@ -133,9 +133,10 @@ public function setModuleHandler(ModuleHandlerInterface $module_handler);
    *
    * @return $this
    *
-   * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
+   * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use
+   * EntityFormInterface::setEntityTypeManager() instead.
    *
-   * @todo Remove this set call in https://www.drupal.org/node/2603542.
+   * @see https://www.drupal.org/node/2549139
    */
   public function setEntityManager(EntityManagerInterface $entity_manager);
 
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeManager.php b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
index 6ae723f8d793..4bfe9b23df29 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeManager.php
@@ -229,10 +229,7 @@ public function getFormObject($entity_type_id, $operation) {
       ->setStringTranslation($this->stringTranslation)
       ->setModuleHandler($this->moduleHandler)
       ->setEntityTypeManager($this)
-      ->setOperation($operation)
-      // The entity manager cannot be injected due to a circular dependency.
-      // @todo Remove this set call in https://www.drupal.org/node/2603542.
-      ->setEntityManager(\Drupal::service('entity.manager'));
+      ->setOperation($operation);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityFormTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityFormTest.php
index 66a59788c268..f7990846b5c5 100644
--- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityFormTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityFormTest.php
@@ -15,19 +15,18 @@
 class ContentEntityFormTest extends UnitTestCase {
 
   /**
+   * Tests the constructor bc layer for injecting the entity manager.
+   *
    * @group legacy
    * @expectedDeprecation Passing the entity.manager service to ContentEntityForm::__construct() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Pass the entity.repository service instead. See https://www.drupal.org/node/2549139.
+   * @expectedDeprecation EntityForm::entityManager is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use EntityForm::entityTypeManager instead. See https://www.drupal.org/node/2549139
    */
   public function testEntityManagerDeprecation() {
     $entity_manager = $this->prophesize(EntityManagerInterface::class)->reveal();
     $entity_type_bundle_info = $this->prophesize(EntityTypeBundleInfoInterface::class)->reveal();
     $time = $this->prophesize(TimeInterface::class)->reveal();
     $form = new ContentEntityForm($entity_manager, $entity_type_bundle_info, $time);
-
-    $reflected_form = new \ReflectionClass($form);
-    $entity_manager_property = $reflected_form->getProperty('entityManager');
-    $entity_manager_property->setAccessible(TRUE);
-    $this->assertTrue($entity_manager_property->getValue($form) === $entity_manager);
+    $this->assertSame($form->entityManager, $entity_manager);
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityFormTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityFormTest.php
index c2e896768f66..6fd620c2d0d7 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityFormTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityFormTest.php
@@ -2,8 +2,10 @@
 
 namespace Drupal\Tests\Core\Entity;
 
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Entity\EntityForm;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityManager;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityType;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
@@ -226,6 +228,48 @@ public function testGetEntityFromRouteMatchAddEntity() {
     $this->assertEquals($entity, $actual);
   }
 
+  /**
+   * Tests that setEntityManager triggers proper deprecation errors.
+   *
+   * @covers ::setEntityManager
+   *
+   * @group legacy
+   *
+   * @expectedDeprecation EntityForm::setEntityTypeManager() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use EntityFormInterface::setEntityTypeManager() instead. See https://www.drupal.org/node/2549139
+   */
+  public function testSetEntityManager() {
+    $this->entityForm->setEntityManager($this->prophesize(EntityManager::class)->reveal());
+  }
+
+  /**
+   * Tests that __set triggers proper deprecation errors.
+   *
+   * @covers ::__set
+   *
+   * @group legacy
+   *
+   * @expectedDeprecation EntityForm::entityManager is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use EntityForm::entityTypeManager instead. See https://www.drupal.org/node/2549139
+   */
+  public function testSet() {
+    $this->entityForm->entityManager = $this->prophesize(EntityManager::class)->reveal();
+  }
+
+  /**
+   * Tests that __get triggers proper deprecation errors.
+   *
+   * @covers ::__get
+   * @group legacy
+   *
+   * @expectedDeprecation EntityForm::entityManager is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use EntityForm::entityTypeManager instead. See https://www.drupal.org/node/2549139
+   */
+  public function testGet() {
+    $container = new ContainerBuilder();
+    $entity_manager = $this->prophesize(EntityManager::class)->reveal();
+    $container->set('entity.manager', $entity_manager);
+    \Drupal::setContainer($container);
+    $this->assertSame($entity_manager, $this->entityForm->entityManager);
+  }
+
   /**
    * Sets up the storage accessed via the entity type manager in the form.
    *
-- 
GitLab