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

Command icon 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

codebymikey created an issue. See original summary.

codebymikey’s picture

Issue summary: View changes

codebymikey’s picture

Status: Active » Needs review
Issue tags: +Needs tests

Added 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.

mandclu’s picture

Thanks 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.

codebymikey’s picture

The only part I'm not sure I understand is why the div wrapper is needed in the fallback render.

It 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.

As a potential alternate approach, what about validating the rule object during the initial loop through the $items array?

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.

mandclu’s picture

OK one last thought: in the scenario where the stored rrule value is invalid, should we log an error?

  • mandclu committed b49e57df on 4.2.x authored by codebymikey
    Issue #3380500 by mandclu, codebymikey: User error: "0" is an invalid...
mandclu’s picture

Status: Needs review » Fixed

I 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!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.