Problem/Motivation
If the SmartDateRecurrenceFormatter formatter is used on a pieced of recurring date which happens to no longer have a valid RRule, then it stops processing and passes the raw scalar ID assigned in this block back to the Drupal renderer which is invalid according to #1283892: Let Render API fail in a tale-telling way on invalid $element.
User error: "0" is an invalid render array key in Drupal\Core\Render\Element::children() (line 98 of /app/web/core/lib/Drupal/Core/Render/Element.php) #0
#1 /app/application/web/core/lib/Drupal/Core/Render/Element.php(98): unknown()
#2 /app/application/web/core/lib/Drupal/Core/Field/FormatterBase.php(93): Drupal\Core\Render\Element::children(Array)
#3 /app/application/web/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php(265): Drupal\Core\Field\FormatterBase->view(Object(Drupal\smart_date\Plugin\Field\FieldType\SmartDateFieldItemList), 'en')
#4 /app/application/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php(266): Drupal\Core\Entity\Entity\EntityViewDisplay->buildMultiple(Array)
#5 /app/application/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(339): Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay->buildMultiple(Array)
#6 /app/application/web/core/modules/node/src/NodeViewBuilder.php(24): Drupal\Core\Entity\EntityViewBuilder->buildComponents(Array, Array, Array, 'full')
#7 /app/application/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(281): Drupal\node\NodeViewBuilder->buildComponents(Array, Array, Array, 'full')
#8 /app/application/web/core/lib/Drupal/Core/Entity/EntityViewBuilder.php(238): Drupal\Core\Entity\EntityViewBuilder->buildMultiple(Array)
#9 [internal function]: Drupal\Core\Entity\EntityViewBuilder->build(Array)
Steps to reproduce
Attempt to render a recurring date field which for whatever reason no longer has a valid SmartDateRule.
Proposed resolution
We could add appropriate handling such that invalid recurring dates are removed from the render array, or better yet, are never passed in the first place. Or if they have to, then they should be placed inside an array with a #rrule_id property instead.
Remaining tasks
Provide a suitable workaround for this edge case.
User interface changes
N/A
Issue fork smart_date-3380500
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:
Comments
Comment #2
codebymikey commentedComment #4
codebymikey commentedAdded logic which renders all the date instances if it's unable to load the Smart Date Rule entity, as well as ensure that the
$elements[$delta]is always an array rather than a string/integer.Tests might still be necessary, but this solves the issue for me, and renders exactly as it would post resaving the piece of content with the missing RRule.
Comment #5
mandclu commentedThanks for identifying this, and providing a fix. The only part I'm not sure I understand is why the div wrapper is needed in the fallback render.
As a potential alternate approach, what about validating the rule object during the initial loop through the $items array? Then the items with invalid rrule references could be rendered as normal. If there was only one rule evaluated and it was an invalid reference, perhaps it could even still subset the elements based on the formatter settings, similar to if $force_chrono was true.
Comment #6
codebymikey commentedIt was necessary because without it, the HTML output was in a different format than if it still had an RRule attached - I think from memory, it'd be just the inner content which makes styling a bit more difficult.
That'a a good idea, but given the way the rest of the code worked wrt loading the
SmartDateRule, I didn't want to move the logic around and potentially break something else or make it harder to review.Comment #7
mandclu commentedOK one last thought: in the scenario where the stored rrule value is invalid, should we log an error?
Comment #9
mandclu commentedI added an error since I think it's important to have visibility on where rules could be getting deleted unexpectedly. Thanks for your work on this!