What's the difference between date field in opening and opening instances

Created on 7 February 2025, 3 months ago

Problem/Motivation

I don't really understand how to manage correctly the opening instances.
There is two ways :

1. Create an opening and add "dates" into the according field. This create new instances, but if the instances has additional fields, we must edit the instances to set correct values (for example price, location, etc...)
Using this way add the value into the "date" field and is accessible via $bookable_calendar_opening->booking_instance->referencedEntities().

2. If an opening already exists, we can use the "Add bookable calendar opening instance" on the "Opening instances" tab of the administration page (admin/content/bookable-calendar/bookable-calendar-opening-instance).
Using this way create a new instance, we can properly fill the additional fields BUT it doesn't add the "date" into date field of the opening itself... So $bookable_calendar_opening->booking_instance doesn't store the instances created in this way.

Proposed resolution

I don't have digg into the code of each (opening and opening instances) but it seems when a new opening instance is created manually, it would add the new "date" into the according field.

Or maybe you can explain how the system works like this and there is a "lack" between the date field of opening and the opening instances created...

Thanks for your answer.

πŸ’¬ Support request
Status

Active

Version

2.2

Component

Miscellaneous

Created by

πŸ‡¨πŸ‡­Switzerland titouille

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

Comments & Activities

  • Issue created by @titouille
  • πŸ‡ΊπŸ‡ΈUnited States josh.fabean

    Hi,

    You are correct that it is currently a one way push from the repeating date field into individual instances.

    Are you doing different location, price and things per individual instance, if not you could put that on the calendar or on the opening and pull it into the display with a relationship instead of filling each instance with duplicate information.

    There is code to handle going to an individual opening instance, deleting it, and it deleting it from the parent opening but not adding, I'm also not sure how hard it would be to push dates into the date repeat rule either trying to do it that way.

    The code where we handle adding an exception to the repeat rule on delete is here: https://git.drupalcode.org/project/bookable_calendar/-/blob/2.2.x/src/En...

    I'm not sure the repeat rule would work but we could probably just have it add a one off date taking advantage of the multiple values that are allowed on the date field in the opening itself.

  • πŸ‡¨πŸ‡­Switzerland titouille

    Hi josh,

    Thank you for your answer. And yes, it's exactly the case. I must create opening instances with different prices / locations / additional informations, so it's not a way to store data in opening and use some sort of render to display it.

    I saw another problem on the current implementation and the manual creation of instances. Because the opening doesn't store the date of the manually created instance, if I try to update the opening itself, it iterate over existing instances and delete the ones that doesn't has a date in opening, except if the instance has already some bookings.

    So the problem is if some manually created instances has no booking, they will be deleted if the opening is updated...

    I resolved the unidirectional problem with hook_entity_insert :

    
    /**
     * Implements hook_entity_update().
     */
    function MYMODULE_entity_insert(EntityInterface $entity) {
      // Exit if the entity is not an opening instance.
      if (!$entity instanceof BookableCalendarOpeningInstance) {
        return;
      }
      if ($entity->bundle() == "bookable_calendar_opening_inst") {
        // Get the current instance date.
        /** @var \Drupal\bookable_calendar\Entity\BookableCalendarOpeningInstance $entity */
        $date = $entity->get('date')->getValue();
        $instance_date = $date[0];
    
        // Get all dates in parent opening.
        /** @var \Drupal\bookable_calendar\Entity\BookableCalendarOpening $opening */
        $opening = $entity->getParentOpening();
        $opening_dates = $opening->get('date')->getValue();
    
        // Check if the instance date exists on opening. It can be the case if the instance is 
        // created on filling the opening itself with a new date.
        $exists = FALSE;
        foreach ($opening_dates as $d) {
          if ($d['value'] == $instance_date['value'] && $d['end_value'] == $instance_date['end_value']) {
            $exists = TRUE;
            break;
          }
        }
        if (!$exists) {
          // Insert new date into opening.
          $opening_dates[] = [
            'value' => $instance_date['value'],
            'end_value' => $instance_date['end_value'],
            'duration' => $instance_date['duration'],
            'timezone' => $instance_date['timezone'],
            'rrule' => NULL,
            'rrule_index' => NULL,
          ];
    
          $opening->set('date', $opening_dates);
          $opening->save();
        }
      }
    }
    

    I'm not sure for the following, but I must implement hook_entity_delete to clear cache of opening when an opening instance is deleted. I noticed that when I remove an opening instance from the opening instances list, the cache of the parent opening is not cleared. The date for the deleted instance remains in opening, and if I edit and save the opening, it recreate the deleted opening instance...

    /**
     * Implements hook_entity_delete().
     */
    function MYMODULE_entity_delete(EntityInterface $entity) {
      if (!$entity instanceof BookableCalendarOpeningInstance) {
        return;
      }
      /** @var \Drupal\bookable_calendar\Entity\BookableCalendarOpeningInstance $entity */
      /** @var \Drupal\bookable_calendar\Entity\BookableCalendarOpening $opening */
      $opening = $entity->getParentOpening();
      \Drupal::entityTypeManager()->getStorage('bookable_calendar_opening')->resetCache([$opening->id()]);
    }
    

    Maybe you can try yourself and make a correction on these problems.

    Best regards.

  • πŸ‡¨πŸ‡­Switzerland titouille

    Little mistake on my code. booking_instance field of opening must be filled with new instance too...

    /**
     * Implements hook_entity_update().
     */
    function MYMODULE_entity_insert(EntityInterface $entity) {
      // Exit if the entity is not an opening instance.
      if (!$entity instanceof BookableCalendarOpeningInstance) {
        return;
      }
      /** @var \Drupal\bookable_calendar\Entity\BookableCalendarOpeningInstance $entity */
      $date = $entity->get('date')->getValue();
      $instance_date = $date[0];
      /** @var \Drupal\bookable_calendar\Entity\BookableCalendarOpening $opening */
      $opening = $entity->getParentOpening();
    
      $opening_dates = $opening->get('date')->getValue();
      $exists = FALSE;
      foreach ($opening_dates as $d) {
        if ($d['value'] == $instance_date['value'] && $d['end_value'] == $instance_date['end_value']) {
          $exists = TRUE;
          break;
        }
      }
      if (!$exists) {
        // Insert new date into opening.
        $opening_dates[] = [
          'value' => $instance_date['value'],
          'end_value' => $instance_date['end_value'],
          'duration' => $instance_date['duration'],
          'timezone' => $instance_date['timezone'],
          'rrule' => NULL,
          'rrule_index' => NULL,
        ];
        $opening->set('date', $opening_dates);
    
        // Set new booking instance in opening.
        $booking_instances = $opening->get('booking_instance')->getValue();
        if (!isset($booking_instances)) {
          $booking_instances = [];
        }
        $booking_instances[] = [
          'target_id' => $entity->id(),
        ];
        $opening->set('booking_instance', $booking_instances);
    
        // Save opening.
        $opening->save();
      }
    }
    
Production build 0.71.5 2024