EntityHelper::getEntityBundle can sometimes return NULL despite typing

Created on 2 January 2025, 6 months ago

Problem/Motivation

I've found a case where EntityHelper::getEntityBundle sometimes attempts to return a NULL even though it's typed to return a string. I believe the Menu Item Extras module can set menu_link_content entities into a state where `$entity->getMenuName()` can return a NULL even though we obviously don't want it to do so.

In any case, we should ensure that EntityHelper::getEntityBundle returns a string in all cases, even if it means treating an entity like a bundle-less entity. I believe this issue 🐛 option argument 'bundle' sometimes has a NULL value, which can cause issue Fixed covers a similar state, and they proposed to solve it by falling back to the entity type ID.

Steps to reproduce

  1. Set up a Drupal site with Menu Item Extras
  2. Add Simple Sitemap
  3. Enable Menu Item Extras on the main menu
  4. Try indexing main menu items for the sitemap

Proposed resolution

Apply fallbacks following the following pattern.

  1. If entity type ID is menu_link_content, and entity has method `getMenuName`, try calling `$entity->getMenuName()` but fall back to `$entity->bundle()`
  2. Otherwise call `$entity->bundle()`
  3. If bundle still appears to be NULL, fall back to ``$entity->getEntityTypeId()`

Remaining tasks

Implement patch

User interface changes

None.

API changes

None.

Data model changes

None.

🐛 Bug report
Status

Active

Version

4.2

Component

Code

Created by

🇦🇺Australia geoffreyr Sydney, AU / Gadigal country

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

Merge Requests

Comments & Activities

  • Issue created by @geoffreyr
  • 🇦🇺Australia geoffreyr Sydney, AU / Gadigal country
  • 🇦🇺Australia geoffreyr Sydney, AU / Gadigal country
  • 🇦🇺Australia geoffreyr Sydney, AU / Gadigal country
  • Pipeline finished with Success
    6 months ago
    Total: 520s
    #383430
  • 🇷🇺Russia walkingdexter

    I can't reproduce the problem by following these steps with Menu Item Extras 3.1.0. Please provide more information.

    I believe this issue 🐛 option argument 'bundle' sometimes has a NULL value, which can cause issue Fixed covers a similar state, and they proposed to solve it by falling back to the entity type ID.

    In this case the problem is more obvious, as the documentation says that FieldDefinitionInterface::getTargetBundle() can return NULL.

  • Issue was unassigned.
  • Status changed to Closed: cannot reproduce 3 months ago
  • 🇷🇺Russia walkingdexter

    Closing due to lack of activity. Feel free to reopen if you can provide more information.

  • 🇦🇺Australia sonnykt Melbourne, Australia

    I'm having the same error with just core Menu Link Content.

    [error] TypeError: Drupal\simple_sitemap\Entity\EntityHelper::getEntityBundle(): Return value must be of type string, null returned in Drupal\simple_sitemap\Entity\EntityHelper->getEntityBundle() (line 127 of /app/web/modules/contrib/simple_sitemap/src/Entity/EntityHelper.php) #0 /app/web/modules/contrib/simple_sitemap/src/Manager/EntityManager.php(522): Drupal\simple_sitemap\Entity\EntityHelper->getEntityBundle()

    With my debugging, the menu item has empty menu_name:

    > $entity = \Drupal::entityTypeManager()->getStorage('menu_link_content')->load(3466)
    = Drupal\menu_link_content\Entity\MenuLinkContent {#8559
        translationLanguages: "en",
        id (integer): "3466",
        uuid (uuid): "6b349420-2ac0-4514-9e31-8937556131b2",
        revision_id (integer): "4711",
        langcode (language): "en",
        bundle (string): "menu_link_content",
        revision_created (created): "1670367653",
        revision_user (entity_reference): [],
        revision_log_message (string_long): [],
        enabled (boolean): "1",
        title (string): "Guide for determining minor uses",
        description (string): [],
        menu_name (string): [],
    

    and getMenuName() returns NULL for this item

    > $entity->getMenuName()
    = NULL
    

    A deep dive into the database tables of this particular item shows a mismatch in language code between the entity and its revision, hence getMenuName() returns NULL despite the entity has a menu_name in its data table:

    MariaDB [drupal]> select id, revision_id, bundle, langcode from menu_link_content where id = 3466;
    +------+-------------+-------------------+----------+
    | id   | revision_id | bundle            | langcode |
    +------+-------------+-------------------+----------+
    | 3466 |        4711 | menu_link_content | und      |
    +------+-------------+-------------------+----------+
    1 row in set (0.001 sec)
    
    MariaDB [drupal]> select id, revision_id, bundle, langcode, menu_name from menu_link_content_data where id = 3466;
    +------+-------------+-------------------+----------+-----------+
    | id   | revision_id | bundle            | langcode | menu_name |
    +------+-------------+-------------------+----------+-----------+
    | 3466 |        4711 | menu_link_content | und      | main      |
    +------+-------------+-------------------+----------+-----------+
    1 row in set (0.002 sec)
    
    MariaDB [drupal]> select id, revision_id, langcode, default_langcode from menu_link_content_field_revision where id = 3466;
    +------+-------------+----------+------------------+
    | id   | revision_id | langcode | default_langcode |
    +------+-------------+----------+------------------+
    | 3466 |        4711 | en       |                1 |
    +------+-------------+----------+------------------+
    1 row in set (0.002 sec)
    
    MariaDB [drupal]> select id, revision_id, langcode, revision_default from menu_link_content_revision where id = 3466;
    +------+-------------+----------+------------------+
    | id   | revision_id | langcode | revision_default |
    +------+-------------+----------+------------------+
    | 3466 |        4711 | en       |                1 |
    +------+-------------+----------+------------------+
    1 row in set (0.002 sec)
    

    The cause of the mismatch is unknown, but $entity->getMenuName() returning NULL causes EntityHelper::getEntityBundle() to return a TypeError. Not only it breaks the sitemap generating in cron, it also breaks the menu item editing UI due to the same type error.

    As $entity->getMenuName() does not always return a string, I believe that EntityHelper::getEntityBundle() needs to check for its return value.

Production build 0.71.5 2024