Add a Normalizer and Denormalizer to support Layout Builder

Created on 19 July 2020, over 4 years ago
Updated 19 January 2023, almost 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

  • 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 9 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 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
    25 days 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

Production build 0.71.5 2024