Support Drupal core DefaultContent API

Created on 5 June 2025, 22 days ago

Problem/Motivation

I have created a custom_field instance with the following properties:
- logo: entity reference to Media entity
- link: link field

In a recipe, I'm using the Drupal core DefaultContent API to add default content upon application of the recipe.
However, this does not work well with the custom_field I have.

When I export the node containing this field (with the contrib Default Content module), I get something like:

field_logos:
    -
      logo: 14
      link: 'https://google.com'
      link__title: ''
      link__options: { }

Obviously directly linking to media ID 14 won't work, because the recipe will be installed on a site that might have different auto-increment IDs.

I tried editing this to use the entity UUID, like other entity references exported via Default Content module:

field_logos:
    -
      logo: eab657e0-3320-41d2-ab4e-53a09b397758
      link: 'https://google.com'
      link__title: ''
      link__options: { }

This doesn't work either.

Looking deeper into the core Importer class (\Drupal\Core\DefaultContent\Importer::setFieldValues()), I notice this only works for EntityReference data types:
if ($property instanceof EntityReference) { ... }
(full namespace = Drupal\Core\Entity\Plugin\DataType\EntityReference)

I'm not familiar enough with the data model of custom_module, but I assume this uses something custom, instead of the core EntityReference data type, and thus does not set the value correctly.
Would there be any way to make this work (without hacking core I presume)?

πŸ“Œ Task
Status

Active

Version

3.1

Component

Code

Created by

πŸ‡§πŸ‡ͺBelgium svendecabooter Gent

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @svendecabooter
  • πŸ‡§πŸ‡ͺBelgium svendecabooter Gent

    Did some more digging, and it seems the datatype used in custom_field module is "CustomFieldEntityReference", which does not inherit from core "EntityReference" data type, so guess this will never work :'(

  • πŸ‡§πŸ‡ͺBelgium svendecabooter Gent

    OK it should be possible after all I think.

    Say we can integrate with the contrib Default Content module, to produce output as follows:

    field_logos:
        -
          logo:
            entity_type: 'media'
            entity: eab657e0-3320-41d2-ab4e-53a09b397758
          link: 'https://google.com'
          link__title: ''
          link__options: { }
    

    (if not possible, worst case we need to document the exported YAML files have to be manually edited).

    Then in CustomFieldEntityReference::setValue(). we can do something like:

      /**
       * {@inheritdoc}
       */
      public function setValue($value, $notify = TRUE): void {
        $entity = $value['entity'] ?? NULL;
        // START ADDED LOGIC.
        if (is_array($value)) {
          if ($value['entity_type'] && Uuid::isValid($value['entity'])) {
            $entity = \Drupal::entityTypeManager()->getStorage($value['entity_type'])->loadByProperties(['uuid' => $value['entity']]);
            $entity = !empty($entity) ? current($entity) : NULL;
          }
        }
        // END ADDED LOGIC.
        if ($entity instanceof EntityInterface) {
          ...
       }
    

    I can spend some time to look further into this, but am currently time restrained, so just doing some braindump here.
    Will try to elaborate on it next week.
    Let me know if it would be a workable solution to extend the setValue() logic, for the use case of default content exports / imports.

  • πŸ‡ΊπŸ‡ΈUnited States apmsooner

    I'm open to any improvements. If you can do the legwork to figure out what needs to happen to get this to work, I'd be happy to implement. Thanks!

  • πŸ‡§πŸ‡ͺBelgium svendecabooter Gent

    svendecabooter β†’ changed the visibility of the branch 3528586-support-drupal-core to hidden.

  • Pipeline finished with Success
    22 days ago
    Total: 325s
    #515215
  • Pipeline finished with Canceled
    22 days ago
    Total: 204s
    #515228
  • Pipeline finished with Failed
    22 days ago
    Total: 391s
    #515230
  • Pipeline finished with Success
    1 day ago
    Total: 312s
    #532255
  • πŸ‡§πŸ‡ͺBelgium svendecabooter Gent

    A patch has been added to default_content module, to make sure the Default Content exported YML files use the UUID identifiers of referenced entities within a custom_field field, rather than their (numeric) entity ID.
    The patch can be found at ✨ Add support for custom_field module Active

  • πŸ‡§πŸ‡ͺBelgium svendecabooter Gent

    Together with the patch to default_content mentioned above, this MR allows custom_field data to be exported by default_content, and imported by default_content import OR core's DefaultContent API, used by recipes.

  • πŸ‡ΊπŸ‡ΈUnited States apmsooner

    This looks pretty straight forward enough to merge however in getting back into these data types, I think its probably worth moving this new helper function to CustomFieldDataTypeBase and also the getEntity() function. I would assume for default content api, the other data types: CustomFieldImage & CustomFieldViewfield would also need the same changes and therefore can take advantage of the same methods and changes you're doing for CustomFieldEntityReference?

    @svendcabooter - poised above question in #custom-field slack channel. Just confirm if this is the case and whether you have time to make the changes or else I can today and get this merged.

Production build 0.71.5 2024