Problem/Motivation
When creating a series with multiple custom instances, the instances are created without their workflow status set to match the series.
Steps to reproduce
- On a fresh Drupal install, enable recurring events and content moderation.
- Configure the "Editorial" workflow to apply to both event series and event instances.
- Create a new event series and select the "Custom/Single Event" recur type.
- Enter the start and end dates/times for the custom instance.
- Click "Add another item" and enter the start and end dates/times for a second custom instance.
- Set the "Save As" field to "Published" and click Save.
Expected result: The series and both instances should be created as published.
Actual result: The series is published, but the instances are in Draft state.
Note that the problem does not occur if you only create one custom instance (i.e., if you don't click the "Add another item" button). This is a side effect of the AJAX action when you click "Add another item". When the form refreshes, the 'event_instances' computed field on the series entity is evaluated and its value is stored as an empty array (because the instances haven't been created yet). Saving the event then triggers recurring_events_eventseries_insert(), which calls $creation_service->createInstances($entity); to create the instances, then $entity->event_instances->referencedEntities(); to get the instances just created. However, because the computed field is only calculated the first time it is called, this returns the empty array, causing the function to skip the calls to $creation_service->configureDefaultInheritances($instance, $entity->id()); and $creation_service->updateInstanceStatus($instance, $entity); (see recurring_events.module, lines 161–171).
This is easily demonstrated with Xdebug by placing breakpoints in recurring_events_eventseries_insert() and \Drupal\recurring_events\Plugin\ComputedField\EventInstances::computeValue(). If you only create one custom instance, computeValue() isn't invoked until the field is called by the _insert() hook, yielding the correct result. If you click the "Add another item" button, however, computeValue() is invoked during the form rebuild (returning empty), and then not again until after the _insert() hook runs (when the page redirects to the entity view, starting a new request).
Proposed resolution
Change \Drupal\recurring_events\EventCreationService::createInstances() to return the array of instances it creates, and then use that in recurring_events_eventseries_insert() rather than relying on the computed field to query the instances.
API changes
\Drupal\recurring_events\EventCreationService::createInstances() will now return an array. This shouldn't be a problem because the method currently returns void, so no existing code should be using its return value before this change.
Issue fork recurring_events-3318998
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:
- 3318998-instances-not-created
changes, plain diff MR !56
Comments
Comment #2
muriqui commentedComment #4
muriqui commentedComment #5
owenbush commentedThank you for this issue. This looks good to me. I wonder if the underlying issue is that ->referencedEntities() is cached and not returning all the instances. This has happened elsehwere a number of times and the solution before was to load a fresh copy of the eventseries, but given that the creation service already returns the instances, using that makes sense. I'll get this merged when gitlab isn't being a jerk.
Comment #8
owenbush commentedMerged into the latest dev branch for 8.x-1.x and 2.0.x. Thank you!