- 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(); } }