Call to a member function isEmpty() on null in date_recur_search_api_entity_build_defaults_alter

Created on 22 July 2024, 3 months ago

Problem/Motivation

When viewing an entity with a computed date_recur occurance field outside of search_api, even when this is disabled, we are seeing a WSOD with the following PHP error.

Error: Call to a member function isEmpty() on null in date_recur_search_api_entity_build_defaults_alter() (line 39 of /var/www/html/docroot/modules/contrib/date_recur_search_api/date_recur_search_api.module).

This happens becuase date_recur_search_api_entity_build_defaults_alter tries to retrive a value for the date occurance field, but this is NULL outside of search api indexes.

Steps to reproduce

Install this module and set up reccuring dates in the way described
Go to a page that has the reccuring date.
See error.

Ordinarly we hide it and use the standard date field in manage display.
We have tried this with and without the date_occurance computed field set to show and still get the error.

Proposed resolution

Add an extra check to make sure that what is being brought back from $entity->get($field_name)->get(0) is not null (or actually an instance of use Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem;).

Remaining tasks

Make a patch.

🐛 Bug report
Status

Active

Version

1.0

Component

Code

Created by

🇬🇧United Kingdom andybroomfield

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

Merge Requests

Comments & Activities

  • Issue created by @andybroomfield
  • Status changed to Needs review 3 months ago
  • 🇬🇧United Kingdom andybroomfield

    Added initial patch in MR.

  • 🇬🇧United Kingdom andybroomfield

    We're not setting this to anything, it's just a NULL value if it's not computed becuase we're viewing the entity page. it's outside of a search api view. But we get the WSOD even though we don't have the computed field in our manage display. It throws the error regardless.

  • 🇬🇧United Kingdom joachim

    It sounds like the computed field is not correctly reporting that it's empty?

  • Status changed to Postponed: needs info 3 months ago
  • 🇬🇧United Kingdom joachim

    Sorry, I misread the error message.

    > Call to a member function isEmpty() on null

    That means that the $entity->get(FIELD) failed.

    Why is the field missing? Can you debug?

  • 🇬🇧United Kingdom andybroomfield

    Looking at $entity->get($field) on the node page gives me

    Drupal\computed_field\Field\ComputedFieldClass {#2574 ▼
      #definition: 
    Drupal\computed_field\Field
    \
    ComputedFieldDefinition {#2572 ▶}
      #name: "localgov_event_date_occurrence"
      #parent: 
    Drupal\Core\Entity\Plugin\DataType
    \
    EntityAdapter {#2423 ▶}
      #_serviceIds: []
      #_entityStorages: []
      #stringTranslation: null
      #typedDataManager: 
    Drupal\Core\TypedData
    \
    TypedDataManager {#594 ▶}
      #list: []
      #langcode: "en"
      #valueComputed: true
    }

    On the Search API page I get

    Drupal\computed_field\Field\ComputedFieldClass {#9711 ▼
      #definition: 
    Drupal\computed_field\Field
    \
    ComputedFieldDefinition {#9742 ▶}
      #name: "localgov_event_date_occurrence"
      #parent: 
    Drupal\Core\Entity\Plugin\DataType
    \
    EntityAdapter {#9788 ▶}
      #_serviceIds: []
      #_entityStorages: []
      #stringTranslation: null
      #typedDataManager: 
    Drupal\Core\TypedData
    \
    TypedDataManager {#1240 ▶}
      #list: array:1 [▼
        0 => 
    Drupal\datetime_range\Plugin\Field\FieldType
    \
    DateRangeItem {#9688 ▼
          #definition: 
    Drupal\Core\Field\TypedData
    \
    FieldItemDataDefinition {#9741 ▶}
          #name: 0
          #parent: 
    Drupal\computed_field\Field
    \
    ComputedFieldClass {#9711}
          #_serviceIds: []
          #_entityStorages: []
          #stringTranslation: null
          #typedDataManager: 
    Drupal\Core\TypedData
    \
    TypedDataManager {#1240 ▶}
          #values: array:3 [ …3]
          #properties: array:2 [ …2]
        }
      ]
      #langcode: "en"
      #valueComputed: true
    }

    I traced the NULL value to docroot/core/lib/Drupal/Core/TypedData/ComputedItemListTrait.php which the get method returns NULL if there is no value in the index.

      public function get($index) {
        if (!is_numeric($index)) {
          throw new \InvalidArgumentException('Unable to get a value with a non-numeric delta in a list.');
        }
    
        // Unlike the base implementation of
        // \Drupal\Core\TypedData\ListInterface::get(), we do not add an empty item
        // automatically because computed item lists need to behave like
        // non-computed ones. For example, calling isEmpty() on a computed item list
        // should return TRUE when the values were computed and the item list is
        // truly empty.
        // @see \Drupal\Core\TypedData\Plugin\DataType\ItemList::get().
        $this->ensureComputedValue();
    
        return $this->list[$index] ?? NULL;
      }
    

    I think it returns NULL as the ComputeValue of src/Plugin/ComputedField/DateOccurrence.php will return an empty array. I can change this to ['now'] and the entity pages get a dateTime of the current date.

  • 🇬🇧United Kingdom joachim

    Oh. There are two get() calls and they're not the same. That's why I'm confused!

        $date_occurrence_field = $entity->get($field_name)->get(0);
    

    $entity->get(FIELDNAME) gets us the FieldItemListInterface for the field. That one's fine, right?

    FieldItemListInterface->get(0) is one of those weird magic ones maybe?

    Maybe we should be calling isEmpty() on the FieldItemListInterface instead? Can you try that?

  • Status changed to Needs review 3 months ago
  • 🇬🇧United Kingdom andybroomfield

    Bumping back to needs review for the updated MR.

  • Pipeline finished with Skipped
    2 days ago
    #311331
  • 🇬🇧United Kingdom joachim

    Sorry it's taken me this long to look at this.

    Reproduced the bug, confirmed the fix.

    Will make a new release.

    Thanks!

Production build 0.71.5 2024