Add a Normalizer and Denormalizer to support Layout Builder

Created on 19 July 2020, over 4 years ago
Updated 19 January 2023, about 2 years ago

Problem/Motivation

Not having a Normalizer and Denormalizer to support Layout Builder

Steps to reproduce

When trying to export content as default content using any of the following commands

drush default-content:export node 1 --file=TARGET_PATH/content/node/homepage.yml
drush default-content:export node 2 --file=TARGET_PATH/content/node/blog-section.yml

Then the following fatal error shows up

Symfony\Component\Yaml\Exception\DumpException: Object support when dumping a YAML file has been disabled. in                      [error]
/var/www/html/dev/drupal80902/vendor/symfony/yaml/Inline.php:199
Stack trace:
#0 /var/www/html/dev/drupal80902/vendor/symfony/yaml/Dumper.php(97):
Symfony\Component\Yaml\Inline::dump(Object(Drupal\layout_builder\Section), 16)
#1 /var/www/html/dev/drupal80902/vendor/symfony/yaml/Dumper.php(153):
Symfony\Component\Yaml\Dumper->dump(Object(Drupal\layout_builder\Section), 9223372036854775803, 0, 16)
#2 /var/www/html/dev/drupal80902/vendor/symfony/yaml/Dumper.php(153): Symfony\Component\Yaml\Dumper->dump(Array,
9223372036854775804, 6, 16)
#3 /var/www/html/dev/drupal80902/vendor/symfony/yaml/Dumper.php(153): Symfony\Component\Yaml\Dumper->dump(Array,
9223372036854775805, 4, 16)
#4 /var/www/html/dev/drupal80902/vendor/symfony/yaml/Dumper.php(153): Symfony\Component\Yaml\Dumper->dump(Array,
9223372036854775806, 2, 16)
#5 /var/www/html/dev/drupal80902/docroot/core/lib/Drupal/Component/Serialization/YamlSymfony.php(22):
Symfony\Component\Yaml\Dumper->dump(Array, 9223372036854775807, 0, 16)
#6 /var/www/html/dev/drupal80902/docroot/core/lib/Drupal/Component/Serialization/Yaml.php(27):
Drupal\Component\Serialization\YamlSymfony::encode(Array)
#7 /var/www/html/dev/drupal80902/docroot/modules/contrib/default_content/src/Exporter.php(116):
Drupal\Component\Serialization\Yaml::encode(Array)
#8 /var/www/html/dev/drupal80902/docroot/modules/contrib/default_content/drush/default_content.drush.inc(59):
Drupal\default_content\Exporter->exportContent('node', '1', NULL)
#9 /usr/local/src/drush/includes/command.inc(422): drush_default_content_export('node', '1')
#10 /usr/local/src/drush/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#11 /usr/local/src/drush/includes/command.inc(199): drush_command('node', '1')
#12 /usr/local/src/drush/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#13 /usr/local/src/drush/includes/preflight.inc(67): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#14 /usr/local/src/drush/drush.php(12): drush_main()
#15 {main}

Next Drupal\Component\Serialization\Exception\InvalidDataTypeException: Object support when dumping a YAML file has been disabled.
in /var/www/html/dev/drupal80902/docroot/core/lib/Drupal/Component/Serialization/YamlSymfony.php:25
Stack trace:
#0 /var/www/html/dev/drupal80902/docroot/core/lib/Drupal/Component/Serialization/Yaml.php(27):
Drupal\Component\Serialization\YamlSymfony::encode(Array)
#1 /var/www/html/dev/drupal80902/docroot/modules/contrib/default_content/src/Exporter.php(116):
Drupal\Component\Serialization\Yaml::encode(Array)
#2 /var/www/html/dev/drupal80902/docroot/modules/contrib/default_content/drush/default_content.drush.inc(59):
Drupal\default_content\Exporter->exportContent('node', '1', NULL)
#3 /usr/local/src/drush/includes/command.inc(422): drush_default_content_export('node', '1')
#4 /usr/local/src/drush/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#5 /usr/local/src/drush/includes/command.inc(199): drush_command('node', '1')
#6 /usr/local/src/drush/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#7 /usr/local/src/drush/includes/preflight.inc(67): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#8 /usr/local/src/drush/drush.php(12): drush_main()
#9 {main}

Proposed resolution

Add a Normalizer and Denormalizer to support Layout Builder

Remaining tasks

  • Automated testing
  • Review
  • Release

User interface changes

  • None

API changes

  • None

Data model changes

Having a Normalizer and Denormalizer for layout builder. but not in Drupal core yet
When Drupal core has them we can switch to the core provided way. ( or could work right away without this fix )
๐Ÿ“Œ [PP-1] Expose Layout Builder data to REST and JSON:API Postponed
โœจ Export configuration YAML strings as multiline Fixed

โœจ Feature request
Status

RTBC

Version

2.0

Component

Code

Created by

๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan

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

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Merge request !15Resolve #3160146 "Add a normalizer" โ†’ (Open) created by johnzzon
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States NicholasS

    @SocialNicheGuru in reply to #57 I tested this and no I don't think it fixes Layout Paragraphs Support

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia rajeshreeputra Pune

    +1 for the RTBC.

  • Status changed to Needs work over 1 year ago
  • ๐Ÿ‡ซ๐Ÿ‡ทFrance andypost

    Can we get a basic test for that?

  • ๐Ÿ‡ซ๐Ÿ‡ทFrance Grimreaper France ๐Ÿ‡ซ๐Ÿ‡ท

    Hi,

    For information: โœจ Update inline block usage on import RTBC

  • ๐Ÿ‡ช๐Ÿ‡ธSpain eduardo morales alberti Spain, ๐Ÿ‡ช๐Ÿ‡บ
  • Current approach just avoids exception & skips "block serialized" approach, which is the default one; @see "\Drupal\layout_builder\Plugin\Block\InlineBlock::getEntity()":

    ...
    if (!empty($this->configuration['block_serialized'])) {
      $this->blockContent = unserialize($this->configuration['block_serialized']);
    }
    elseif (!empty($this->configuration['block_revision_id'])) {
      $entity = $this->entityTypeManager->getStorage('block_content')->loadRevision($this->configuration['block_revision_id']);
      $this->blockContent = $entity;
    }
    ....
    

    So any serialized block dependencies are ignored, and is the first option when new non existing content block is used in layout builder, besides that approach just works with "inline_block" plugin variants & "InlineBlock instance" can be used instead in order to get it working per base class.

    Other case where that should be managed as in layout builder you can mix entity field blocks and content blocks (content) into any display of exported content or its dependencies.

    Also some entities like section library template may use same field type to store sections but in different field name, not "layout_builder__layout" but "layout_section", to manage that again "instance of SectionData" can be used instead to detect it.

    So taking all use cases would be something like:

    1. Content blocks serialized & dependent entities (media or other)
    2. Content blocks direct usage & dependent entities (not serialized)
    3. Content blocks usage inside any display of exported entity or its dependent entities. Maybe this one is the hardest to manage

    Besides changes going in this direction should be compatible with sites without layout_builder module enabled? Maybe all should be managed into import/export subscribers.

    Working into patch/mr to manage at least first & second use cases.

  • To clarify main point, is not just about normalize / denormalize field but also include dependencies (exportContentWithReferences).

  • Open in Jenkins โ†’ Open on Drupal.org โ†’
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 5.7
    last update 11 months ago
    13 pass
  • Added changes to MR;

    1. Avoid layout_builder classes direct use to not force module dependency by missing classes on sites without layout builder enabled
    2. Manage serialized block content
    3. Use base classes to evaluate instances to avoid strict unique core lb support

    Maybe "Drupal\block_content\Plugin\Block\Drupal\block_content\Plugin\Block" should be also supported (direct block content usage from core content block library). Also other possible use cases like commented into #63 -> 3.

  • Thanks for patch #53, we have tested it in drupal 9.5. And it works correctly.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States DamienMcKenna NH, USA
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States drupalninja99

    The content looks like it exports correctly but then I get this error on import:

    In SectionData.php line 35:
    
      [InvalidArgumentException]
      Value assigned to "section" is not a valid section
    

    I think the function is here in core/modules/layout_builder/src/Plugin/DataType/SectionData.php:

    public function setValue($value, $notify = TRUE) {
        if ($value && !$value instanceof Section) {
          throw new \InvalidArgumentException(sprintf('Value assigned to "%s" is not a valid section', $this->getName()));
        }
        parent::setValue($value, $notify);
      }
    

    $value is coming in as an array not instanceof Section.

  • First commit to issue fork.
  • Pipeline finished with Success
    3 months ago
    Total: 145s
    #326054
  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine sickness29

    Added test for new normalizer, let me know if I can help more, thanks

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States agentrickard Georgia (US)

    Latest patch is working nicely on Drupal 10.3.6.. Both import and export of a Layout Builder page work as expected.

  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan

    Facing the same issue as in #68, thanks, Jay, for reporting.

  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan

    Attached a static default_content--2024-11-13--3160146--mr-15.patch static file for MR15
    to be used with Composer Patches

  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan
  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan

    The patch in #53 is working
    Latest changes over MR5 copied as a static file in #73 misses the order of first block.
    and all other blocks in the same Layout Builder get to be positioned in the wrong section or column

  • Pipeline finished with Success
    about 2 months ago
    Total: 166s
    #355750
  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan

    Attached a static default_content--2024-12-02--3160146--mr-15.patch file for MR15 from last changes to this point.
    to be used with Composer Patches

  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States pbabin

    Not sure if this is the correct place to report this. I'm also getting the Object support when dumping a YAML file has been disabled. error. I saw that another post was closed that reported this error as being a duplicate. We're using layout-paragraphs (gasp) but that hasn't been the issue as we have been successful in the past in exporting and importing this data. We are actually still using the import functionality from our last export nearly a year or two ago but need to update our default content.

    I installed the most recent patch and the error occurs at the $return = Yaml::encode($normalized) in the Exporter.php class. Since we have a lot of stuff being exported out I added the following to help me identify the issue

        function find_objects($array, $path = '') {
          foreach ($array as $key => $value) {
            $new_path = $path ? $path . '.' . $key : $key;
            if (is_object($value)) {
              echo "Found object at $new_path\n";
            } elseif (is_array($value)) {
              find_objects($value, $new_path);
            }
          }
        }
    
        find_objects($normalized);
    

    And it looks like this is erroring out for us on a meta tag breadcrumb item we have on our page. I've included a screenshot from the xdebug if this might be helpful.

    Any recommendations?

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States pbabin
  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Rajab Natshah Jordan

    Paul, it seems like youโ€™re using a custom entity type, possibly a newly custom-coded one, but it doesnโ€™t have Normalizer or Denormalizer support built in.

    I realized this after Sascha's comment in #10

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States phenaproxima Massachusetts

    phenaproxima โ†’ changed the visibility of the branch 3160146-add-a-normalizer to hidden.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States phenaproxima Massachusetts

    phenaproxima โ†’ changed the visibility of the branch 3160146-add-a-normalizer to active.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States thejimbirch Cape Cod, Massachusetts

    This is going to be important for some recipes in Drupal CMS and was referenced in โœจ The default content importer should handle Layout Builder section data Active

  • ๐Ÿ‡จ๐Ÿ‡ญSwitzerland berdir Switzerland

    Thanks for the reference. I would expect that this simplifies this issue a lot then, might be enough to normalize/export the structure into the correct format, without special import handling.

Production build 0.71.5 2024