From ffe69958b02367dcd2c1141163a4aa498c36f5e2 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Wed, 31 Jul 2019 08:52:27 +0100
Subject: [PATCH] Issue #2450793 by Berdir, Mile23, Wim Leers, mikelutz, xjm,
 TR: Properly deprecate support for entity type label callbacks

---
 .../Drupal/Core/Entity/ContentEntityBase.php  |  3 +-
 core/lib/Drupal/Core/Entity/EntityBase.php    |  3 +-
 core/lib/Drupal/Core/Entity/EntityType.php    | 10 ++---
 .../Core/Entity/EntityTypeInterface.php       | 15 +++----
 .../src/JsonApiResource/ResourceObject.php    |  6 +--
 core/modules/user/src/Entity/User.php         |  8 +++-
 ...llbackTest.php => UserEntityLabelTest.php} |  2 +-
 .../user/tests/src/Kernel/UserLegacyTest.php  | 10 +++++
 core/modules/user/user.module                 |  7 +--
 .../Core/Entity/ContentEntityBaseUnitTest.php |  9 +++-
 .../Tests/Core/Entity/EntityTypeTest.php      | 43 +++++++++++++++++++
 .../Tests/Core/Entity/EntityUnitTest.php      | 12 ++++--
 12 files changed, 99 insertions(+), 29 deletions(-)
 rename core/modules/user/tests/src/Kernel/{UserEntityLabelCallbackTest.php => UserEntityLabelTest.php} (96%)

diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 19ad14fca9e3..5ca737ffbf3e 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -1246,7 +1246,8 @@ public function __clone() {
   public function label() {
     $label = NULL;
     $entity_type = $this->getEntityType();
-    if (($label_callback = $entity_type->getLabelCallback()) && is_callable($label_callback)) {
+    if (($label_callback = $entity_type->get('label_callback')) && is_callable($label_callback)) {
+      @trigger_error('Entity type ' . $this->getEntityTypeId() . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
       $label = call_user_func($label_callback, $this);
     }
     elseif (($label_key = $entity_type->getKey('label'))) {
diff --git a/core/lib/Drupal/Core/Entity/EntityBase.php b/core/lib/Drupal/Core/Entity/EntityBase.php
index f6d0b358d889..66a3857dc047 100644
--- a/core/lib/Drupal/Core/Entity/EntityBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityBase.php
@@ -166,7 +166,8 @@ public function bundle() {
   public function label() {
     $label = NULL;
     $entity_type = $this->getEntityType();
-    if (($label_callback = $entity_type->getLabelCallback()) && is_callable($label_callback)) {
+    if (($label_callback = $entity_type->get('label_callback')) && is_callable($label_callback)) {
+      @trigger_error('Entity type ' . $this->getEntityTypeId() . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
       $label = call_user_func($label_callback, $this);
     }
     elseif (($label_key = $entity_type->getKey('label')) && isset($this->{$label_key})) {
diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index c7d60384c4d8..388ea31a5467 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -96,13 +96,10 @@ class EntityType extends PluginDefinition implements EntityTypeInterface {
    *
    * @var callable|null
    *
-   * @deprecated in Drupal 8.0.x-dev and will be removed before Drupal 9.0.0.
-   *   Use Drupal\Core\Entity\EntityInterface::label() for complex label
-   *   generation as needed.
+   * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the
+   *   EntityInterface::label() method instead for dynamic labels.
    *
    * @see \Drupal\Core\Entity\EntityInterface::label()
-   *
-   * @todo Remove usages of label_callback https://www.drupal.org/node/2450793.
    */
   protected $label_callback = NULL;
 
@@ -667,6 +664,7 @@ public function setLinkTemplate($key, $path) {
    * {@inheritdoc}
    */
   public function getLabelCallback() {
+    @trigger_error('EntityType::getLabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
     return $this->label_callback;
   }
 
@@ -674,6 +672,7 @@ public function getLabelCallback() {
    * {@inheritdoc}
    */
   public function setLabelCallback($callback) {
+    @trigger_error('EntityType::setLabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
     $this->label_callback = $callback;
     return $this;
   }
@@ -682,6 +681,7 @@ public function setLabelCallback($callback) {
    * {@inheritdoc}
    */
   public function hasLabelCallback() {
+    @trigger_error('EntityType::hasabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
     return isset($this->label_callback);
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
index 77fa4933adc3..3a6702281da4 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
@@ -488,15 +488,12 @@ public function setLinkTemplate($key, $path);
    * @return callable|null
    *   The callback, or NULL if none exists.
    *
-   * @deprecated in Drupal 8.0.x-dev and will be removed before Drupal 9.0.0.
-   *   Use Drupal\Core\Entity\EntityInterface::label() for complex label
-   *   generation as needed.
+   * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the
+   *   EntityInterface::label() method instead for dynamic labels.
    *
    * @see \Drupal\Core\Entity\EntityInterface::label()
    * @see \Drupal\Core\Entity\EntityTypeInterface::setLabelCallback()
    * @see \Drupal\Core\Entity\EntityTypeInterface::hasLabelCallback()
-   *
-   * @todo Remove usages of label_callback https://www.drupal.org/node/2450793.
    */
   public function getLabelCallback();
 
@@ -508,8 +505,8 @@ public function getLabelCallback();
    *
    * @return $this
    *
-   * @deprecated in Drupal 8.0.x-dev and will be removed before Drupal 9.0.0.
-   *   Use EntityInterface::label() for complex label generation as needed.
+   * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the
+   *   EntityInterface::label() method instead for dynamic labels.
    *
    * @see \Drupal\Core\Entity\EntityInterface::label()
    * @see \Drupal\Core\Entity\EntityTypeInterface::getLabelCallback()
@@ -522,8 +519,8 @@ public function setLabelCallback($callback);
    *
    * @return bool
    *
-   * @deprecated in Drupal 8.0.x-dev and will be removed before Drupal 9.0.0.
-   *   Use EntityInterface::label() for complex label generation as needed.
+   * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the
+   *   EntityInterface::label() method instead for dynamic labels.
    *
    * @see \Drupal\Core\Entity\EntityInterface::label()
    * @see \Drupal\Core\Entity\EntityTypeInterface::getLabelCallback()
diff --git a/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php b/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php
index 8a08cb3d4e2e..0540248c9b9c 100644
--- a/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php
+++ b/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php
@@ -281,10 +281,10 @@ protected static function extractContentEntityFields(ResourceType $resource_type
       [$resource_type, 'isFieldEnabled']
     );
 
-    // The "label" field needs special treatment: some entity types have a label
-    // field that is actually backed by a label callback.
+    // Special handling for user entities.
+    // @todo Improve in https://www.drupal.org/project/drupal/issues/3057175.
     $entity_type = $entity->getEntityType();
-    if ($entity_type->hasLabelCallback()) {
+    if ($entity_type->id() == 'user') {
       $fields[static::getLabelFieldName($entity)]->value = $entity->label();
     }
 
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 8ed8dfdac8c0..f693fe3826bd 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -48,7 +48,6 @@
  *   admin_permission = "administer users",
  *   base_table = "users",
  *   data_table = "users_field_data",
- *   label_callback = "user_format_name",
  *   translatable = TRUE,
  *   entity_keys = {
  *     "id" = "uid",
@@ -83,6 +82,13 @@ public function isNew() {
     return !empty($this->enforceIsNew) || $this->id() === NULL;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function label() {
+    return $this->getDisplayName();
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/user/tests/src/Kernel/UserEntityLabelCallbackTest.php b/core/modules/user/tests/src/Kernel/UserEntityLabelTest.php
similarity index 96%
rename from core/modules/user/tests/src/Kernel/UserEntityLabelCallbackTest.php
rename to core/modules/user/tests/src/Kernel/UserEntityLabelTest.php
index e815c4c0af28..625631e0ef54 100644
--- a/core/modules/user/tests/src/Kernel/UserEntityLabelCallbackTest.php
+++ b/core/modules/user/tests/src/Kernel/UserEntityLabelTest.php
@@ -11,7 +11,7 @@
  *
  * @group user
  */
-class UserEntityLabelCallbackTest extends KernelTestBase {
+class UserEntityLabelTest extends KernelTestBase {
 
   use UserCreationTrait;
 
diff --git a/core/modules/user/tests/src/Kernel/UserLegacyTest.php b/core/modules/user/tests/src/Kernel/UserLegacyTest.php
index 46abae4aa4c8..fb7fa3096632 100644
--- a/core/modules/user/tests/src/Kernel/UserLegacyTest.php
+++ b/core/modules/user/tests/src/Kernel/UserLegacyTest.php
@@ -84,4 +84,14 @@ public function testUserDeleteMultiple() {
     $this->assert(NULL === User::load(11), "User 11 has been deleted");
   }
 
+  /**
+   * Tests user_format_name().
+   *
+   * @expectedDeprecation user_format_name() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use $account->label() or $account->getDisplayName() instead. See https://www.drupal.org/node/3050794
+   */
+  public function testUserFormatName() {
+    $user = User::create(['name' => 'foo', 'uid' => 10]);
+    $this->assertSame('foo', user_format_name($user));
+  }
+
 }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 6f46ca3b0e74..7c18443ef1aa 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -436,12 +436,13 @@ function user_preprocess_block(&$variables) {
  * @return string
  *   An unsanitized string with the username to display.
  *
- * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
- *   Use \Drupal\Core\Session\AccountInterface::getDisplayName().
+ * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0.
+ *   Use $account->label() or $account->getDisplayName() instead
  *
- * @todo Remove usage in https://www.drupal.org/node/2311219.
+ * @see https://www.drupal.org/node/3050794
  */
 function user_format_name(AccountInterface $account) {
+  @trigger_error('user_format_name() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Use $account->label() or $account->getDisplayName() instead. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
   return $account->getDisplayName();
 }
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
index 02c7a371e227..ce2c999698fa 100644
--- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\TypedData\TypedDataManagerInterface;
+use Drupal\Tests\Traits\ExpectDeprecationTrait;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Language\Language;
 use Symfony\Component\Validator\Validator\ValidatorInterface;
@@ -23,6 +24,8 @@
  */
 class ContentEntityBaseUnitTest extends UnitTestCase {
 
+  use ExpectDeprecationTrait;
+
   /**
    * The bundle of the entity under test.
    *
@@ -475,6 +478,9 @@ public function testAccess() {
    * @group legacy
    */
   public function testLabel() {
+
+    $this->expectDeprecation('Entity type ' . $this->entityTypeId . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794');
+
     // Make a mock with one method that we use as the entity's label callback.
     // We check that it is called, and that the entity's label is the callback's
     // return value.
@@ -484,7 +490,8 @@ public function testLabel() {
       ->method(__FUNCTION__)
       ->will($this->returnValue($callback_label));
     $this->entityType->expects($this->once())
-      ->method('getLabelCallback')
+      ->method('get')
+      ->with('label_callback')
       ->will($this->returnValue([$callback_container, __FUNCTION__]));
 
     $this->assertSame($callback_label, $this->entity->label());
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
index f787a720db8b..b9eef7b9cd8f 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
@@ -496,4 +496,47 @@ public function testIsSerializable() {
     $this->assertEquals('example_entity_type', $entity_type->id());
   }
 
+  /**
+   * @covers ::getLabelCallback
+   *
+   * @group legacy
+   *
+   * @deprecatedMessage EntityType::getLabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794
+   */
+  public function testGetLabelCallack() {
+    $entity_type = $this->setUpEntityType(['label_callback' => 'label_function']);
+    $this->assertSame('label_function', $entity_type->getLabelCallback());
+
+    $entity_type = $this->setUpEntityType([]);
+    $this->assertNull($entity_type->getLabelCallback());
+  }
+
+  /**
+   * @covers ::setLabelCallback
+   *
+   * @group legacy
+   *
+   * @deprecatedMessage EntityType::setLabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794
+   */
+  public function testSetLabelCallack() {
+    $entity_type = $this->setUpEntityType([]);
+    $entity_type->setLabelCallback('label_function');
+    $this->assertSame('label_function', $entity_type->get('label_callback'));
+  }
+
+  /**
+   * @covers ::hasLabelCallback
+   *
+   * @group legacy
+   *
+   * @deprecatedMessage EntityType::hasLabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794
+   */
+  public function testHasLabelCallack() {
+    $entity_type = $this->setUpEntityType(['label_callback' => 'label_function']);
+    $this->assertTrue($entity_type->hasLabelCallback());
+
+    $entity_type = $this->setUpEntityType([]);
+    $this->assertFalse($entity_type->hasLabelCallback());
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
index 5a7f26814a96..f04df1b535f0 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityTypeRepositoryInterface;
 use Drupal\Core\Language\Language;
 use Drupal\entity_test\Entity\EntityTestMul;
+use Drupal\Tests\Traits\ExpectDeprecationTrait;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -19,6 +20,8 @@
  */
 class EntityUnitTest extends UnitTestCase {
 
+  use ExpectDeprecationTrait;
+
   /**
    * The entity under test.
    *
@@ -171,6 +174,9 @@ public function testBundle() {
    * @group legacy
    */
   public function testLabel() {
+
+    $this->expectDeprecation('Entity type ' . $this->entityTypeId . ' defines a label callback. Support for that is deprecated in drupal:8.0.0 and will be removed in drupal:9.0.0. Override the EntityInterface::label() method instead. See https://www.drupal.org/node/3050794');
+
     // Make a mock with one method that we use as the entity's uri_callback. We
     // check that it is called, and that the entity's label is the callback's
     // return value.
@@ -181,11 +187,9 @@ public function testLabel() {
       ->method(__FUNCTION__)
       ->will($this->returnValue($callback_label));
     $this->entityType->expects($this->at(0))
-      ->method('getLabelCallback')
+      ->method('get')
+      ->with('label_callback')
       ->will($this->returnValue([$callback_container, __FUNCTION__]));
-    $this->entityType->expects($this->at(1))
-      ->method('getLabelCallback')
-      ->will($this->returnValue(NULL));
     $this->entityType->expects($this->at(2))
       ->method('getKey')
       ->with('label')
-- 
GitLab