Creating a new inheritance doesn't get added to existing children

Created on 21 June 2024, 12 months ago

There is a fault in field_inheritance, when you add new fields/inheritances, it doesn't get updated on the old eventinstances until they get saved from the form. Saving the entity programmatically doesnt do it alone.

This is because the logic that links eventinstances and eventseries together is set by field_inheritance directly in the form_alter and form_submit.

This is an example of how i semi-manually fixed my existing children (eventinstances) to respect a new field. I've run this in an update hook:

/**
 * Linking new field inheritances with existing eventinstances.
 *
 * There is a fault in field_inheritance, when you add new fields/inheritances,
 * it doesn't get updated on the old eventinstances until they get saved from
 * the form.
 * This is because the logic that links eventinstances and eventseries together
 * is set by field_inheritance directly in the form_alter and form_submit.
 * This helper function allows you to pass along a name of a field inherited
 * field that has been set up at /admin/structure/field_inheritance, and
 * the helper will find all eventinstances and make sure the new field is
 * linked together with the relevant eventseries.
 */
function _example_module_update_field_inheritance($field_inheritance_name): string {
  $ids =
    \Drupal::entityQuery('eventinstance')
      ->accessCheck(FALSE)
      ->execute();

  if (empty($ids) || is_int($ids)) {
    return 'No entities to update.';
  }

  $entities =
    \Drupal::entityTypeManager()->getStorage('eventinstance')->loadMultiple($ids);

  $count = 0;

  foreach ($entities as $entity) {
    try {
      if (!($entity instanceof EventInstance)) {
        continue;
      }

      $event_series = $entity->getEventSeries();

      if (!($event_series instanceof EventSeries)) {
        continue;
      }

      // This matches the key that is defined in field_inheritance.
      $state_key = $entity->getEntityTypeId() . ':' . $entity->uuid();
      $field_inheritance = \Drupal::keyValue('field_inheritance')->get($state_key);

      // In theory, an eventinstance could be set up to inherit from another
      // entity than the eventseries - but in practice, this is really unlikely,
      // and something we're willing to disregard.
      $field_inheritance[$field_inheritance_name] = [
        'entity' => $event_series->id(),
      ];

      \Drupal::keyValue('field_inheritance')->set($state_key, $field_inheritance);

      $entity->save();
      $count++;
    }
    catch (\Exception $e) {
      \Drupal::logger('example_module')->error('Could not update field_inheritance on eventinstance @id - Error: @message', [
        '@message' => $e->getMessage(),
        '@id' => $entity->id(),
      ]);
    }
  }

  return t(
    "Updated @count eventinstances, linking field  '@field' to inherit from eventseries.",
    ['@field' => $field_inheritance_name, '@count' => $count]
  )->render();
}

🐛 Bug report
Status

Active

Version

2.0

Component

Code

Created by

🇩🇰Denmark ras-ben Copenhagen

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

Comments & Activities

  • Issue created by @ras-ben
  • 🇪🇸Spain plopesc Valladolid

    I see your point, but not sure how to approach it.

    Technically each field_inheritance can depend on a different entity. Event Instance A might use the title of Event Series X and the location of EventSeries Y, hence we need an explicit action for defining them.

    That's an edge case, but the approach taken there, even if smart, would not cover all the scenarios.

    I was thinking in something more in the line of adding an option in the entity form that says "All the Inheritance from Entity:Bundle X will share the source" and store it as it is in the DB. Then, for entities with that option enabled, those fields will automatically be inherited. Meanwhile, regular fields with explicit assignation would remain as they now, waiting for an explicit assignation.

Production build 0.71.5 2024