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 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.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

geoffreyr created an issue. See original summary.

geoffreyr’s picture

Issue summary: View changes

geoffreyr’s picture

Assigned: geoffreyr » Unassigned
Status: Active » Needs review
walkingdexter’s picture

Version: 4.2.2 » 4.x-dev
Status: Needs review » Postponed (maintainer needs more info)

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 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.

walkingdexter’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)

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

sonnykt’s picture

Status: Closed (cannot reproduce) » Active

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.

anybody’s picture

Priority: Normal » Major

I can also confirm this issue. This entirely blocks deleting a custom menu item, as the error appears and the item can't be deleted. Implementation needs to be more defensive, as multiple people already ran into this.

anybody’s picture

Status: Active » Reviewed & tested by the community

MR !118 fixes the issue for me, now the menu item can be deleted as expected. Still the maintainer should check, if the implementation is the correct fix, I can't tell.

gbyte’s picture

Priority: Major » Normal

  • gbyte committed f90a08b4 on 4.x authored by geoffreyr
    Issue #3496884: EntityHelper::getEntityBundle can sometimes return NULL...
gbyte’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

anybody’s picture

@gbyte could you please tag a new release with this fix? Thanks! :)

gbyte’s picture

@gbyte could you please tag a new release with this fix? Thanks! :)

Will do soon, though I would add releasing a new minor version is a bit more involved than 'tagging .'

anybody’s picture

Yes, sorry if my phrasing was incorrect.

gbyte’s picture

@gbyte could you please tag a new release with this fix? Thanks! :)

That's done.