Problem/Motivation

#2361539: Config export key order is not predictable for sequences, add orderby property to config schema introduced \Drupal\Core\Config\Schema\SequenceDataDefinition, a subclass of \Drupal\Core\TypedData\ListDataDefinition which was used until then.

This new class was associated with the sequence config schema type. Everything's been working fine.

But because the new SequenceDataDefinition did not override \Drupal\Core\TypedData\ListDataDefinition::getDataType(), the returned data type is still wrong.

This has not mattered in the >10 years that have passed since #1866610: Introduce Kwalify-inspired schema format for configuration introduced the concept of config schemas nor in the almost 9 years since #2277945: Typed configuration implements TypedDataInterface improperly added typed data integration:

sequence:
  label: Sequence
  class: '\Drupal\Core\Config\Schema\Sequence'
  definition_class: '\Drupal\Core\TypedData\ListDataDefinition'

… but then again:

  1. \Drupal\Core\TypedData\ListDataDefinition is atypical because it overrides the inherited \Drupal\Core\TypedData\DataDefinition::getDataType() which would've returned the correct value
  2. It's only now that we're getting serious about config validation (see #2164373: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs …), which is why I discovered it in #3216089: Expose validation constraints (and validatability %) in Config Inspector UI.

Steps to reproduce

N/A

Proposed resolution

Tests + fix.

Remaining tasks

None.

User interface changes

None.

API changes

None.

Data model changes

None.

Release notes snippet

N/A

Comments

Wim Leers created an issue. See original summary.

wim leers’s picture

Assigned: xjm » wim leers

Oops! 😅

wim leers’s picture

Assigned: wim leers » Unassigned
Status: Active » Needs review
StatusFileSize
new1.31 KB
new1.9 KB
wim leers’s picture

wim leers’s picture

How the hell did you run into this?

I worked around it in contrib like this:

  /**
   * Work-around for bug introduced in #2361539.
   *
   * @see \Drupal\Core\TypedData\ListDataDefinition::getDataType()
   * @see \Drupal\Core\Config\Schema\SequenceDataDefinition
   * @see https://www.drupal.org/project/drupal/issues/2361539
   * @todo Remove this when this module requires a Drupal core version that includes https://www.drupal.org/project/drupal/issues/3361034.
   */
  protected static function getDataType(TypedDataInterface $typed_data) : string {
    $data_type = $typed_data->getDataDefinition()->getDataType();
    if ($data_type === 'list') {
      $data_type = 'sequence';
    }
    return $data_type;
  }

… because without this, it's impossible to correctly traverse a typed data tree by using the return value of $typed_data->getDataDefinition()->getDataType() … since list is not actually a config schema type, \Drupal\Core\Config\TypedConfigManager::determineType() decides to make it automagically fall back to the undefined type 😳

… at which point traversing further down the three of course is impossible.

Why can this go undiscovered for a decade?

The reason this has not caused problems for Drupal core so far is that \Drupal\Core\TypedData\Validation\RecursiveContextualValidator::validateNode() does not use the full config schema tree, but instead relies on inspecting the typed data's object instances:

    // If the data is a list or complex data, validate the contained list items
    // or properties. However, do not recurse if the data is empty.
    // Next, we do not recurse if given constraints are validated against an
    // entity, since we should determine whether the entity matches the
    // constraints and not whether the entity validates.
    if (($data instanceof ListInterface || $data instanceof ComplexDataInterface) && !$data->isEmpty() && !($data instanceof EntityAdapter && $constraints_given)) {
      foreach ($data as $property) {
        $this->validateNode($property);
      }
    }
borisson_’s picture

Status: Needs review » Reviewed & tested by the community

Super interesting bug, good find. Are the other TypedData classes correct?

wim leers’s picture

Are the other TypedData classes correct?

FieldConfigBase::getDataType() is wrong too:

  public function getDataType() {
    return 'list';
  }

… but I figured we'd keep this tightly scoped, because that is one of the most complex pieces of config 😱

The last submitted patch, 3: 3361034-3-test-only-FAIL.patch, failed testing. View results

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 3: 3361034-3.patch, failed testing. View results

borisson_’s picture

Status: Needs work » Reviewed & tested by the community

Looks like a random failure to me

quietone’s picture

Title: `sequence` Typed Data instances return wrong data type: `list` instead of `sequence` » Make 'sequence' Typed Data instances return type of 'sequence' instead of 'list'

Triaging the RTBC queue.

What a easy issue to triage! The IS is clear and enjoyable to read. The situation is further explained in comment #5. I also agree with the scoping. All questions have been answered.

The only thin I see that it does appear this a followup is needed for #7.

I have updated the title to explain what is being changed.

wim leers’s picture

#11 That's LOVELY to hear! 😊😊 Glad to read it helps and is appreciated!

New issue created, with a lot more detail than was present in #7: #3370179: Clarify why FieldConfigBase::getDataType() is 'list' and not 'field_config_base'.

fago’s picture

Good find! Yes, the typed-data implementation of config wasn't focused enough on implementing its contract cleanly.

The fix is straight forward, the right thing todo and comes with test! I second the RTBC!

lauriii’s picture

Issue tags: +Needs change record

Discussed with @longwave and @fago and agreed that we should write a short change record for the behavior change here.

fago’s picture

Issue tags: -Needs change record

I've added a change record draft

  • lauriii committed 89ac074f on 11.x
    Issue #3361034 by Wim Leers, fago, borisson_, longwave:  Make 'sequence...

lauriii credited longwave.

lauriii’s picture

Status: Reviewed & tested by the community » Fixed

Committed 89ac074 and pushed to 11.x. Thanks!

Status: Fixed » Closed (fixed)

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