Problem/Motivation

\Drupal\field\Entity\FieldStorageConfig::id():

  public function id() {
    return $this->getTargetEntityTypeId() . '.' . $this->getName();
  }

and \Drupal\field\Entity\FieldStorageConfig::loadByName():

  public static function loadByName($entity_type_id, $field_name) {
    return \Drupal::entityTypeManager()->getStorage('field_storage_config')->load($entity_type_id . '.' . $field_name);
  }

and worse:
\Drupal\Core\Field\FieldConfigBase::id():

  public function id() {
    return $this->entity_type . '.' . $this->bundle . '.' . $this->field_name;
  }

and \Drupal\field\Entity\FieldConfig::loadByName():

  public static function loadByName($entity_type_id, $bundle, $field_name) {
    return \Drupal::entityTypeManager()->getStorage('field_config')->load($entity_type_id . '.' . $bundle . '.' . $field_name);
  }

(Same thing for \Drupal\Core\Field\Entity\BaseFieldOverride::loadByName(): 3 parameters that together create the name/ID.)

The corresponding config entity type annotations do not have any metadata at all that would allow us to construct these IDs automatically. They contain a config_prefix key-value pair, but not something like a config_name_parts key-value pair.

Until Drupal core provides an API for this, we have no choice but to hardcode these three. We can find them by searching for .*.* in *.schema.yml files.

But … that's how we can discover there's actually several more: core.entity_view_mode.*.*, core.entity_form_mode.*.*, core.entity_view_display.*.*.* and core.entity_form_display.*.*.*. For these, all of the mapping/loading logic is embedded in \Drupal\Core\Entity\EntityDisplayRepository.

Steps to reproduce

Proposed resolution

Harden \Drupal\jsonapi_schema\StaticDataDefinitionExtractor::extractConfigEntityType().

Remaining tasks

User interface changes

API changes

Data model changes

Comments

Wim Leers created an issue. See original summary.

wim leers’s picture

Title: Special case config entities with multi-part IDs: field_storage_config, field_config, entity_view_mode, entity_form_mode, entity_view_display and entity_form_display » Schema incorrect for config entity types with multi-part IDs (field_storage_config, field_config, entity_view_mode, entity_form_mode, entity_view_display and entity_form_display)
Assigned: wim leers » Unassigned
Status: Active » Needs review
StatusFileSize
new1.94 KB

Response for /jsonapi/field_storage_config/field_storage_config/resource/schema:

Before
{
  "$schema": "https://json-schema.org/draft/2019-09/hyper-schema",
  "$id": "http://core.test/jsonapi/field_storage_config/field_storage_config/resource/schema",
  "title": "Field storage",
  "allOf": [
    {
      "type": "object",
      "properties": {
        "type": {
          "$ref": "#/definitions/type"
        },
        "attributes": {
          "$ref": "#/definitions/attributes"
        }
      }
    },
    {
      "$ref": "https://jsonapi.org/schema#/definitions/resource"
    }
  ],
  "definitions": {
    "type": {
      "const": "field_storage_config--field_storage_config"
    },
    "attributes": {
      "properties": {
        "drupal_internal__id": {
          "title": "drupal_internal__id"
        },
        "langcode": {
          "title": "langcode"
        },
        "status": {
          "title": "status"
        },
        "dependencies": {
          "title": "dependencies"
        },
        "third_party_settings": {
          "title": "third_party_settings"
        },
        "field_name": {
          "title": "field_name"
        },
        "entity_type": {
          "title": "entity_type"
        },
        "field_storage_config_type": {
          "title": "field_storage_config_type"
        },
        "settings": {
          "title": "settings"
        },
        "module": {
          "title": "module"
        },
        "locked": {
          "title": "locked"
        },
        "cardinality": {
          "title": "cardinality"
        },
        "translatable": {
          "title": "translatable"
        },
        "indexes": {
          "title": "indexes"
        },
        "persist_with_no_fields": {
          "title": "persist_with_no_fields"
        },
        "custom_storage": {
          "title": "custom_storage"
        }
      },
      "additionalProperties": false
    }
  }
}
After
{
  "$schema": "https://json-schema.org/draft/2019-09/hyper-schema",
  "$id": "http://core.test/jsonapi/field_storage_config/field_storage_config/resource/schema",
  "title": "Field storage",
  "allOf": [
    {
      "type": "object",
      "properties": {
        "type": {
          "$ref": "#/definitions/type"
        },
        "attributes": {
          "$ref": "#/definitions/attributes"
        }
      }
    },
    {
      "$ref": "https://jsonapi.org/schema#/definitions/resource"
    }
  ],
  "definitions": {
    "type": {
      "const": "field_storage_config--field_storage_config"
    },
    "attributes": {
      "properties": {
        "drupal_internal__id": {
          "type": "string",
          "title": "drupal_internal__id"
        },
        "langcode": {
          "type": "string",
          "title": "langcode"
        },
        "status": {
          "type": "boolean",
          "title": "status"
        },
        "dependencies": {
          "title": "dependencies"
        },
        "third_party_settings": {
          "type": "array",
          "items": {
            "properties": {
              "third_party_settings": {
                "title": "third_party_settings"
              }
            }
          }
        },
        "field_name": {
          "type": "string",
          "title": "field_name"
        },
        "entity_type": {
          "type": "string",
          "title": "entity_type"
        },
        "field_storage_config_type": {
          "type": "string",
          "title": "field_storage_config_type"
        },
        "settings": {
          "title": "settings"
        },
        "module": {
          "type": "string",
          "title": "module"
        },
        "locked": {
          "type": "boolean",
          "title": "locked"
        },
        "cardinality": {
          "type": "integer",
          "title": "cardinality"
        },
        "translatable": {
          "type": "boolean",
          "title": "translatable"
        },
        "indexes": {
          "type": "array",
          "items": {
            "properties": {
              "indexes": {
                "title": "indexes"
              }
            }
          }
        },
        "persist_with_no_fields": {
          "type": "boolean",
          "title": "persist_with_no_fields"
        },
        "custom_storage": {
          "type": "boolean",
          "title": "custom_storage"
        }
      },
      "description": "Entity attributes",
      "type": "object",
      "additionalProperties": false
    }
  }
}

(Note how type now appears for everything, unlike before!)

wim leers’s picture

m.stenta’s picture

I discovered this too while writing automated tests in #3257911: Add basic test coverage. I had to hard-code those same six entity types as exceptions in the tests to make them pass. If we merge this, we can remove that exception from the tests.