Drupal\group\Plugin\Group\RelationHandlerDefault::getRelationshipLabel() doesn't account for inexistent entity

Created on 18 April 2024, 2 months ago
Updated 15 May 2024, about 1 month ago

Problem/Motivation

Method GroupRelationship::getEntity does not respect the return type EntityInterface. The method can also return NULL.

Steps to reproduce

  1. Create a group and add a node to it
  2. Register a hook_entity_delete function. Inside of it add a call to $entity->label();
  3. Delete the node

An exception is thrown Error: Call to a member function label() on null in Drupal\group\Plugin\Group\RelationHandlerDefault\UiTextProvider->getRelationshipLabel() (line 36 of modules/contrib/group/src/Plugin/Group/RelationHandlerDefault/UiTextProvider.php).

Proposed resolution

Either change the return type of GroupRelationship::getEntity to ?EntityInterface, or mark the method with @throws and throw an exception. I don't think the exception is the way to go, because this does not feel like an exceptional situation.

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Active

Version

3.3

Component

Code

Created by

🇸🇮Slovenia alecsmrekar

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @alecsmrekar
  • 🇵🇱Poland Graber

    I think for the sake of correct docs we should change the return type to ?EntityInterface as proposed by Alec but the real issue here is that Drupal\group\Plugin\Group\RelationHandlerDefault::getRelationshipLabel() doesn't account for the situation when NULL is actually returned and that can always be a case. Can we change it to something like:

      /**
       * {@inheritdoc}
       */
      public function getRelationshipLabel(GroupRelationshipInterface $group_relationship) {
        $entity = $group_relationship->getEntity();
        if ($entity === NULL) {
           $label = $this->t('Deleted entity: @plugin (@id)', [
             '@plugin' => $group_relationship->getPluginId(),
             '@id' => $group_relationship->getEntityId(),
           ];
        }
        else {
          $label = $group_relationship->getEntity()->label();
        }
        return $label;
      }
    

    By the way, Drupal\group\Plugin\Group\RelationHandler\UiTextProviderInterface::getRelationshipLabel() return type is also incorrect as it can return a string and not only \Drupal\Core\StringTranslation\TranslatableMarkup. I'd probably start using type hints instead of those misleading comments across the entire project.
    I'd say let's solve the issue with getRelationshipLabel here and leave type hints to the maintainer as it's a much bigger general work and out of scope here.

  • 🇸🇮Slovenia alecsmrekar

    but the real issue here is that Drupal\group\Plugin\Group\RelationHandlerDefault::getRelationshipLabel() doesn't account for the situation when NULL is actually returned

    In my view getRelationshipLabel is not wrong, it's respecting the return type of the GroupRelationship::getEntity method. Why check if something is NULL if the called function says it'll never be NULL. The called function GroupRelationship::getEntity is at fault here.

    Adding this check would prevent the issue I reported in the issue description, but I think we should avoid tolerating wrong types, since types are very good guardrails.

  • 🇵🇱Poland Graber

    The thing is that every entity loading method can return NULL. See Drupal\Core\Entity\EntityStorageInterface::load() that is at the very bottom of all this and has a correct return type specified.

  • 🇵🇱Poland Graber

    OFC you can open a generic issue to correct return types across the entire module as we found 2 already.

  • Made a patch with #2 proposal; just fixed a missing ")".

    Tested on my own envirotment (Under Drupal 10.2.6 with Group 2.2.2) in wich I had this problem.

    The "call of label() on Null" problem after deleting content is now gone.

Production build 0.69.0 2024