Problem/Motivation

When switching an old D7 website to PHP 7.4 I get the following notices at several points.

Notice: Trying to access array offset on value of type null in entity_extract_ids() (line 8000 of /home/kwbirds/public_html/includes/common.inc).
Notice: Trying to access array offset on value of type null in entity_extract_ids() (line 8001 of /home/kwbirds/public_html/includes/common.inc).

It seems that whenever a taxonomy term is rendered in a custom view mode it comes with empty entity_keys and this causes the lines 8000 and 8001 in includes/common.inc to through the above notices. The same notices are produced in the "Manege Display" page of the same content type.
This might have to do with Display Suite through which the custom view modes are created, but the issue would remain that the entity_extract_ids function can not cope with empty entity keys under PHP 7.4.

Lines 8000 and 8001 of common.inc:

  $id = isset($entity->{$info['entity keys']['id']}) ? $entity->{$info['entity keys']['id']} : NULL;
  $vid = ($info['entity keys']['revision'] && isset($entity->{$info['entity keys']['revision']})) ? $entity->{$info['entity keys']['revision']} : NULL;

As a temporary workaround and trying to understand what is happening I replaced the above two lines with the following which avoids the notices and also displays some information about the missing entity keys:

  if (!empty($info['entity keys'])) {
  $id = isset($entity->{$info['entity keys']['id']}) ? $entity->{$info['entity keys']['id']} : NULL;
  $vid = ($info['entity keys']['revision'] && isset($entity->{$info['entity keys']['revision']})) ? $entity->{$info['entity keys']['revision']} : NULL;
  }
  else {
    $id = '';
    $vid = '';
    $testmsg = $entity_type . " Empty entity keys";
    echo htmlspecialchars($testmsg, ENT_QUOTES, 'UTF-8');
  }

Here the taxonomy term is rendered in the header of a view (look for the text "term Empty entity keys"):
http://www.kuwaitbirds.org/birds/conservation-status/vulnerable

And here two taxonomy term reference fields are shown in custom view modes too:
http://www.kuwaitbirds.org/birds/levant-sparrowhawk

Issue fork drupal-3166668

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

arx-e created an issue. See original summary.

Neeraj420’s picture

@arx-e Have you got any solution for this issue?

arx-e’s picture

I made this patch where I got rid of the "if .. else" by nesting the ternary operator statements. I tested it i a couple of Drupal 7 sites and it applies cleanly and works to avoid the related error messages.

arx-e’s picture

Status: Active » Needs review
Neeraj420’s picture

@arx-e

Though I have not done a detailed testing, however issue was resolved once changes were made directly to common.inc file. I wish if this can be committed into the main branch of Drupal core.

vlad.dancer’s picture

Status: Needs review » Reviewed & tested by the community

Hey @arx-e.
> It seems that whenever a taxonomy term is rendered in a custom view mode it comes with empty entity_keys
The same thing for me too.

Thanks for the patch. The code looks good to me.
I've tested on Drupal 7.78 under PHP 7.4.10, the patch applied without problems.

Let's push it further!

arx-e’s picture

Myddna’s picture

Hi!

Just tested the patch in #7 against 7.80 and it applied OK.

arx-e’s picture

@Myddna

That shouldn't be OK!
The common.inc file has change between versions 7.79 and 7.80 and 6 lines have been added before this point (line 8013 is now line 8019).
So a new patch should be created which I will try to do ASAP.

MaxMendez’s picture

Fixed my problem the patch #10, thanks for your work

akhilavnair’s picture

Hi,

Patch #10 works fine. Could you please merge this to Drupal 7.80.

mcdruid’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs tests
FileSize
1.02 KB
1.03 KB

Thanks for the patch.

However, I'd prefer not to see the ternaries wrapped in more ternaries.

How about something simple like this patch?

Also, this should ideally have tests. They could be very basic.

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community

RTBC + 1

arx-e’s picture

@mcdruid As you can see in the original post that was my first though and try. But my experience with code and best practices is very limited and I didn't know that nested ternaries are something unwelcome. I wet with them as they resulted in less code/changes.

And I don't have an inkling of how one would add tests. Sorry!

joseph.olstad’s picture

Prefer patch 14 after comparing with the MR.

Thanks

akhilavnair’s picture

Issue tags: -Needs tests +merge
jenlampton’s picture

Confirming latest patch in #14 still applies cleanly and resolves the issue on PHP 7.4.
I'm not sure of the status of the MR. Are all the commits showing here just rebases from 7.x?

mcdruid’s picture

Issue tags: -merge +Needs tests

I'm not sure of the status of the MR. Are all the commits showing here just rebases from 7.x?

...yes, looks like it.

I'd still like to see some (very basic) tests for this.

alrueden’s picture

Patch at #14 works for me (albeit the line numbers have changed now).

Acquia is updating all hosted D7 sites to PHP 7.4 on October 4, 2021. Any chance this could get committed before that happens? I'd love to not have a core patch!

igorbarato made their first commit to this issue’s fork.

igorbarato’s picture

I updated the MR with the latest Drupal core updates and tested them.

Bhanu951’s picture

Confirming latest MR in #25 applies cleanly and resolves the issue on PHP 7.4.

+1 from me for RTBC.

poker10’s picture

While I was experimenting with a possible test to this issue I found out that the problem is a little bit different as it is presented in the issue summary.

I was able to simulate the notice (somehow playing with display_suite settings) and it was not caused by empty entity keys, but the whole empty $info variable. See longer decription below:

------------

The if condition in the issue summary does not only cover this one possibility, it could also be a case where the whole $info variable is empty:

if (!empty($info['entity keys'])) {
  ....
} else {
  ....
}

This code will reach the else block if entity keys are empty OR if the $info variable is empty. The variable will be empty everytime you call entity_get_info() with a name of non-existing entity.

I was not able to simulate the problem with empty entity keys and while digging into it, it seems like that the function entity_get_info() always set the content of entity keys:

      $entity_info = module_invoke_all('entity_info');
      // Merge in default values.
      foreach ($entity_info as $name => $data) {
        $entity_info[$name] += array(
          'fieldable' => FALSE,
          'controller class' => 'DrupalDefaultEntityController',
          'static cache' => TRUE,
          'field cache' => TRUE,
          'load hook' => $name . '_load',
          'bundles' => array(),
          'view modes' => array(),
          'entity keys' => array(),
          'translation' => array(),
        );
        $entity_info[$name]['entity keys'] += array(
          'revision' => '',
          'bundle' => '',
        );
        ...

So even in case that the returned entity has empty entity keys, this function will set at least the array with empty revision and empty bundle. Only way how this could be empty would be if the drupal_alter() called afterwards will unset it and that is unlikely to happen...

// Let other modules alter the entity info.
drupal_alter('entity_info', $entity_info);

-----------

So my testing revealed that the display suite is (in some circumstances) calling the entity_get_info() with the $entity_type = 'term'. This will cause the $info variable to be NULL, because the correct entity type for taxonomy terms is 'taxonomy_term'.

    // Move any preprocess fields to render container.
    // Inconsistency in taxonomy term naming.
    $entity_type = $vars['elements']['#entity_type'];
    if ($vars['elements']['#entity_type'] == 'taxonomy_term') {
      $entity_type = 'term';
    }

    // Get entity id and bundle
    $id = NULL;
    $bundle = $vars['elements']['#bundle'];
    $entity = isset($vars[$entity_type]) ? $vars[$entity_type] : (isset($vars['elements']['#' . $entity_type]) ? $vars['elements']['#' . $entity_type] : NULL);
    list($id,, $bundle) = entity_extract_ids($entity_type, $entity);

There is a clear Display Suite bug - they are changing the $entity_type variable for the entity retrieval from the $vars array, but also passing the changed variable to the entity_extract_ids() without setting it back.

------------

But anyway, I think it would be good to sanitize this also on the Drupal core side, because this situation is not handled correctly and the NULL value is used as an expected array later (without check what entity_get_info() returned). This can cause issues in PHP 7.4+.

function entity_extract_ids($entity_type, $entity) {
  $info = entity_get_info($entity_type);
  // Objects being created might not have id/vid yet.
  $id = isset($entity->{$info['entity keys']['id']}) ? $entity->{$info['entity keys']['id']} : NULL;

So if we check the $info variable, it will create a better code (from my point of view). See my patch proposal. What do you think?

The last submitted patch, 28: 3166668-28-test-only.patch, failed testing. View results

mcdruid’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs tests +Pending Drupal 7 commit

I think this looks good, thank you!

Is there an issue filed for the problem in Display Suite described in #28?

Fabianx’s picture

Assigned: Unassigned » mcdruid

RTBC again, let's get this in!

  • mcdruid committed c985a67 on 7.x
    Issue #3166668 by akhilavnair, arx-e, poker10, mcdruid, igorbarato,...

Status: Fixed » Closed (fixed)

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