Problem/Motivation

When accessing Layout Builder overrides via REST (i.e. when accessing an overridden entity's layout field), the contents of sections are empty.

Proposed resolution

Add a normalizer for the layout_section DataType, which ensures that sections can be properly serialized and unserialized via the serialization API (and REST).

Remaining tasks

N/A

User interface changes

N/A

API changes

A new normalizer will be added for the layout_section DataType.
Layout section data will be exposed for all serialization types.

Data model changes

N/A

CommentFileSizeAuthor
#286 2942975-285_on_top_of_3049332-134.patch17.2 KBmkalkbrenner
#285 core-2942975-285-core-layout-entity-normalizers.patch17.15 KBalex.skrypnyk
#284 2942975-281_on_top_of_3049332-134.patch17.8 KBmkalkbrenner
#283 2942975-281_on_top_of_3049332-134.patch17.98 KBmkalkbrenner
#282 2942975-281_on_top_of_3049332-134.patch13.19 KBmkalkbrenner
#281 json-api-layout-fix-D11.3-2942975-281.patch18.55 KBvasike
#280 json-api-layout-fix-2942975-280.patch18.89 KBkalpanajaiswal
#279 json-api-layout-fix-2942975-279.patch19.11 KBkalpanajaiswal
#277 2942975-274_on_top_of_3049332-134.patch17.57 KBmkalkbrenner
#274 2942975-274.patch17.5 KBelgandoz
#273 2942975-273.patch17.31 KBrpearl
#269 2942975-10.3.x.patch18.35 KBartsays
#264 2942975_expose_lb_data-10.3.x-264.patch13.79 KBflyke
#262 2942975-262-reroll.patch18.68 KBkevinquillen
#261 2942975-261-reroll.patch14.09 KBkevinquillen
#255 2942975-255.patch18.14 KBadwivedi008
#255 interdiff-237-255.txt6 KBadwivedi008
#253 2942975-252_revised_239.patch6.92 KBadwivedi008
#251 2942975-251.patch18.28 KBwmcmillian
#243 2942975-243.patch18.2 KBsorlov
#241 2942975-241.patch18.1 KBsorlov
#240 2942975-240.patch18.55 KBsorlov
#239 2942975-238-reroll-10.1.patch7.44 KBpatriciacb
#237 2942975-237-D10.1.patch18.16 KBmkalkbrenner
#230 2942975-230.patch18.11 KBandypost
#230 interdiff.txt891 bytesandypost
#228 2942975-228.patch18.38 KBandypost
#228 interdiff.txt1.18 KBandypost
#224 2942975-224.patch18.32 KBandypost
#224 interdiff.txt1.55 KBandypost
#223 2942975-223.patch18.31 KBandypost
#223 interdiff.txt1.64 KBandypost
#221 2942975-221.patch18.22 KBandypost
#221 interdiff.txt463 bytesandypost
#220 2942975-220.patch18.22 KBandypost
#220 interdiff.txt3.6 KBandypost
#217 2942975-217.patch21.91 KBarisen
#215 2942975-214.patch21.93 KBarisen
#213 2942975-213.patch17.48 KB_utsavsharma
#212 2942975-212.patch22.12 KB_pratik_
#211 2942975-200.patch22.09 KBdaniel.pernold
#199 2942975-199.patch23.12 KBrassoni
#198 interdiff-196-198.txt9.3 KBrassoni
#198 2942975-198.patch23.06 KBrassoni
#196 interdiff-192-196.txt6.3 KBilya.no
#196 2942975-196.patch16.6 KBilya.no
#193 interdiff-191-192.txt689 bytesjunaidpv
#193 2942975-192.patch16.6 KBjunaidpv
#191 interdiff_190-191.txt382 bytesranjith_kumar_k_u
#191 2942975-191.patch16.63 KBranjith_kumar_k_u
#190 2942975-core-3-x_190.patch16.63 KBkriboogh
#189 2942975-core-3-x_189.patch16.6 KBplach
#188 2942975-core-3-x_188.interdiff.txt1.3 KBplach
#188 2942975-core-3-x_188.patch16.67 KBplach
#185 layout_builder-rebase_drupal_9_3_x-2942975-159-array.patch16.28 KBdrupalninja99
#180 interdiff.txt703 bytesantonnavi
#180 2942975-core-3-x_180.patch16.39 KBantonnavi
#178 2942975-core-3-x_178.patch15.88 KBvacho
#166 2942975_166.patch15.23 KBmkalkbrenner
#163 2942975_163.patch15.16 KBmkalkbrenner
#159 interdiff_152-159.txt15.16 KBBalasaranyaV
#159 layout_builder-rebase_drupal_9_3_x-2942975-159.patch15.16 KBBalasaranyaV
#152 2942975-layout_builder_rest_e866ee63_reverted.patch15.14 KBmkalkbrenner
#151 2942975-layout_builder_rest_e866ee63_reverted.patch0 bytesmkalkbrenner
#145 reroll_diff_142-146.txt14.75 KBacouch
#145 2942975_145.patch55.05 KBacouch
#142 interdiff-136-142.txt304.04 KBkuhikar
#142 2942975-142-d8_d9.patch54.33 KBkuhikar
#140 2942975_140.patch55.08 KBkuhikar
#140 2942975_d8_to_d9_140.patch55.63 KBkuhikar
#139 2942975_138.patch55.09 KBkuhikar
#138 2942975_137.patch55.09 KBkuhikar
#138 Before Applying Patch.png243.58 KBkuhikar
#138 After Applying Patch.png461.84 KBkuhikar
#136 2942975-drupal_8_9_x-136.patch20.11 KBmanuel.adan
#135 interdiff-132_133.txt934 bytesOscaner
#135 2942975-133.patch25.88 KBOscaner
#132 export-layout-builder-configuration-2942975-132.patch9.94 KBmayurjadhav
#131 2942975-131.patch20 KBOscaner
#121 response-layout-builder-payload.yml4.86 KBalexmoreno
#121 json-relationships.png158.19 KBalexmoreno
#117 querying fields.png178.55 KBalexmoreno
#117 layout information after patch.png144.98 KBalexmoreno
#116 interdiff-100-116.txt2.4 KBilya.no
#116 2942975-116.patch20.11 KBilya.no
#115 layout_builder_content_sync_fixer.zip4.75 KBadam3145
#100 2942975-100.patch19.58 KBheddn
#100 interdiff_98-100.txt4.62 KBheddn
#98 2942975-98.patch15.45 KBheddn
#98 interdiff_96-98.txt2.59 KBheddn
#96 interdiff_95-96.txt1.52 KBheddn
#96 2942975-96.patch13.67 KBheddn
#95 2942975-95.patch13.69 KBheddn
#95 interdiff_94-95.txt5.82 KBheddn
#93 2942975-93.patch15.48 KBheddn
#93 interdiff_82-93.txt8.77 KBheddn
#82 interdiff.2942975.81-82.txt1.4 KBaleevas
#82 2942975-82.patch10.43 KBaleevas
#81 2942975-81.patch10.43 KBaleevas
#79 interdiff_78_79.txt622 bytesi-grou
#79 layout_builder-export-content-2942975-79.patch10.26 KBi-grou
#78 interdiff_75_78.txt949 bytesOscaner
#78 layout_builder-export-content-2942975-78.patch10.17 KBOscaner
#75 lb.patch9.57 KBarthur.islamov
#73 2942975-73.patch10.04 KBvijaycs85
#67 interdiff-59-67.txt687 bytesvaibhavjain
#67 layout_builder-export-content-2942975-67.patch10.14 KBvaibhavjain
#65 interdiff_59-65.txt514 bytesvedpareek
#65 layout_builder-export-content-2942975-65.patch4.47 KBvedpareek
#59 layout_builder-export-content-2942975-59.patch9.46 KBgeo
#59 interdiff-58-59.txt1.08 KBgeo
#59 layout_builder-export-content-2942975-59.patch9.46 KBgeo
#58 layout_builder-export-content-2942975-58.patch9.02 KBgeo
#56 layout_builder-export-content-2942975-56.patch3.36 KBgeo
#54 access_workaround-2942975-54.patch716 bytesluke_nuke
#52 2942975-52.patch7.54 KBthursday_bw
#33 2942975-33_forbid_write_access.patch1.26 KBwim leers
#33 2942975-33_forbid_all_access.patch1.08 KBwim leers
#33 layout_builder__layout field consistently normalized.png489.82 KBwim leers
#24 interdiff-2942975-21-24.txt570 bytesmpotter
#24 2942975-24.patch7.28 KBmpotter
#21 2942975-21.patch6.58 KBmpotter
#14 interdiff-2942975-10-14.txt539 bytessamuel.mortenson
#14 2942975-14.patch6.58 KBsamuel.mortenson
#10 interdiff-2942975-8-10.txt711 bytessamuel.mortenson
#10 2942975-10.patch6.59 KBsamuel.mortenson
#8 interdiff-2942975-7-8.txt689 bytessamuel.mortenson
#8 2942975-8.patch6.59 KBsamuel.mortenson
#7 interdiff-2942975-5-7.txt798 bytessamuel.mortenson
#7 2942975-7.patch6.64 KBsamuel.mortenson
#5 interdiff-2942975-3-5.txt3.85 KBsamuel.mortenson
#5 2942975-5.patch6.64 KBsamuel.mortenson
#3 2942975-3.patch3.53 KBsamuel.mortenson

Issue fork drupal-2942975

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

samuel.mortenson created an issue. See original summary.

tim.plunkett’s picture

Component: layout.module » layout_builder.module
samuel.mortenson’s picture

Status: Active » Needs work
StatusFileSize
new3.53 KB

Here's a start to this, still need to add tests and think about validation.

I opted to write two normalizers - one for the layout_section DataType and another for the field item. This made sense to me as it allows for new kinds of layout field, but we could put everything in the field item normalizer if that seem simpler. I tested GET/PATCH and it seems to work, so feel free to test things out and find bugs as I (or others) write test coverage.

wim leers’s picture

Issue tags: +API-First Initiative

Great start :)

  1. Thanks for having a @DataType-level normalizer! This is in line with #2926507: Discourage @FieldType-level normalizers, encourage @DataType-level normalizers, to strengthen the API-First ecosystem! It also means this will work with JSON API :)
  2. +++ b/core/modules/layout_builder/layout_builder.services.yml
    @@ -39,3 +39,11 @@ services:
    +      - { name: normalizer, priority: 1 }
    ...
    +      - { name: normalizer, priority: 9 }
    

    Why these priorities? We've been insisting that normalizers always have a comment explaining the rationale behind their priorities.

    (This is a huge weakness in the Symfony DIC — priorities should not be numerical; one should have to define before/after dependencies. Numerical priorities don't work in projects that can be extended by simply installing modules.)

  3. +++ b/core/modules/layout_builder/src/Normalizer/LayoutSectionItemNormalizer.php
    @@ -0,0 +1,28 @@
    +class LayoutSectionItemNormalizer extends FieldItemNormalizer {
    ...
    +  protected $supportedInterfaceOrClass = LayoutSectionItem::class;
    

    Ideally we wouldn't have @FieldType-level normalizers.

    But it's indeed necessary for denormalization.

    Can you please make this service private and internal? So we can remove it when #2957385: FieldItemNormalizer never calls @DataType-level normalizer service' ::denormalize() method lands.

  4. +++ b/core/modules/layout_builder/src/Normalizer/SectionDataNormalizer.php
    @@ -0,0 +1,45 @@
    +    return $object->getValue()->toArray();
    

    I'm a bit scared by how freeform this seems to be. If it's so freeform, how will https://www.drupal.org/project/openapi then be able to generate documentation for this?

  5. In general: please look at #2926508: Add DateTimeNormalizer+TimestampNormalizer, deprecate TimestampItemNormalizer: @DataType-level normalizers are reusable by JSON:API for guidance/inspiration!
  6. It'd be great to also manually test this in JSON API (I realize you can't add test coverage for it since JSON API is not in core).
samuel.mortenson’s picture

Status: Needs work » Needs review
StatusFileSize
new6.64 KB
new3.85 KB

Addressed all points in #4 (including new unit test coverage 🏄‍♂️) except the validation and schema feedback. May need @tim.plunkett to chime in here for direction.

samuel.mortenson’s picture

Status: Needs work » Needs review
StatusFileSize
new6.64 KB
new798 bytes

Fixed coding standards on the new test.

samuel.mortenson’s picture

StatusFileSize
new6.59 KB
new689 bytes

And updated a test method to actually test ::supportsDenormalization

samuel.mortenson’s picture

StatusFileSize
new6.59 KB
new711 bytes

Missed one.

tim.plunkett’s picture

+++ b/core/modules/layout_builder/src/Normalizer/SectionDataNormalizer.php
--- /dev/null
+++ b/core/modules/layout_builder/tests/src/Unit/SectionDataNormalizerTest.php

+++ b/core/modules/layout_builder/tests/src/Unit/SectionDataNormalizerTest.php
@@ -0,0 +1,86 @@
+namespace Drupal\Tests\layout_builder\Unit\Normalizer;

namespace mismatch; delete the \Normalizer part or move the file in and things should pass.

samuel.mortenson’s picture

Status: Needs work » Needs review
StatusFileSize
new6.58 KB
new539 bytes

Fixed the namespace issue, thanks @tim.plunkett!

wim leers’s picture

Great work!

  1. +++ b/core/modules/layout_builder/src/Normalizer/LayoutSectionItemNormalizer.php
    @@ -0,0 +1,32 @@
    + * @todo Remove in https://www.drupal.org/node/issues/2957385
    

    ❤️

  2. +++ b/core/modules/layout_builder/src/Normalizer/SectionDataNormalizer.php
    @@ -0,0 +1,45 @@
    +  protected $supportedInterfaceOrClass = SectionData::class;
    ...
    +    /** @var \Drupal\Core\Field\FieldItemInterface $field_item */
    

    This is tying the denormalization of a @DataType to its containing field. That shouldn't be necessary. All this should be doing is creating the value necessary to be set on the main property of a @FieldType=layout_section.

    Then LayoutSectionItemNormalizer::denormalize() can take that return value and set it on the @FieldType=layout_section target instance.

    Is this confusing, messy, and poorly delineated? Yes. That's what #2926507: Discourage @FieldType-level normalizers, encourage @DataType-level normalizers, to strengthen the API-First ecosystem aims to fix/standardize, but until then we need to be vigilant, to not introduce even more of these.

  3. +++ b/core/modules/layout_builder/tests/src/Unit/SectionDataNormalizerTest.php
    @@ -0,0 +1,86 @@
    +class SectionDataNormalizerTest extends UnitTestCase {
    

    🤘

borisson_’s picture

Status: Needs review » Needs work

Based on #15, we need to fix .2 of that review.

samuel.mortenson’s picture

We discussed this in a private chat already, but I don't like the idea of having a typed data normalizer that normalizes \Drupal\layout_builder\Plugin\DataType\SectionData, but does not return an instance of SectionData when denormalized. Normalizers are meant to accept their ::supportedInterfaceOrClass in normalize, and return an object of that class in denormalize based on the $class argument. Changing this behavior defeats the purpose of normalization for me, even if core is already doing this.

Maybe a middle ground would be to not have a typed data normalizer for SectionData, and instead write one for Drupal\layout_builder\Section, which is the value it accepts. Then the field normalizer could use this to set a value on its typed data object.

wim leers’s picture

I'm not sure I agree with #2914503: Determine if serializing blobs is safe for use in Layout Builder's outcome — if that had had a different outcome, then this issue may not have needed to exist.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mpotter’s picture

Adding this as a stable blocker as sites need a way to export landing page content for deployment to other environments. This was possible with Lightning Landing Pages with Panelizer and is needed for nodes using Layout Builder with modules such as Default Content. Default Content exports are empty without this serializing patch.

mpotter’s picture

StatusFileSize
new6.58 KB

Here is a reroll of #14 against the latest 8.6

mpotter’s picture

Status: Needs work » Needs review
mpotter’s picture

Status: Needs review » Needs work

Not sure if this is working for REST, but it's not working for default_content. This patch allows me to export a node with layout_builder and I see the proper json data in the export. However when I try to import the node json, I get:

In SqlContentEntityStorage.php line 783:

Value assigned to "section" is not a valid section

In SectionData.php line 31:

Value assigned to "section" is not a valid section

When debugging this, it's trying to assign an array to the "section" property rather than a Section object class. Doesn't seem like the denormalizer is being called in LayoutSectionItemNormalizer::denormalize. But maybe it hasn't gotten to that point yet since the debug stack shows it is trying to get the property value in order to determine if it's empty first.

Seems maybe related to this: https://www.drupal.org/project/jsonapi/issues/2955615 in JSONApi, but not fixed in core itself.

Edited: Looks like this is what @samuel.mortenson was saying in #17, so sorry for the dup.

mpotter’s picture

StatusFileSize
new7.28 KB
new570 bytes

Here is a tweak to the patch. This doesn't feel right at all, but it got me past the errors in default_content when importing the section json. default_content import is never calling anything in the SectionDataNormalizer so not sure if that's an issue with default_content or with the normalizer. Given that Sam mentioned he tested the previous patch with JSON get/patch it makes me think either default_content has a problem with json importing typed-data or that there is another core issue buried somewhere.

In any case, posting this patch so a client can try it and to get more comments.

wim leers’s picture

#24: Yeah, it definitely doesn't seem right that LayoutSectionItemNormalizer::denormalize() is duplicating logic from SectionDataNormalizer::denormalize(). That almost must mean that default_content does something funky, like only denormalizing field-level data and not field property-level data.


Re-scanning this issue, I see that in #18 I linked to #2914503: Determine if serializing blobs is safe for use in Layout Builder. That reminds me of #2895532: @DataType=map cannot be normalized, affects @FieldType=link, @FieldType=map.

huzooka’s picture

Status: Needs work » Needs review
jibran’s picture

  1. +++ b/core/modules/layout_builder/src/Normalizer/LayoutSectionItemNormalizer.php
    @@ -0,0 +1,32 @@
    +    $section_data = $this->serializer->denormalize($data['section'], SectionData::class, $format, $context);;
    +    return parent::denormalize($section_data->getValue(), $class, $format, $context);
    

    Let's add some docs here.

  2. +++ b/core/modules/layout_builder/src/Plugin/DataType/SectionData.php
    @@ -27,6 +27,9 @@ class SectionData extends TypedData {
    +    if ($value && is_array($value)) {
    +      $value = Section::fromArray($value);
    +    }
    

    We should add dedicated test(maybe KTB) for this.

gun_dose’s picture

I applied patch from #24 to Drupal 8.6.4 and it works fine for me. I exported node with layout to default content and imported it back and all works fine.

jidrone’s picture

The #24 also worked for me.

wim leers’s picture

This just came up in the JSON:API issue queue: #3022575: [upstream] Support for layout 😀

tallytarik’s picture

#24 also worked for me, Drupal 8.6.5.

jurgenhaas’s picture

Tried #24 in 8.6.7 and it works as expected.

wim leers’s picture

Sorry for the long silence on my side 😔 A proper deep dive below!

👍 Normalization:

First, and most importantly: applying this patch makes it show up in the json and hal_json formats fore core's REST module, as well as for the contrib JSON:API module (soon to be in core: #2843147: Add JSON:API to core as a stable module). All information is available, and consistently so.

API

🙏 Normalization test coverage

This patch contains unit test coverage (👏), but not functional test coverage. Experience has taught me that for anything REST API-related, we want functional test coverage. Because there are so many subsystems being integrated (Entity API, Field API, Typed Data API, Routing API, Access API, Serialization API …), a functional test is a way to prove that it all actually works in actual requests.

#2942976: Add REST test coverage for Layout Builder already exists for this, but I think it should be merged with this. We already have examples of REST tests for specific field types: \Drupal\Tests\datetime\Functional\EntityResource\EntityTest\EntityTestDateonlyTest, \Drupal\Tests\entity_test\Functional\Rest\EntityTestTextItemNormalizerTest, and more.

🤔 Schema: documentation describing how to interpret the stored value

Second most important: being able to make sense of this data: what is its schema, what is the meaning of the structure, and each particular value?

Without this, it's going to be impossible difficult for decoupled applications to allow a content creator to customize each individual entity and have the client respect this custom layout.

Now, to be fair, Drupal 8.0.0 shipped without schema support for its REST API. I don't think we should hold Layout Builder to a higher standard. So I'm not arguing for complete/comprehensive API docs. I'm saying that for this field to be actually consumable/interpretable, given the complexity of a value for this field/data type is significantly higher than other core fields, it's necessary for it to be at least clearly documented. https://www.drupal.org/docs/8/core/modules/layout-builder does not yet exist.

#2919811: Write Layout Builder handbook documentation already exists for this.

😨 Validation

It seems that validation is currently limited to:

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

@mpotter encountered this in #23 when trying to use Layout Builder + https://www.drupal.org/project/default_content. Which is why he added the tweak/hack/work-around in #24.

This isn't "real" validation though: it's only verifying that it receives data of a certain type, it doesn't yet verify the values of that data.

I've searched through the code base, and as far as I can tell, validation is absent! 😨 To be more precise: there is no active need for validation logic, because the UI is structured in such a way that only trusted logic ever generates values to be stored. \Drupal\layout_builder\SectionListInterface + \Drupal\layout_builder\Section + \Drupal\layout_builder\SectionComponent fit together, forming a data structure that is more restricted than just an array, the UI/form logic interacts with methods on these, and hence there hasn't been a need for validation logic (at least not yet).

However, when a decoupled client wishes to modify the layout for an entity, it of course does not have access to these nice PHP interfaces — all it has is plain JSON. There is no validation constraint on either @FieldType=layout_section or @DataType=layout_section. Which means that I can set arbitrary data. This has at least two dangerous consequences:

  1. I can break the site (or at least the viewing of a particular entity, and probably the editing of said entity too) by sending garbage data — AFAICT any array will be accepted.
  2. I can disclose sensitive information, by for example placing a "View" block with sensitive information without further access control, whose access is intended to be protected through block visibility rules. Since there are no restrictions on which blocks I can place.

😨 Access

AFAICT currently anybody who can edit the entity, can also edit Layout Builder's field.

Considering the risks wrt validation, a viable strategy could be that only trusted users can modify Layout Builder's field. There is a configure any layout permission, but it's only applied to routes (with the _has_layout_section route requirement).

@FieldType=layout_section could be protected by this permission as well. Created #3028301: Do not expose to Layout Builder's sections either in defaults or overrides to REST and other external APIs for this.

🙏 Normalization implementation: complicated by the desire to support writes

The only reason that LayoutSectionItemNormalizer exists (at least until #2957385: FieldItemNormalizer never calls @DataType-level normalizer service' ::denormalize() method lands), and also the only reason that \Drupal\layout_builder\Plugin\DataType\SectionData needs to be modified, is to support writes. The patch would become much simpler if we chose to not support writing, for now. Most of the value is in reading it anyway!

Conclusion

I see the following paths forward:

  1. The patch works well in that it exposes the data. But I worry that client developers will not know how to interpret this data.
    1. We could solve this altogether by simply not yet exposing this field via an API — that's totally legitimate! Once we make this available via APIs, we have to support it forever. Are we confident enough to commit to that? Marking this field type internal for now (see https://www.drupal.org/node/2916592) inaccessible (even better!) would instantly solve this issue.
      See 2942975-33_forbid_all_access.patch.
    2. If we don't want to do that, we have to document it and add explicit test coverage for at least one of every possible type of thing (field, block, view …) that can be placed using Layout Builder, to ensure we don't unknowingly change the schema. This is doable.
  2. My biggest fear is letting API clients writing layout information. AFAICT validation is absent. Which is fine for the coupled UI because it naturally limits what data can be saved, but not for a decoupled UI. I've explained why this can easily lead to broken sites at minimum, and information disclosure at worst.
    1. I think we should remove the ability to set this field via the API, at least for now.
      See 2942975-33_forbid_write_access.patch.
    2. If that's not an option, then I think we should at least restrict access.
      See #3028301: Do not expose to Layout Builder's sections either in defaults or overrides to REST and other external APIs.
tedbow’s picture

@Wim Leers thanks for the detailed review!

I can disclose sensitive information, by for example placing a "View" block with sensitive information without further access control, whose access is intended to be protected through block visibility rules. Since there are no restrictions on which blocks I can place.

I think this is similar to the block UI in that if you give the user administer blocks permission that can place any block. True the user could set a visibility rule for user role but they don't have to. So you are essentially giving them permission to place any block and have render whatever it will render.

At least in the layout case, for now, configure any layout, is a restricted permission.

So for a Layout user they can place any block regardless of whether they are doing so via the UI or through a REST call.

AFAICT currently anybody who can edit the entity, can also edit Layout Builder's field.

Yes this is true for except for the access control on the routes. With the route access control only users with configure any layout permission can edit layouts. They don't actually need access to update the entity(or view right now 😫#3028490: Users with "configure any layout" can see entities they don't have "view" access to)

The patch would become much simpler if we chose to not support writing, for now. Most of the value is in reading it anyway!

I 2nd this. I think a read-only solution now would be very useful.

Once we make this available via APIs, we have to support it forever. Are we confident enough to commit to that?

I would probably defer to @tim.plunkett on this. I guess 1 reason to not expose the field at all right now is I think we would be much more sure after 6 months or 1 year of Layout Builder being stable.

I think that if for some reason we need to change the way the field is stored we could do that without any BC implications if the field is not exposed via our APIs. Because the no module should ever deserializing the Layout reading the data.

If we expose the field over the API it would be effectively just that same as saying we support modules getting the json string decoding it and figuring out the layout from there. Because this is effectively be what a decoupled application would be doing.

And once we expose we can never change that structure. Though in theory we could write a BC layer to with normalizer to keep the format the same for sites that want it the same. But considering how much discussion there was around #2751325: All serialized values are strings, should be integers/booleans when appropriate and #2768651: Let TimestampItem (de)normalize to/from RFC3339 timestamps, not UNIX timestamps, for better DX I think that is something we want to avoid at all costs if we can.

So that would lead me to endorse:

We could solve this altogether by simply not yet exposing this field via an API — that's totally legitimate! Once we make this available via APIs, we have to support it forever.

If we can't do that I think we should only allow read access for now.

tedbow’s picture

I have repurposed the existing issue which was Add default field-level access restriction to Layout Builder's field type to #3028301: Do not expose to Layout Builder's sections either in defaults or overrides to REST and other external APIs

basically the idea is do this in 3 stages

  1. No field API access
  2. Read access
  3. Write access

but we could discuss on that issue and leave this 1 for when we actually want to implement the normalizer(if we don't want to do it now)

tim.plunkett’s picture

Moving tag to other issue

wim leers’s picture

Title: Add a DataType normalizer for layout_section » [PP-1] Add a DataType normalizer for layout_section
Status: Needs review » Postponed
Related issues: +#3028490: Users with "configure any layout" can see entities they don't have "view" access to

#34:

I think this is similar to the block UI in that if you give the user administer blocks permission that can place any block.

If that were the case, I wouldn't be worried. But today, there's no access control on the layout field at all: if the entity can be edited, then the layout can be edited. Which you acknowledged further in your comment.

Thanks for linking #3028490: Users with "configure any layout" can see entities they don't have "view" access to — I hadn't found that yet. Following.

Marking this issue postponed on #3028301: Do not expose to Layout Builder's sections either in defaults or overrides to REST and other external APIs.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

xjm’s picture

Category: Feature request » Task
Priority: Normal » Major
xjm’s picture

Title: [PP-1] Add a DataType normalizer for layout_section » Expose Layout Builder data to REST and JSON:API
Status: Postponed » Active
Related issues: +#3040354: Introduce entity type annotation key for indicating that an entity type is *safe* for HTTP API usage

Turns out we had to introduce a hack in JSON:API itself to avoid exposing LB data over JSON:API. Adding #3040354: Introduce entity type annotation key for indicating that an entity type is *safe* for HTTP API usage as a related issue.

Since our existing normalizer for REST didn't apply to JSON:API, retitling to make it clear that fixing both should be in scope.

andypost’s picture

The only issue I recall is inline blocks which has no ui and not enough data exposed

mrweiner’s picture

Just curious whether any progress has been made here. Since both JSON:API and Layout Builder are stable in core I think people will expect them to play nicely together.

mpotter’s picture

Also wondering what the current workaround for this is. The original patch in #24 was to provide a Json Normalizer for SectionData so the default_content module could export landing page nodes to be deployed across sites.

In the past, landing pages could be designed using Panels and Page Manager and exported to config and deployed across site environments. With Layout Builder, landing pages are Node content and the main way our clients deployed this content was via the default_content module. Now with 8.7 this has all broken and clients no longer have a way to deploy configured landing pages between environments (such as a search results page with facet blocks and other blocks placed on the page).

Is there any other way to restore a Json Normalizer that default_content can use to export a Node with Layout SectionData as JSON without exposing it to the world via Json:api?

andypost’s picture

@mpotter for a while this normalizers could be added to https://www.drupal.org/project/better_normalizers

larowlan’s picture

Added duplicate issue from Default Content to related issues

sharique’s picture

I'm using 8.7.1, patch #33 doesn't work for me.
And patch #24 give following error.
Error: Maximum function nesting level of '256' reached, aborting! in Drupal::getContainer() (line 128 of /var/www/centara/docroot/core/lib/Drupal.php) #0 /var/www/centara/docroot/core/lib/Drupal.php(283): Drupal::getContainer() #1 ......

Both patches work for me neither in JSON API nor default content export.

mrweiner’s picture

@Sharique I haven't actually tested the patches yet myself, but the error you've noted is unrelated. See https://stackoverflow.com/questions/4293775/increasing-nesting-function-...

gun_dose’s picture

Is there any progress? At 8.7 version all patches are not working.

thursday_bw’s picture

Like gundose stated.

The patches on this page don't work with 8.7.

I have applied the patch in #24 cleanly, however there is no layout in the exported landing page.

thursday_bw’s picture

If i'm understanding all this correctly,
layouts aren't exposed to REST and other API's in drupal 8.7.* due to https://www.drupal.org/project/drupal/issues/3028301 which in turn means, default_content_deploy doesn't export it either. Even with the patches on the issue this comment refers to being applied.

Can anyone thing of a work around, even if temporally?

thursday_bw’s picture

StatusFileSize
new7.54 KB

OK.. Work around.

I'm uploading this patch but I do not recommend that it be accepted into core.
It's just here for you to apply to D8.7 if you so choose as a work around.

If you apply patch 2942975-24.patch
along with 2942975-52.patch

You will be able to export the layout using
default content deploy

Due to https://www.drupal.org/project/drupal/issues/3028301 restricting exposure of layouts, I don't know yet what a correct solution to this
would be.

andypost’s picture

I think better to add normalizer to https://www.drupal.org/project/better_normalizers and create separate release for 8.7

luke_nuke’s picture

StatusFileSize
new716 bytes

This issue blocks layouts from being exportable by any module attempting that (default_content, content_sync among others). As most people from issue queues of these modules will end up here, I decided to write up the possible solution here.

If you really want to have this working on 8.7.x (and possibly 8.8.x), you would have to apply the attached patch. It's just workaround though, because it has some security implications mentioned by Wim Leers . But that's not enough, you also would have to write custom normalizers for Layout elements. It is what was attempted by #24 . There are more issues if you want to use this exporting capability to later import these nodes with layouts. For example exported references to revision ids of inline block contents in layouts configurations won't match with the real ones, so there is more logic required to get proper references on import. I managed to make it work for my use case, and assuming the attached patch has been applied - it can be done by contrib module.

thursday_bw’s picture

Luke Nuke, there is a work around for exporting layouts that works now, without any patch by taking advantage of layout builder library module. https://www.drupal.org/project/layout_library

With this you can create a layout in the library, and then instead of adding a layout override on a node, you tell that node to use the layout from the library.. and then it all exports nicely.

geo’s picture

Reworked patches from #52 for D8.7.5
As mentioned in #52 It is a temporary solution. I've created it for using it along with default content export.

wim leers’s picture

I've created it for using it along with default content export.

Just be aware that by doing this, you're on your own. Layout Builder does not guarantee that those storage details will remain the same. So if they change, your default content exports will stop working.

geo’s picture

StatusFileSize
new9.02 KB

Updated my previous patch #56 (I've missed several files).
The patch for D8.7.5 and use it on your own risk.

geo’s picture

StatusFileSize
new9.46 KB
new1.08 KB
new9.46 KB

One more patch for D8.7.5 - still use it on your own risk.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

vijaycs85’s picture

Status: Active » Needs review

Manually tested the patch (8.7.x HEAD) with default_content module and the exported node has the layout configuration and node-level override details (as below).

"layout_builder__layout": [
        {
            "section": {
                "layout_id": "layout_onecol",
                "layout_settings": [],
                "components": {
                    "b9d1b078-51c2-4918-a69b-5a4b58e3a947": {
                        "uuid": "b9d1b078-51c2-4918-a69b-5a4b58e3a947",
                        "region": "content",
                        "configuration": {
                            "id": "block_content:18853fa3-6af3-44a2-a14e-799af4e46910",
                            "label": "Working block",
                            "provider": "block_content",
                            "label_display": 0,
                            "status": true,
                            "info": "",
                            "view_mode": "full",
                            "context_mapping": []
                        },
                        "additional": [],
                        "weight": 1
                    }
                },
                "third_party_settings": []
            }
        }
]
lpc’s picture

Tested patch manually on Umami (8.7.8) and multilingual website I am working on (8.7.7). I can confirm that Default content exports layout builder configuration.

"layout_builder__layout": [
        {
            "section": {
                "layout_id": "layout_onecol",
                "layout_settings": [],
		"components": {
                    "7ac803f4-47bf-45c6-bfda-cd53baa6bf06": {
                        "uuid": "7ac803f4-47bf-45c6-bfda-cd53baa6bf06",
                        "region": "content",
                        "configuration": {
                            "label_display": "0",
                            "context_mapping": {
                                "entity": "layout_builder.entity"
                            },
                            "id": "extra_field_block:node:page_laybout_builder:>
                        },
                        "additional": [],
                        "weight": 0
                    },
                    "a2e569b1-224c-4e3a-9569-03d0db59f2f0": {
                        "uuid": "a2e569b1-224c-4e3a-9569-03d0db59f2f0",
                        "region": "content",
                        "configuration": {
                            "label_display": "0",
                            "context_mapping": {
                                "entity": "layout_builder.entity"
                            },
                            "id": "field_block:node:page_laybout_builder:body",
                            "formatter": {
                                "label": "hidden",
                                "type": "text_default",
                                "settings": [],
                                "third_party_settings": []
                            }
                        },                                   
                    "16c0a1b9-9fb5-4b5d-9f71-bc30c84d65bd": {                   
                        "uuid": "16c0a1b9-9fb5-4b5d-9f71-bc30c84d65bd",         
                        "region": "content",                                    
                        "configuration": {                                      
                            "id": "inline_block:basic",                         
                            "label": "reger",                                   
                            "provider": "layout_builder",                       
                            "label_display": "visible",                         
                            "view_mode": "full",                                
                            "block_revision_id": "7",                           
                            "block_serialized": null,                           
                            "context_mapping": []                               
                        },                                                      
                        "additional": [],                                       
                        "weight": 2                                             
                    }                                                           
                },                                                              
                "third_party_settings": []                                      
            }                                                                   
        }                                                                       
    ]   
vaibhavjain’s picture

The patch at #59 works well. I checked with JSON API output, and I am able to see the components there.
However I have a case, where I am not able to fetch the component content.

  1. Added a new node, with layout builder enabled per node.
  2. Added a new block type, text block.
  3. Added a new block content of type, text block.
  4. From Node, layout manager, add a new block of type text block and add a block that already exists.
  5. In the JSON API output, we cannot access content of Block, added via layout builder.

Question 1 - If we are exposing components, inside the layout, how do we plan to get content of each component ? There are no self or related links, to help you fetch the content and meta data of the component.
Question 2 - If all of the above is true, are we saying that, we can only access content of the block, which are not create via Layout Builder ?

I also see that JSONAPI, wont allow you to access the content of a block which is not reusable. A non Reusable block is created, when you add a block via Layout builder. However, this is also being worked upon here 2999491

Output of my JSON API

{
  "fda2e964-4a5e-4203-81ff-09954d1fb919": {
    "uuid": "fda2e964-4a5e-4203-81ff-09954d1fb919",
    "region": "first",
    "configuration": {
      "id": "inline_block:text_block",
      "label": "Non Reusable Block",
      "provider": "layout_builder",
      "label_display": "visible",
      "view_mode": "full",
      "block_revision_id": "2",
      "block_serialized": null,
      "context_mapping": []
    },
    "additional": [],
    "weight": 0
  },
  "f21a9758-3abe-4c96-8c60-53496fd31e42": {
    "uuid": "f21a9758-3abe-4c96-8c60-53496fd31e42",
    "region": "second",
    "configuration": {
      "id": "block_content:6255d80f-07e4-455e-bd47-f7a37fa9cee0",
      "label": "Reusable Block",
      "provider": "block_content",
      "label_display": "visible",
      "status": true,
      "info": "",
      "view_mode": "full",
      "context_mapping": []
    },
    "additional": [],
    "weight": 0
  }
}
vedpareek’s picture

Status: Needs work » Needs review
StatusFileSize
new4.47 KB
new514 bytes

Hi @Vaibhav I was facing the same issue, I have been able to send block bundle and block uuid in json output. This patch has been tested against 8.9.x branch.
Attaching the patch for the same
Thanks

vaibhavjain’s picture

Status: Needs work » Needs review
StatusFileSize
new10.14 KB
new687 bytes

As the patch in #65 is incorrect, uploading the correct patch, with interdiff.

zkent’s picture

Hello,

Our website uses a fair number of custom landing pages built using the landing page content type and modified using the layout builder. What is the status of a patch for this issue?

Zach

lpc’s picture

Issue summary: View changes

What is the status of a patch for this issue?

Patch #59 works well.

aldibier’s picture

Patch #67 works like a charm! tested in Drupal 8.8.1

lpmthong.dev’s picture

I used #67, now can see the layout_builder__layout but how can I use jsonapi to PATCH the node to change the layout? Always get errors when tried to PATCH.

vijaycs85’s picture

Status: Needs work » Needs review
StatusFileSize
new10.04 KB

Re-rolling against 8.9.x (and works for 8.8.x as well).

arthur.islamov’s picture

StatusFileSize
new9.57 KB
vijaycs85’s picture

@arthur.islamov could you provide interdiff?

morbus iff’s picture

Confirming #72 is still an issue with #75: When attempting to PATCH a layout_builder__layout field, I receive: "The current user is not allowed to PATCH the selected field (layout_builder__layout)." I receive the same error with POST, meaning I can't create a custom layout in a node (i.e., I can't create custom landing pages from JSON:API). That's my sole need - is this patch only for EXPOSING the data, or also for creating/updating that data?

Oscaner’s picture

StatusFileSize
new10.17 KB
new949 bytes
i-grou’s picture

Tried patch #78 and it works fine for export, but somehow $section_data->getValue() (in LayoutSectionItemNormalizer->denormalize()) produces an error when importing node with individual layout (using content_sync module):

Error: Call to undefined method Drupal\layout_builder\Section::getValue() in Drupal\layout_builder\Normalizer\LayoutSectionItemNormalizer->denormalize() (line 30 of /var/www/rtc.ccuptest.co.uk/web/core/modules/layout_builder/src/Normalizer/LayoutSectionItemNormalizer.php).

So to workaround it I've added a check if method exists, if not - then using $data['section'] instead works fine.
Maybe it's better to debug SectionData class, but I got no luck with this (in 15 min), maybe someone else can handle it. Or maybe it's related ot my drupal version - 8.8.4. Meanwhile we can go ahead with this patch.

i-grou’s picture

I've ran some more tests and it turned out that patch above not working as expected. Hope it would be fixed in the next release.

aleevas’s picture

StatusFileSize
new10.43 KB

The latest patch was rerolled

aleevas’s picture

Status: Needs work » Needs review
StatusFileSize
new10.43 KB
new1.4 KB

Fixed for latest patch

jonathanjain’s picture

I have applied #82 patch

adam3145’s picture

I just tested this on Drupal 8.8, with layout builder and it's working well with content sync to export my inline blocks!
Anything I can do to help get this commited?

tbsiqueira’s picture

Currently tested for drupal 8.5 works like a charm! Thank you!

EDIT: Thank you for the reply @adam3145 I was using the wrong patch version, I used version 73 and it worked.

adam3145’s picture

I am on 8.8.2, I just put the file in the /web folder of my site, and ran the patch -p1

carlosrfm’s picture

Successfully applied patch #82.

Does anyone else is getting this a duplicate "section" tag? This is generating an error whenever I try to import.

"layout_builder__layout": [
        {
            "section": {
                "section": {
                    "layout_id": "layout_onecol",
                    "layout_settings": {

Thanks!

adam3145’s picture

I am not, do you have multiple sections on your export, as currently I only have 1 on all my pages.

carlosrfm’s picture

No, just a single section containing 2 blocks (body and a form).

adam3145’s picture

Actually yes I do have duplicate sections, however I don't seem to be getting an error when trying to import.

Are you using content sync?

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

heddn’s picture

StatusFileSize
new8.77 KB
new15.48 KB

This hopefully fixes some things.

heddn’s picture

Status: Needs work » Needs review
heddn’s picture

StatusFileSize
new5.82 KB
new13.69 KB

removes a level of un-needed nesting and general cleanup.

heddn’s picture

StatusFileSize
new13.67 KB
new1.52 KB
heddn’s picture

Status: Needs work » Needs review
StatusFileSize
new2.59 KB
new15.45 KB

Hopefully a few more things fixed. The remaining failures I think are more complicated then what time I have to give right now. I did some manual testing and remaining failing tests didn't fail manually (for me).

heddn’s picture

Status: Needs work » Needs review
StatusFileSize
new4.62 KB
new19.58 KB

We have to remove the uuids as the keys for components since it causes XML serialization to fail. It isn't really needed any way, so I don't think that is an issue. See interdiff for how that looks in umami.

Marko B’s picture

Issue summary: View changes
Marko B’s picture

Issue summary: View changes

As #64 wrote there are important questions this patch doesn't address. Layout builder will and should be used mostly for one time blocks and custom landing pages. So far we get config of the layout but content is non fetchable.

adam3145’s picture

I don’t know what you mean content not exposed. I am using this with the content sync module and all of my inline blocks content are exporting and working perfectly

heddn’s picture

I opened #3151275: referencedEntities should return referenced layout builder added entities earlier to day that might be moderately related.

Marko B’s picture

@adam3145 sorry I didn't make it clear enough. So currently only "reusable" blocks can be fetched with JSON:API, those that dont have that option enabled have access restriction. There is this message "The current user is not allowed to GET the selected resource. Non-reusable blocks must set an access dependency for access control." that comes from getAccessCheckedResourceObject which gets access info from
web/core/modules/block_content/src/BlockContentAccessControlHandler.php and checkAccess which has this

    if ($entity->isReusable() === FALSE) {
      if (!$entity instanceof DependentAccessInterface) {
        throw new \LogicException("Non-reusable block entities must implement \Drupal\block_content\Access\DependentAccessInterface for access control.");
      }

meaning you won't be able to fetch with JSON API non-reusable blocks with current access checker in getAccessCheckedResourceObject.

Marko B’s picture

Other problem we have is that JSON:API output is not really DX friendly, simplest example would be that we get this export for simple custom block

                "uuid": "365dd4c2-41ad-469a-94b3-dc426e8587d0",
                "region": "content",
                "configuration": {
                  "id": "inline_block:hero_block",

which you then need to substring to get proper endpoint which would be jsonapi/block_content/hero_block/365dd4c2-41ad-469a-94b3-dc426e8587d0. This looks more like hardcoding stuff then dynamically getting proper endpoints.

And this is simple example. I have much more complex, like having ID from commerce block

         "uuid": "60bf2ad0-4fcc-4633-ba40-80b1a6829979",
                "region": "second",
                "configuration": {
                  "id": "field_block:commerce_product:toys:variations",

How to get proper url for this one :) is it even obtainable in current setup. There is some UUID but which endpoint to use here, JSON output doesnt help much?

tim.plunkett’s picture

Issue summary: View changes
Issue tags: +Needs issue summary update

#70 removed the issue summary, not sure why.
Restoring what it was, but I think it needs an update anyway.

geek-merlin’s picture

#106: This means there will never be access for those one-shot blocks on their own.
I suppose Includes come to the rescue, and maybe #105.

adam3145’s picture

That’s interesting. I am using content sync and my non reusable inline blocks are exporting perfectly. I think I am using patch from 82 or so.

Marko B’s picture

I am using patch #78 as this is last one that works with 8.8.6 but I don't see this worked on on later patches and mentioned in comments and interfdiffs. If someone can verify this has been worked on later and where, would gladly check it.

Marko B’s picture

Also if you are using revisions for your LB and blocks also have revisions you will probably have problems with jsonapi and UUIDs. Seems to me this is the problem https://www.drupal.org/project/drupal/issues/3043321 which leads to this
https://www.drupal.org/project/drupal/issues/3031271

For me block uuids in LB json object dont match what I can fetch, when exposing them they return nothing, but I can manually find proper versions that JA can expose.

adam3145’s picture

I have made a module that automatically fixes the UUID's for the purposes of content sync with exposed inline blocks. I can share it here if that's helpfull, it is a stand alone module that I was going to post while this is fixed up in core...

heddn’s picture

I ran into an issue recently when exporting the layout builder data on a node that the inline blocks are linked via bid/vid. I can't just use their UUID and it relinks them when re-importing the content. That seems related to #112/113, is that true?

adam3145’s picture

StatusFileSize
new4.75 KB

So I have a module that i did to fix that, It's attached. You just import normally then run this drush command to clean it up. "drush content-sync-fixer:all"

What we had to do is:

Layout Builder adds a new field to the tables where this feature is enabled, this field is a BLOB field where the layout configuration is saved as a PHP serialized object, each object in the layout is stored in this field with all the proper data to be shown, but, Layout Builder doesn't work as a Drupal entity itself it works in the same way as a text in a field.

Content Sync converts any content in a config presentation in YML when it is exported and then each file is interpreted in a reverse way. Content Sync creates blocks normally when it imports the content, but the relationship stored in the BLOB field is not processed to try to connect properly the content of the field with the blocks. Then the revision_ids inside each inline-block in the layout configuration could not match with the revision_ids over the imported blocks, this is why some inline-blocks are missed and others are misconnected.

To follow up the issue you must query the database in both instances (origin and destination) and check the related data to known entities and fields.

To get specific node information
SELECT * FROM node_field_data WHERE title = 'Web Design';

To get layout builder data using previous information
SELECT bundle, deleted, entity_id, revision_id FROM node__layout_builder__layout WHERE entity_id = 7;

To get serialized data
SELECT CAST(layout_builder__layout_section AS CHAR(50000) CHARACTER SET utf8) FROM node__layout_builder__layout WHERE entity_id = 7;

You will get some like this...
image.png

If you check the layout builder information with the block_content table in both instances (origin and destination), you could check that the information is the same (after import in destination)

But, if you check specific block using
SELECT * FROM block_content WHERE revision_id = 107;

It is possible that block content doesn't match, se below images
image.png

Our solution processes the content inside each node__layout_builder__layout record to connect each inline-block stored in the BLOB field taking in count its UUID code to connect to the correct block.

ilya.no’s picture

StatusFileSize
new20.11 KB
new2.4 KB

I'm currently using latest patch and noticed, that new options have been added to the configuration, but no corresponding schema. Attaching patch with added schema changes.

alexmoreno’s picture

Issue summary: View changes
StatusFileSize
new144.98 KB
new178.55 KB

I've been testing this with latest patch in #116. TLDR, it works.

Now, the long answer, in case it helps anyone else.

Use case: Drupal as a repository of content for a js application (react, but could be vuejs or anything else).

Layout builder is needed to build the content and expose it via json. A content type with layout builder enabled and a few custom blocks for testing.

Used:

- Drupal Version 8.9.2
- https://www.drupal.org/project/jsonapi_explorer (for testing and exploration purposes)

New brand install, enabled json api and layout builder, left everything else untouched. From there, I created a few landing pages where I am overriding the layout, adding new columns, adding blocks, custom blocks with specific fields, etc…

I am fetching the whole list of nodes with this query:
http://alexplayground.lndo.site:8000/jsonapi/node/landing_page/

Then, once I know the node that I to check out, I just fetch that one, say for example:

http://alexplayground.lndo.site:8000/jsonapi/node/landing_page/?filter[d...

Results:
Without the patch I could not see any information related to the layout or the fields exposed on that layout.

After that, I applied the path and I repeated the query. Then I could see how a new field comes available: layout_builder__layout

On it I can see the different layouts, the components I have created inside those layouts, layout_id, column_widths, the weight of each component, etc.

Something to notice is that there will be no information on that query regarding the fields contained on those blocks, apart of label, uuid, and a few other bits. See:

  "configuration": {
        "id": "inline_block:custom_block",
        "label": "test title",
        "provider": "layout_builder",
        "label_display": 0,
        "view_mode": "full",
        "block_revision_id": "6",
        "block_serialized": null,
        "context_mapping": [],
        "type": "custom_block",
        "uuid": "3370b3b9-7d02-43b7-8b65-4c38de8dbf2d"
      },

This can be puzzling on the beginning if you are not familiar with json, and make you think that you are missing information on that query. However, and please correct me here if I'm wrong, I think this is expected. Those extra bits require an extra jsonapi call using the uuid that is provided. For example, I have several blocks on that payload. I choose one of them, get the uuid and make a query like this:

http://alexplayground.lndo.site:8000/jsonapi/block_content/text/d49bdb94...

geek-merlin’s picture

@alexmoreno #117:

Great writeup!

> Something to notice is that there will be no information on that query regarding the fields contained on those blocks, apart of label, uuid, and a few other bits.
> This can be puzzling on the beginning if you are not familiar with json, and make you think that you are missing information on that query. However, and please correct me here if I'm wrong, I think this is expected. Those extra bits require an extra jsonapi call using the uuid that is provided.

Can you check if Includes do work for this case?

vaibhavjain’s picture

Issue summary: View changes

Thank you for explaining things well @alexmoreno. I had same issue (https://www.drupal.org/project/drupal/issues/2942975#comment-13341530), and hence added type and UUID fields to be output (https://www.drupal.org/project/drupal/issues/2942975#comment-13361683). This lets me atleast build the JSON:API URL, which I can use to fetch the content of the components placed, via layout builder.
Yes, this was tested well with custom blocks and multiple block type, however never tried with fields from node or any other blocks from contrib modules.

IMO, we should be providing the relative link automatically, so that we can hit one specific key to fetch the content, than building a URL currently.

@geek-merlin I have verified this before, JSON:API includes does not work well here. Hence the route of adding more info to the output was taken.

geek-merlin’s picture

> I have verified this before, JSON:API includes does not work well here.

Interesting. We should understand and document why. Or even better, make this work, maybe in a followup.

alexmoreno’s picture

Issue summary: View changes
StatusFileSize
new158.19 KB
new4.86 KB

@geek-merlin what I can see is that the document specifies that you need to use "relationship", ie:

{
  "data": {
    "type": "node--article",
    "id": "some-random-uuid",
    "relationships": {
      "field_comments": {
        "links": {
          "related": {
            "href": "https://my.example.com/node/article/some-random-uuid/field_comments"
          }
        }
      }
    }
  }
}

then you can make a query like this:

/jsonapi/node/article/some-random-uuid?include=field_comments.uid

where field_comments is specified on the relationships.

However on my tests I would not get those relationship fields, at least not for the layout builder components. I may not be doing it right though, see payload attached for reference.

Only local images are allowed.

https://www.drupal.org/files/issues/2020-07-17/response-layout-builder-p...

geek-merlin’s picture

@alexmoreno: Thanks a lot!

I did not check the source how JsonApi populates that reference field, but the hottest guess is that it uses EntityInterface::referencedEntities. In which case fixing this at least needs the referenced issue (it may or may not need more).

dmitry.korhov’s picture

Any news so far? This functionality is pretty essential for decoupled Drupal.
Is https://www.drupal.org/project/drupal/issues/3151275 a blocker?
Can we have this patch released at least as experemental module?

alexmoreno’s picture

Hi again,

I have found an scenario where this is not working. I don't think it's expected, but please keep me humble here

If you override the node with a custom layout, the layout data is exposed correctly (as shown in #117).

However, if you have a default layout, and you don't override it in your node with the aim for that node to use the default one, then the json returns that the layout is empty. See:

```"layout_builder__layout":[]}```

When selecting as well that

Another case, if you specify that you don't want for that content type to be customised by the user on the node level, then the layout_builder__layout does not even appear on the json data.

Does this even make sense? Anyone could raise any light on this?

Thanks.

tedbow’s picture

re #124

Does this even make sense? Anyone could raise any light on this?

Yes it makes sense. This issue just deals with exposing the stored layout information. Layout Builder stores the layout override data in a field it controls layout_builder__layout. It stores the default layout in the third party settings information of the LayoutBuilderEntityViewDisplay entity. If a particular bundle does not allow overrides then it does not create the layout_builder__layout field for that bundle.

It sounds like what you want is "For any entity using the layout builder give me layout information". This would take more custom code either on the client side making more request or server-side augmenting the data that is stored with the entity when it is returned with JSON API.

However, if you have a default layout, and you don't override it in your node with the aim for that node to use the default one, then the json returns that the layout is empty.

Yes this because when you make a JSON API request for the node it only returns the actual data that is stored in the field just like any other field. In the case when there is not an override there is not date stored in this field.

Another case, if you specify that you don't want for that content type to be customised by the user on the node level, then the layout_builder__layout does not even appear on the json data.

This is because the layout_builder__layout is not added until entity display is set to use the layout builder and allow overrides. The field is also deleted if the ability do overrides is removed(you can't do this while there is field data, i.e. any existing overrides.)
@see \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::addSectionField() and \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::removeSectionField()

if you wanted get the default layout when there is no override you would have to make a JSON API request for entity_view_display entity that stores this information in it's third party settings. It would tell if the layout builder is enable and the default layout.

alexmoreno’s picture

I did some work trying to get the default layouts for when the nodes are not overriding it.

Here are my notes, I'll publish this code in a module as well, so it's easier to patch in case anyone has any feedback

https://www.alexmoreno.net/layout-builder-exposing-content-type-default-...

alexmoreno’s picture

see as well the code here: https://www.drupal.org/project/lb_default_layout

Can we assume that this patch is tested and RBTC? Are there any concerns left?

tim.plunkett’s picture

Still needs an issue summary update.
The patch is also failing tests.
Here's a code review.
Whoever updates the patch, please include an interdiff.

  1. +++ b/core/modules/layout_builder/layout_builder.services.yml
    @@ -44,6 +44,17 @@ services:
    +  layout_builder.normalizer.entity_display:
    +    class: Drupal\layout_builder\Normalizer\LayoutEntityDisplayNormalizer
    +    tags:
    +      # Priority must be higher than serializer.normalizer.config_entity.
    +      - { name: normalizer, priority: 1 }
    +    arguments: ['@entity_type.manager', '@entity_type.repository', '@entity_field.manager']
    +  layout_builder.normalizer.section_data:
    +    class: Drupal\layout_builder\Normalizer\SectionDataNormalizer
    +    tags:
    +      # Priority must be higher than serializer.normalizer.typed_data.
    +      - { name: normalizer, priority: 1 }
    
    +++ b/core/modules/layout_builder/src/LayoutBuilderServiceProvider.php
    @@ -39,14 +37,6 @@ public function register(ContainerBuilder $container) {
    -    if (isset($modules['serialization'])) {
    -      $definition = (new ChildDefinition('serializer.normalizer.config_entity'))
    -        ->setClass(LayoutEntityDisplayNormalizer::class)
    -        // Ensure that this normalizer takes precedence for Layout Builder data
    -        // over the generic serializer.normalizer.config_entity.
    -        ->addTag('normalizer', ['priority' => 5]);
    -      $container->setDefinition('layout_builder.normalizer.layout_entity_display', $definition);
    -    }
    

    Why this change?

  2. +++ b/core/modules/layout_builder/src/Plugin/DataType/SectionData.php
    @@ -30,8 +30,18 @@ class SectionData extends TypedData {
    +
    +    if ($value && is_array($value)) {
    +      $value = Section::fromArray($value);
    +    }
    ...
         if ($value && !$value instanceof Section) {
    

    This addition isn't documented. It also seems to overlap with the next conditional

  3. +++ b/core/modules/layout_builder/src/Plugin/DataType/SectionData.php
    @@ -30,8 +30,18 @@ class SectionData extends TypedData {
    +      else {
    +        parent::setValue($value->value, $notify);
    +      }
    

    Drop the else case, and have $value = $value->value;?

    Also why is there all of a sudden a $value->value?

  4. +++ b/core/modules/layout_builder/src/Section.php
    @@ -337,9 +337,9 @@ public function toArray() {
    -      'components' => array_map(function (SectionComponent $component) {
    +      'components' => array_values(array_map(function (SectionComponent $component) {
    

    Why this addition? Does this change have test coverage?

  5. +++ b/core/modules/layout_builder/tests/src/Unit/SectionDataNormalizerTest.php
    @@ -0,0 +1,95 @@
    +    $section->toArray()
    +      ->willReturn($data);
    +    $section_data->getValue()
    +      ->willReturn($section);
    

    Nit: remove needless returns/indents

  6. +++ b/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.full.yml
    @@ -31,7 +31,7 @@ third_party_settings:
    -          eadd557c-6414-40e5-9a95-355720385477:
    +          -
    

    Whoa, this is a data model change, isn't it?

heddn’s picture

re #128.6. See #100 for the reason for those changes. It was an issue w/ XML seralization. Not so much for JSON/YAML. But we have to support all, right?

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Oscaner’s picture

StatusFileSize
new20 KB

Based on #116 patch, no changes, just want to patch successfully on Drupal 8.8.10

mayurjadhav’s picture

Status: Needs work » Needs review
StatusFileSize
new9.94 KB

Added patch for 8.9.x, Kindly Review.

Ref from duplicate issue: https://www.drupal.org/project/drupal/issues/3182960

tim.plunkett’s picture

@mayurjadhav How does that relate to the patch from #116 that I reviewed in #128?
Or the reroll for 8.8 in #131? Your patch is less than half the size, and doesn't seem to have any test coverage.


As I asked in #128:

Whoever updates the patch, please include an interdiff.

Someone please help get this issue back on track! Needs an issue summary update, and also a fresh 9.2.x patch that takes #128 into account.

mayurjadhav’s picture

Assigned: Unassigned » mayurjadhav
Status: Needs review » Needs work

@tim.plunkett Sorry for the incomplete patch...I was in rush and uploaded patch without reading all comments..I'm working on latest patch which will address all the points mention in #128 along with Test.

Oscaner’s picture

StatusFileSize
new25.88 KB
new934 bytes
manuel.adan’s picture

StatusFileSize
new20.11 KB

#131 just for the 8.9.x branch

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

kuhikar’s picture

StatusFileSize
new461.84 KB
new243.58 KB
new55.09 KB

Hello Team

I have resolved phpcs for 9.1.x and added patch: 2942975_137.patch by combining 2942975-drupal_8_9_x-136.patch.

I have followed below steps for 9.1.x version:

Please do check attached images for the reference.

kuhikar’s picture

StatusFileSize
new55.09 KB
kuhikar’s picture

StatusFileSize
new55.63 KB
new55.08 KB

Hello Team,

I have corrected CSpell : failed issue of https://www.drupal.org/pift-ci-job/2105852 for #138. Please do check updated patch (
2942975_140.patch, 2942975_d8_to_d9_140.patch )
for resolving the phpcs errors in Drupal 9.1.x.

Please merge #136 and create 3.x version, after that for 9.1.x, please merge
2942975_140.patch.

2942975_d8_to_d9_140.patch created for Unix Line Ending formats and root directory is in /app folder.

dmitry.korhov’s picture

Assigned: mayurjadhav » Unassigned

@kuhikar please add interdiff

kuhikar’s picture

StatusFileSize
new54.33 KB
new304.04 KB

Hello Team,

Please do check updated patch : 2942975-142-d8_d9.patch for resolving hunk error.

@dmitry.korhov, Please check attached interdiff-136-142.txt.

I have applied #136 patch on D89x and #142 on D91x and after that, I run command to get diff for --core/modules/layout_builder.

kuhikar’s picture

Hello Team,

Currently, we are migrating D8 to D9 and please help to merge patch so we will have 3.x version.

Please do check: Drupal 8 end-of-life on November 2, 2021 : https://www.drupal.org/psa-2021-2021-06-29

Kindly help us to release 3.x version.

kuhikar’s picture

Hello Team,

Any update to release 3.x version of this module? Kindly help us.
@dmitry.korhov, Can you please review patch: 2942975-142-d8_d9.patch

Drupal 8 end-of-life on November 2, 2021 : https://www.drupal.org/psa-2021-2021-06-29

acouch’s picture

StatusFileSize
new55.05 KB
new14.75 KB

I re-rolled this against 9.3.x

tim.plunkett’s picture

Unfortunately all of the patches posted since #116 have either lost changes or added new unnecessary changes. Switching to an MR and maybe going to try to address #128...

Still needs an issue summary update.

tim.plunkett’s picture

Status: Needs work » Needs review

NR to see how tests are doing

tim.plunkett’s picture

Issue summary: View changes
Issue tags: -Needs issue summary update

Okay I went ahead and made the issue summary updates and feedback changes I'd asked for last year, and resolved the remaining test failures.
This should be ready for review now.

trevorbradley’s picture

Status: Needs review » Needs work

Commit e866ee63 is causing a fault on my system:

[error] InvalidArgumentException: Value assigned to "section" is not a valid section in Drupal\layout_builder\Plugin\DataType\SectionData->setValue() (line 34 of /app/docroot/core/modules/layout_builder/src/Plugin/DataType/SectionData.php).

$value is still being passed in as an array for a custom layout section, removing the array filter from SectionData::setValue() causes it to break.

mkalkbrenner’s picture

Here's a patch based on MR 1131 and the comment #150.

mkalkbrenner’s picture

StatusFileSize
new15.14 KB

Something went wrong.

tedbow’s picture

Status: Needs work » Needs review
mkalkbrenner’s picture

I ran the failing tests multiple times locally. The result toggles. Sometimes the tests succeed, sometimes they fail.

tim.plunkett’s picture

Please stop posting patches now that we're using the MR. Just push new commits to the branch.

mkalkbrenner’s picture

@tim.plunkett the patch I posted didn't contain anything new. It just reflects an earlier version of the MR, that doesn't lead to errors in default_content_deploy, just as mentioned in #150.
I uploaded it to have something that could be used deployment piplines already.

Am I allowed to revert your change directly in the MR?

The required change is already discussed above and it seemed that you're not convinced yet.

deciphered’s picture

I can confirm that the patch from #152 works with Tome and JSON:API whereas the current MR works with JSON:API but not Tome, with the errors reported in #150.

It would be ideal to get the MR synced back to the patch.

BalasaranyaV’s picture

Status: Needs work » Needs review
StatusFileSize
new15.16 KB
new15.16 KB

Rebased a patch #152 to merge with Drupal 9.3.x branch.

christian.wiedemann’s picture

Hi all, I try to solve the puzzle to load layout builder inline blocks with JSON:API. My puzzle starts here and after a long weekend I just want to ask if I am on the right trail.

This patch provides sections and components but not the associated block content entities. This is by design. To fetch inline blocks we need a second jsonapi call. @alexmoreno mentioned it in #117. (Thanks for the post, it helps to understand such long issues)

Fetching blocks works right now BUT filter by any query doesn't. There is hard coded resuable=true in TemporaryQueryGuard. So I can't fetch them. This is propably also by design? So I can fetch a block with jsonapi/block_content/text/d49bdb94... but not with jsonapi/block_content/text?filter[id]=d49bdb94... or with any other filter.

        if (isset(static::$fieldManager->getBaseFieldDefinitions($entity_type_id)['reusable'])) {
          $specific_condition = new EntityCondition('reusable', 1);
          $cacheability->addCacheTags($entity_type->getListCacheTags());
        }

So I did not find any solution to fetch multiple non reusable inline blocks in one call. To help me out I created https://www.drupal.org/project/jsonapi_include_lb which uses a simple computed field to provide blocks as entity reference.

Is there a better option?

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mkalkbrenner’s picture

Status: Needs work » Needs review
StatusFileSize
new15.16 KB

Re-rolled against 9.4.x to get test results

mkalkbrenner’s picture

Status: Needs work » Needs review

I ran the tests locally. The same tests fail. As soon as I enable xdebug and step through \Drupal\rest\Plugin\rest\resource\EntityRessource::get(), the tests succeed. It looks like a timing issue which is strange.
If the error happens and the server returns status code 500 it complains about an illegal character in \Symfony\Component\Serializer\Encoder\XmlEncoder.
But I can't debug it. As already mentioned, the error doesn't happen as soon as xdebug is enabled and I try to step through the process.

mkalkbrenner’s picture

StatusFileSize
new15.23 KB
mkalkbrenner’s picture

like described in #165 and seen as different numbers of failures in #163 and #166, there seems to be a timing problem or an issue with randomized content in the tests.

drupalninja99’s picture

I am confused why we went away from this approach which return components as an array of objects: https://www.drupal.org/files/issues/2021-08-25/2942975_145.patch

This is much more useful in Gatsby. I saw at some point that change went away back to a nested object.

drupalninja99’s picture

I have the same issue cited in https://www.drupal.org/project/drupal/issues/2942975#comment-13361683 and other places where I can't fetch inline block data from JSON:API like I would say paragraphs. Those JSON:API endpoints only include reusable blocks and the patch from this thread does not include all the block fields in layout_builder__layout. That means I am unable to get all the block data I need on the frontend.

drupalninja99’s picture

After quite a bit of work/testing I found the solution I needed in project jsonapi_include_lb.

sumitmadan made their first commit to this issue’s fork.

sumitmadan’s picture

I rebased the MR with 9.4.x branch. I am not able to edit the base branch in the MR. I am not sure if I need any permission for that.

@tim.plunkett can you please update that?

sumitmadan’s picture

I continued testing the MR on my local. I see two tests are failing which are because of a single reason. The xml format is not rendering properly. The error is following:

DOMException: Invalid Character Error in DOMDocument->createElement() (line 490 of /app/vendor/symfony/serializer/Encoder/XmlEncoder.php).

The reason is the uuid part inside the component key.

"components": {
   "38a9bdec-3df6-457d-bf7a-15b19bd67736": {
}

Does anybody have a suggestion on this problem?

Paragraph does it like this and it works fine with paragraph:

"field_test": [
	{
		"target_id": 1,
		"target_revision_id": 1,
		"target_type": "paragraph",
		"target_uuid": "d1fd68e4-e561-4d09-afd4-cbb6ac86d190"
	},
	{
		"target_id": 2,
		"target_revision_id": 2,
		"target_type": "paragraph",
		"target_uuid": "02b5f3d6-8cf5-4b31-9b07-cb5480223860"
	}
]
tim.plunkett’s picture

#173, thanks for the rebase. I adjusted the target branch.

mattjones86’s picture

I have given this MR a try today and found that while it did expose the Layout Builder data, it unfortunately didn't do a great job exposing data for the inline_block entities.

Within each Layout Builder Section these block are referenced with block_revision_id, but the relationships are not attached to allow modules like entity_share to know where to find these.

It would be ideal if these could be looked up and appended in a similar method to EntityReference fields. I did take a look at updating the MR with this myself, but it looked a little too complex to attempt without guidance.

From what I understand, it would involve updating ResourceObjectNormalizer::serializeField() to handle LayoutSectionItemList fields, along with adding quite a few new methods (e.g. Relationship::createFromLayoutBuilderField()) to find and append the correct relationships.

      if ($field instanceof EntityReferenceFieldItemListInterface) {
        // Build the relationship object based on the entity reference and
        // normalize that object instead.
        assert(!empty($context['resource_object']) && $context['resource_object'] instanceof ResourceObject);
        $resource_object = $context['resource_object'];
        $relationship = Relationship::createFromEntityReferenceField($resource_object, $field);
        $normalized_field = $this->serializer->normalize($relationship, $format, $context);
      }
      else if ($field instanceof LayoutSectionItemList) {
        // Pluck inline_block revision IDs and append to relationships here
      }
      else {
        $normalized_field = $this->serializer->normalize($field, $format, $context);
      }
{
  "jsonapi": {
    "version": "1.0",
    "meta": {
      "links": {
        "self": {
          "href": "http://jsonapi.org/format/1.0/"
        }
      }
    }
  },
  "data": {
    "type": "node--article",
    "id": "d7284b3e-a616-4d33-ac88-919bce701b63",
    "links": {
      "self": {
        "href": "https://dev.example.com/jsonapi/node/article/d7284b3e-a616-4d33-ac88-919bce701b63?resourceVersion=id%3A1"
      }
    },
    "attributes": {
      "drupal_internal__nid": 1,
      "drupal_internal__vid": 1,
      "langcode": "en",
      "revision_timestamp": "2021-09-14T09:41:50+00:00",
      "revision_log": null,
      "status": true,
      "title": "Article Style Guide",
      "created": "2021-09-14T09:41:39+00:00",
      "changed": "2022-01-19T10:47:02+00:00",
      "promote": false,
      "sticky": false,
      "default_langcode": true,
      "revision_translation_affected": true,
      "metatag": null,
      "path": {
        "alias": "/article-style-guide",
        "pid": 82,
        "langcode": "en"
      },

      ...

      "layout_builder__layout": [
        {
          "section": {
            "layout_id": "layout_twocol_section",
            "layout_settings": {
              "label": "",
              "column_widths": "50-50",
              "layout_builder_styles_style": [
                "section_margin_normal",
                "section_vertical_align_top",
                "section_width_normal"
              ],
              "context_mapping": []
            },
            "components": {
              "5a6eed43-01f1-4bc3-88d3-0e933da4ab7e": {
                "uuid": "5a6eed43-01f1-4bc3-88d3-0e933da4ab7e",
                "region": "first",
                "configuration": {
                  "id": "inline_block:image",
                  "label": "",
                  "label_display": true,
                  "provider": "layout_builder",
                  "view_mode": "full",
                  "block_revision_id": "223987",
                  "block_serialized": null,
                  "context_mapping": []
                },
                "weight": 0,
                "additional": []
              }
            }
          }
        }
      ]
    },
    "relationships": {
      "node_type": {
        "data": {
          "type": "node_type--node_type",
          "id": "1af93c9b-8669-4535-b786-f4c3f0b51488",
          "meta": {
            "drupal_internal__target_id": "article"
          }
        },
        "links": {
          "related": {
            "href": "https://dev.example.com/jsonapi/node/article/d7284b3e-a616-4d33-ac88-919bce701b63/node_type?resourceVersion=id%3A1"
          },
          "self": {
            "href": "https://dev.example.com/jsonapi/node/article/d7284b3e-a616-4d33-ac88-919bce701b63/relationships/node_type?resourceVersion=id%3A1"
          }
        }
      },

       // Would be ideal to see the related inline_block entities here!!

    }
  },
  "links": {
    "self": {
      "href": "https://dev.example.com/jsonapi/node/article/d7284b3e-a616-4d33-ac88-919bce701b63?resourceVersion=id%3A1"
    }
  }
}
tedbow’s picture

re #176

It would be ideal if these could be looked up and appended in a similar method to EntityReference fields.

I agree what that would be ideal but I think that could be follow-up to this issue. This issue is already 4 years old and adding more scope will just make take longer to get committed.

I don't think we can alter layout_builder__layout to add this information because then this would probably cause problems for instance where this serialization was being used for import/export purposes. So it would probably have to be somewhere else in the JSON API response. For that reason I think it adds extra complexity to this issue.

vacho’s picture

StatusFileSize
new15.88 KB

This patch is for core 8.3.x and contains array_values for SectionComponent. To avoid to crash the installation.

joachim made their first commit to this issue’s fork.

antonnavi’s picture

StatusFileSize
new16.39 KB
new703 bytes

Patch for core 9.3.x (posted in #178) was updated:
Added exposing of sections on request (through jsonapi module /jsonapi/page_variant/page_variant) of page variant which was built as a "Layout Builder". See more details here: https://www.drupal.org/project/page_manager/issues/3170526

antonnavi’s picture

@tim.plunkett or @joachim is it possible to add changes:

diff -u b/core/modules/layout_builder/src/Section.php b/core/modules/layout_builder/src/Section.php
--- b/core/modules/layout_builder/src/Section.php
+++ b/core/modules/layout_builder/src/Section.php
@@ -16,7 +16,7 @@
  * @see \Drupal\Core\Layout\LayoutDefinition
  * @see \Drupal\layout_builder\SectionComponent
  */
-class Section implements ThirdPartySettingsInterface {
+class Section implements ThirdPartySettingsInterface, \JsonSerializable {
 
   /**
    * The layout plugin ID.
@@ -441,2 +441,11 @@
 
+  /**
+   * Returns a representation of the section for use in JSON serialization.
+   *
+   * @return array
+   *   Representation of the section.
+   */
+  public function jsonSerialize() {
+    return $this->toArray();
+  }
+
 }

to the issue branch (to be able to export of sections through the jsonapi module on request like /jsonapi/page_variant/page_variant).

UPD: Added, found how to do it by myself. Sorry for bothering.

vacho’s picture

Still needs to fix, test issues.

trevorbradley’s picture

[Deleted] My comment is about the layout_builder_st contrib module, not core. Apologies for getting my wires crossed. I'll go make my comment there.

tim.plunkett’s picture

Hiding patches since all work should be in the MR.

drupalninja99’s picture

Status: Needs work » Needs review
StatusFileSize
new16.28 KB

A shot in the dark but I liked the array_values() addition that was questioned in #128. This makes it much easier to query component data from GraphQL. Adding to the layout_builder-rebase_drupal_9_3_x-2942975-159.patch so that you can see what it looks like in comparison.

Status: Needs review » Needs work
fpoirier’s picture

I tried path #185 and #180 and I do get the section data although I only get the components definitions without the block values. Here an example :

"layout_builder__layout": [
    {
      "section": {
        "layout_id": "layout_onecol",
        "layout_settings": {
          "label": ""
        },
        "components": [
          {
            "uuid": "567ecf83-40c0-4554-befb-491ceaf38eb5",
            "region": "content",
            "configuration": {
              "id": "inline_block:card",
              "label": "Lorem ipsum title",
              "label_display": "visible",
              "provider": "layout_builder",
              "view_mode": "full",
              "block_revision_id": "2",
              "block_serialized": null,
              "context_mapping": [
                
              ],
              "type": "card",
              "uuid": "4d8cb490-6d31-4a2b-8d16-98a1490dcdef"
            },
            "weight": 2,
            "additional": [
              
            ]
          }
        ],
        "third_party_settings": [
          
        ]
      }
    }
  ]

I did some debugging and I realize that the `LayoutEntityDisplayNormalizer` is never called which could maybe explain why the inline block values are not showing ?

plach’s picture

Status: Needs work » Needs review
StatusFileSize
new16.67 KB
new1.3 KB

I was testing this and got an error on denormalizaton, this updated patch seems to fix it.

plach’s picture

StatusFileSize
new16.6 KB

And this the 9.3.x version.

kriboogh’s picture

StatusFileSize
new16.63 KB

Small update on #189 to silence the return type error.

ranjith_kumar_k_u’s picture

StatusFileSize
new16.63 KB
new382 bytes

Status: Needs review » Needs work

The last submitted patch, 191: 2942975-191.patch, failed testing. View results

junaidpv’s picture

Status: Needs work » Needs review
StatusFileSize
new16.6 KB
new689 bytes

Exporting works fine with #191, but it fails with this message when try to import the exported node with layout builder settings:

[error] Drupal\Component\Plugin\Exception\PluginNotFoundException: The "" plugin does not exist. Valid plugin IDs for Drupal\Core\Layout\LayoutPluginManager are: layout_twocol_section, layout_threecol_section, layout_fourcol_section, layout_onecol, layout_twocol, layout_twocol_bricks, layout_threecol_25_50_25, layout_threecol_33_34_33, radix_bryant_flipped, radix_bartlett_flipped, radix_bartlett, radix_boxton, radix_brenham_flipped, radix_brenham, radix_brown, radix_bryant, radix_burr_flipped, radix_burr, radix_geary, radix_harris, radix_hewston_flipped, radix_hewston, radix_mccoppin, radix_moscone_flipped, radix_moscone, radix_phelan, radix_pond, radix_rolph, radix_sanderson_flipped, radix_sanderson, radix_selby_flipped, radix_selby, radix_sutro_double, radix_sutro, radix_taylor_flipped, radix_taylor, radix_webb_flipped, radix_webb, radix_whelan, vefl_onecol, layout_builder_blank in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 53 of core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php).

I noticed the exported layout builder settings part having extra level of "section". Here is the patch fixing that issue. Then it worked with importing node with same layout builder settings.

Status: Needs review » Needs work

The last submitted patch, 193: 2942975-192.patch, failed testing. View results

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

ilya.no’s picture

StatusFileSize
new16.6 KB
new6.3 KB

Attaching patch for 9.5.x-dev version. Works locally. Tried to fix tests, but no luck so far. Interdiff may be not correct, since some test files were moved to hal module.

flyke’s picture

I can confirm that patch #196 also applies to 9.4.1

rassoni’s picture

Status: Needs work » Needs review
StatusFileSize
new23.06 KB
new9.3 KB

Try to fix test failed issues.

rassoni’s picture

StatusFileSize
new23.12 KB

Status: Needs review » Needs work

The last submitted patch, 199: 2942975-199.patch, failed testing. View results

christian.wiedemann’s picture

With the latest patch #199 enabled layout builder sections are not part of json output of entity_view_display jsonapi call.

e.g:
jsonapi/entity_view_display/entity_view_display/2edbf6ce-3960-4f54-86ac-0703774c9d8f

The reason for this behavior is "Drupal\jsonapi\Normalizer\ResourceObjectNormalizer:196";

      // @todo Replace this workaround after https://www.drupal.org/node/3043245
      //   or remove the need for this in https://www.drupal.org/node/2942975.
      //   See \Drupal\layout_builder\Normalizer\LayoutEntityDisplayNormalizer.
      if ($context['resource_object']->getResourceType()->getDeserializationTargetClass() === 'Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay' && $context['resource_object']->getField('third_party_settings') === $field) {
        unset($field['layout_builder']['sections']);
      }

I created a follow up issue to remove the unset.

see: https://www.drupal.org/project/drupal/issues/3293908

tim.plunkett’s picture

That was added in #3042198: Add JSON:API integration test for LayoutBuilderEntityViewDisplay (after this issue had begun). I don't know that it needs to be removed separately, could happen here

morbus iff’s picture

Do the updated patches support the PATCH/POSTing of the layout builder layouts field? Back in #72/75: "When attempting to PATCH a layout_builder__layout field, I receive: "The current user is not allowed to PATCH the selected field (layout_builder__layout)." I receive the same error with POST, meaning I can't create a custom layout in a node (i.e., I can't create custom landing pages from JSON:API). That's my sole need - is this patch only for EXPOSING the data, or also for creating/updating that data?"

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

yahyaalhamad’s picture

The field only displays overridden layouts, it does not work with default layouts.

dmitry.korhov’s picture

The field only displays overridden layouts, it does not work with default layouts.

There is a workaround for it, we managed it by triggering Enhancer (from JSONAPI Extras) manually in some event

nielsaers’s picture

For those creating a patch from https://git.drupalcode.org/issue/drupal-2942975/-/tree/2942975-reroll-9.4.x and using the the patch from https://www.drupal.org/project/drupal/issues/2946333. There will be a conflict in applying it.

The patch in 2946333 adds the following line to LayoutBuilderEntityViewDisplayResourceTestBase.php:

    $expected['hidden'][OverridesSectionStorage::TRANSLATED_CONFIGURATION_FIELD_NAME] = TRUE;

Below:

    $expected['hidden'][OverridesSectionStorage::FIELD_NAME] = TRUE;
junaidpv’s picture

#196 used to work for me. But now I also need patch from #3293908-5: Expose Layout Builder Sections to entity view displays (jsonapi/entity_view_display/entity_view_display) to work the importing back the content with the layout builder overriden settings.

daniel.pernold’s picture

StatusFileSize
new22.09 KB

Reroll for Drupal 9.4.8

_pratik_’s picture

StatusFileSize
new22.12 KB

Patch is applying now for me.

_utsavsharma’s picture

Status: Needs work » Needs review
StatusFileSize
new17.48 KB

Fixed CCF of #212.
Please review.

Status: Needs review » Needs work

The last submitted patch, 213: 2942975-213.patch, failed testing. View results

arisen’s picture

StatusFileSize
new21.93 KB

Added missing files SectionDataNormalizer.php and SectionDataNormalizerTest.php to #213.
Patch applying properly. Please review.

arisen’s picture

Status: Needs work » Needs review
arisen’s picture

Version: 10.1.x-dev » 9.4.x-dev
StatusFileSize
new21.91 KB

Fixed CCF of #215. Please review.

arisen’s picture

Version: 9.4.x-dev » 10.1.x-dev

Status: Needs review » Needs work

The last submitted patch, 217: 2942975-217.patch, failed testing. View results

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new3.6 KB
new18.22 KB

Re-roll and clean-up for 10.1.x

andypost’s picture

StatusFileSize
new463 bytes
new18.22 KB

fix CS

Status: Needs review » Needs work

The last submitted patch, 221: 2942975-221.patch, failed testing. View results

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.64 KB
new18.31 KB

Fix return types

andypost’s picture

StatusFileSize
new1.55 KB
new18.32 KB

and bit more

The last submitted patch, 223: 2942975-223.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 224: 2942975-224.patch, failed testing. View results

dmitry.korhov’s picture

`mixed` return type should not be used, we know what kind of entity|variable is returned.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new1.18 KB
new18.38 KB

One more polishing round

Status: Needs review » Needs work

The last submitted patch, 228: 2942975-228.patch, failed testing. View results

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new891 bytes
new18.11 KB

still not clear why serializer does not return tests for failed LB tests, but here copy-paste clean-up

Status: Needs review » Needs work

The last submitted patch, 230: 2942975-230.patch, failed testing. View results

morbus iff’s picture

Has anyone gotten this to work with POSTing a new node, with a layout_builder__layout configuration? Whenever I attempt to add a layout builder configuration, with a single views block, I get error "The current user is not allowed to POST the selected field (layout_builder__layout).", even though the current user is an administrative user.

Aaron23’s picture

Hi Team,

This patch works for me 2942975-196.patch

In addition to that I have used layout library module.

When I create a node and selecting the layout library (chosen any of the template which is created from layout library). In the page api response I'm seeing an empty array,

"layout_builder__layout": []

Just simply once, I go to the layout of the node and save it.. I'm able to see the components

Could anyone help to fix it and possible to provide solution???

kyberman’s picture

Hi, if anybody simply needs to export the "layout_builder__layout" field serialized value using a REST view (e.g. for migration), I created a little formatter with a combination of hook_entity_field_access_alter. Any feedback is welcome, thanks!

function YOUR_MODULE_entity_field_access_alter(array &$grants, array $context) {
  if ($context['field_definition']->getName() === 'layout_builder__layout'
    && $context['operation'] === 'view' && $grants[':default']->isForbidden()
  ) {
    $grants[':default'] = AccessResult::allowed()->inheritCacheability($grants[':default']);
  }
}
namespace Drupal\YOUR_MODULE\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Render\Markup;

/**
 * @FieldFormatter(
 *   id = "layout_builder_raw",
 *   label = @Translation("Layout Builder raw data"),
 *   description = @Translation("Display the Layout Builder raw data."),
 *   field_types = {
 *     "layout_section",
 *   }
 * )
 */
class LayoutBuilderRawFormatter extends FormatterBase {

  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];
    $entity = $items->getEntity();

    foreach ($items as $delta => $item) {
      $elements[$delta] = [
        '#markup' => Markup::create(serialize($item->section)),
        '#cache' => [
          'tags' => $entity->getCacheTags(),
        ],
      ];
    }

    return $elements;
  }

}
andypost’s picture

After SF 6.3 upgrade it will need return types

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mkalkbrenner’s picture

StatusFileSize
new18.16 KB

#230 doesn't apply for Drupal 10.1.1. Here's an adjusted version.

patriciacb’s picture

StatusFileSize
new7.44 KB

I rerrolled the patch in #237 because still couldn't be applied to version 10.1.1. I couldn't generate the interdiff file because it throws the typical error with whitespaces that I haven't been able to solve.

patriciacb’s picture

StatusFileSize
new7.44 KB

I rerrolled the patch because it couldn't be applied to version 10.1. I couldn't generate the interdiff file because it throws the typical error with whitespaces that I haven't been able to solve.

sorlov’s picture

StatusFileSize
new18.55 KB

reroll for latest 10.1.x

sorlov’s picture

StatusFileSize
new18.1 KB
sorlov’s picture

sorlov’s picture

StatusFileSize
new18.2 KB

reroll for latest 11.x

sorlov’s picture

sorlov’s picture

Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs upgrade path

Seems there are a few test failures.

Also see a schema change imagine that will need a post_update and tests.

larowlan’s picture

At present there's a security issue with this patch, if you're using it to POST/PATCH

\Drupal\layout_builder\Plugin\Block\InlineBlock::getEntity calls unserialize on block_serialized

If that value is provided by untrusted user input over an API, you could open the site up to a gadget chain attack.

I also think that points to a larger issue with this patch in relation to JSON:API, and that's that we don't get relationship support for inline blocks.

I've got some thoughts on that and will take some time to write that up in the next fortnight or so.

wim leers’s picture

I lost this write-up not once, but twice, because my >5 year old iPad is not able to handle looking at 2 browser tabs if one of them is this one. Kind of understandable though: it's 158 KB of HTML 🫣

I haven't reviewed this issue in ~5 years, but #247 shows that there are still security concerns (see the ones I raised 5 years ago at #33).

👏 @larowlan for the detailed analysis over at https://www.previousnext.com.au/blog/pitchburgh-diaries-decoupled-layout... 👏

I agree with his statements, assuming that it is a hard requirement to be able to truly access sections and components as related resources.

I'm not convinced this is truly a hard requirement though. I do see the need for listing all available section plugins and all available components. Without that, it's impossible for the client to know the possible values. But I don't see the need to address/access section (plugin) instances and component (plugin) instances (meaning: as they are used in a specific entity) directly via JSON:API? 🤔

If we'd drop that requirement:

  1. Why would it not be enough to model/expose/normalize Layout Builder sections and components used in a given entity like any other field? Because attributes (the JSON:API equivalent of "entity fields") may contain any valid JSON value, including complex data structures involving JSON objects and arrays?
  2. If we did that, then I think we might be able to express references to other entities from within those components kind of like Dynamic Entity References? Why would that not be sufficient? /jsonapi/<node 4453>/relationships/layout + a meta on the relationship to express that this is a reference for that component?

I bet I'm missing something though, because it's been years since I dug into JSON:API or Layout Builder details 😅 But it's a testament to your excellent write-up, that I was able to articulate this. Still an inkling of hope that this will help get this issue going… 🤞🤓

andypost’s picture

I bet there's different purpose and requirement additionally to subject of the issue.

Moreover this part already exists - #3231584: DiffArray does not serialize Layout builder section objects causing an error with view display configs managed by layout_builder

(De)serialization is required for
- configuration of entity displays with pre-configured sections #3151275: referencedEntities should return referenced layout builder added entities
- entities for contrib Default_content #3160146: Add a Normalizer and Denormalizer to support Layout Builder and similar to #2956221: Issue with Layout Builder and Serializer normalization

larowlan’s picture

Title: Expose Layout Builder data to REST and JSON:API » [PP-1] Expose Layout Builder data to REST and JSON:API
Status: Needs work » Postponed
Related issues: +#3391461: Harden the use of unserialize in InlineBlock via allowed classes

#248 I think that's worth exploring - hadn't considered using meta.

In the meantime I opened #3391461: Harden the use of unserialize in InlineBlock via allowed classes which is a hard blocker for this.

wmcmillian’s picture

StatusFileSize
new18.28 KB

I've re-rolled this and added this to the SectionDataNormalizer:

/**
   * {@inheritdoc}
   */
  protected $supportedInterfaceOrClass = SectionData::class;

This was causing an issue when normalizing/denormalizing entities with other typed data attached to them.

adwivedi008’s picture

Hii everyone

I am using #239 for D-10.1.7 and along with this patch I am also using https://www.drupal.org/files/issues/2023-07-25/2946333-d10-307.patch

The patch applies clearly but I am facing this error while clearing the cache

PHP Fatal error: Class Drupal\layout_builder\Section contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize) in /web/core/modules/layout_builder/src/Section.php on line 21

Please suggest how to resolve this

adwivedi008’s picture

StatusFileSize
new6.92 KB

Revised #239 for

PHP Fatal error: Class Drupal\layout_builder\Section contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize) in /web/core/modules/layout_builder/src/Section.php on line 21

After comparing with #251

flyke’s picture

The most recent patch I found that applies to Drupal 10.2 is #237 at this moment.

adwivedi008’s picture

StatusFileSize
new6 KB
new18.14 KB

Rerolled patch#237 as it was failing for D-10.1.7

s_leu made their first commit to this issue’s fork.

kevinquillen’s picture

Where does this issue stand? In my case I am only concerned with GET requests to feed headless instances. With the patch, I do get some layout data, for example:

"layout_builder__layout": [
{
"layout_id": "layout_onecol",
"layout_settings": {
"label": "",
"section_uuid": "4d50e824-c405-4f5d-bfe7-b96dc1e88b99"
},
"components": [
{
"uuid": "eadd557c-6414-40e5-9a95-355720385477",
"region": "content",
"configuration": {
"id": "field_block:node:recipe:field_tags",
"label_display": "0",
"context_mapping": {
"entity": "layout_builder.entity"
},
"formatter": {
"type": "entity_reference_label",
"label": "inline",
"settings": {
"link": true
},
"third_party_settings": []
}
},
"weight": 3,
"additional": []
},

But no inline block data, or relationships.

kevinquillen’s picture

With the patch from 255, and:

I can get managed layout data, overridden entity layout data, and block data in layout builder over JSON:API. However, regions are not in order and neither are blocks, and I think that should be a part of this patch. The data should be stored or returned in the order it is saved. Otherwise this forces consumers to have to assemble it after the fact. It may not be perfect but it is starting to finally seem possible that we can serve headless solutions that use Layout Builder and assemble the data in a framework of choice in a decoupled setup.

I think it is more critical to fix those issues so JSON:API data can be read over GET requests at a minimum first to start empowering decoupled solutions and focus on the rest in other issues.

kevinquillen’s picture

StatusFileSize
new14.09 KB

Re-roll for 10.3.

kevinquillen’s picture

StatusFileSize
new18.68 KB

Re-rolled patch to include new files.

flyke’s picture

Seems to work or at least apply on a clean 10.3.x

flyke’s picture

StatusFileSize
new13.79 KB

Comment deleted because the original reroll patch did work. Just not in my project, probably a conflict with another patch.
Update: it seems to be a conflict with #3049332 Because if I do this in my patches section of my project's composer.json file:

        "patches": {
            "drupal/core": {
                "#2942975":"https://www.drupal.org/files/issues/2024-06-21/2942975-262-reroll.patch",
                "#3049332":"https://www.drupal.org/files/issues/2024-06-26/3049332_d10.3.0.patch",

Then this patch works, but the path from #3049332 will not apply.
If I do this in my composer.json:

        "patches": {
            "drupal/core": {
                "#3049332":"https://www.drupal.org/files/issues/2024-06-26/3049332_d10.3.0.patch",
                "#2942975":"https://www.drupal.org/files/issues/2024-06-21/2942975-262-reroll.patch",

Then this patch will not apply, but the patch from #3049332 will apply.

Unfortunatly, I need both; I have both problems.

flyke’s picture

kevinquillen’s picture

Noticed that if you try to load and include layout builder data from a default managed layout, you will get an access denied exception with "The administer node display permission is required". This prevents exporting and attaching default layout data to a response for JSON:API - which you would need to have if the viewed node did not override / add a layout (you'd have to check the content type display and return that).

The access check happens here in core/modules/jsonapi/src/Access/EntityAccessChecker.php:

  /**
   * Get the object to normalize and the access based on the provided entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity to test access for.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   (optional) The account with which access should be checked. Defaults to
   *   the current user.
   *
   * @return \Drupal\jsonapi\JsonApiResource\ResourceObject|\Drupal\jsonapi\JsonApiResource\LabelOnlyResourceObject|\Drupal\jsonapi\Exception\EntityAccessDeniedHttpException
   *   The ResourceObject, a LabelOnlyResourceObject or an
   *   EntityAccessDeniedHttpException object if neither is accessible. All
   *   three possible return values carry the access result cacheability.
   */
  public function getAccessCheckedResourceObject(EntityInterface $entity, ?AccountInterface $account = NULL) {
    $account = $account ?: $this->currentUser;
    $resource_type = $this->resourceTypeRepository->get($entity->getEntityTypeId(), $entity->bundle());
    $entity = $this->entityRepository->getTranslationFromContext($entity, NULL, ['operation' => 'entity_upcast']);
    $access = $this->checkEntityAccess($entity, 'view', $account);
    $entity->addCacheableDependency($access);
    if (!$access->isAllowed()) {
      // If this is the default revision or the entity is not revisionable, then
      // check access to the entity label. Revision support is all or nothing.
      if (!$entity->getEntityType()->isRevisionable() || $entity->isDefaultRevision()) {
        $label_access = $entity->access('view label', NULL, TRUE);
        $entity->addCacheableDependency($label_access);
        if ($label_access->isAllowed()) {
          return LabelOnlyResourceObject::createFromEntity($resource_type, $entity);
        }
        $access = $access->orIf($label_access);
      }
      return new EntityAccessDeniedHttpException($entity, $access, '/data', 'The current user is not allowed to GET the selected resource.');
    }
    return ResourceObject::createFromEntity($resource_type, $entity);
  }

A default layout with block_content entities has a dependency on the entity view display to which it is attached, which will deny access if the current user does not have 'administer node display' permissions.

For our local POC I worked around this for now by patching in this before EntityAccessDeniedHttpException is returned, ran out of time investigating last Friday:

      // Workaround for blocks in default managed layouts.
      // The 'administer node display' is required to view, but that breaks for
      // layout builder blocks.
      if ($entity->getEntityTypeId() == 'block_content' && $access->getReason() == "The 'administer node display' permission is required.") {
        return ResourceObject::createFromEntity($resource_type, $entity);
      }
flyke’s picture

Added issue #3049332 as related because its impossible to use this patch and patch from that issue at the same time.

gaurav_manerkar’s picture

Missing `SectionDataNormalizer` class in #264 patch

artsays’s picture

StatusFileSize
new18.35 KB

Looks like into the latest patch #264 for Drupal Core version 10.3.x
Was missed in creating class two classes SectionDataNormalizer & SectionDataNormalizerTest the result Fatal errors

PHP Fatal error: Uncaught Error: Class "Drupal\layout_builder\Normalizer\SectionDataNormalizer" not found in

I've updated the patch 2942975-10.3.x.patch

kevinquillen’s picture

Note that for Drupal 11 compatibility, the following change has to be made in SectionDataNormalizer, as $supportedInterfaceOrClass has been removed:

  /**
   * {@inheritdoc}
   */
  public function getSupportedTypes(?string $format): array {
    return [
      SectionData::class => TRUE,
    ];
  }

Otherwise, this patch will apply cleanly to Drupal 11 and works. I will try to re-roll this week when I get time.

drupalninja99’s picture

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

drupalninja99’s picture

Bleh sorry posted to the wrong issue ignore me

rpearl’s picture

StatusFileSize
new17.31 KB

Re-roll of the patch for Drupal 10.4.x.

elgandoz’s picture

StatusFileSize
new17.5 KB

Re-roll of #273 with @kevinquillen recommendation from #270.
It applies to core 11.1.x (it should still work on 10.4.x).
I'm currently using it to export LB content with Tome, it works fine.

phenaproxima’s picture

Adding #3532694: Add a command-line utility to export content in YAML format as related, because this issue completely blocks the ability to export Layout Builder data.

mkalkbrenner’s picture

StatusFileSize
new17.57 KB

This issue also blocks https://www.drupal.org/project/issues/default_content_deploy

Anyway, here's a version of patch #274 that could be applied on top of https://www.drupal.org/project/drupal/issues/3049332#comment-16184349

phenaproxima’s picture

Removing the default content export issue, as it has gone in a direction that no longer involves the Serialization module.

kalpanajaiswal’s picture

StatusFileSize
new19.11 KB
kalpanajaiswal’s picture

StatusFileSize
new18.89 KB

Revised and upgraded the patch to support Drupal 10.5.8.

vasike’s picture

New patch for D11.3 upgrades

mkalkbrenner’s picture

StatusFileSize
new13.19 KB

Same like in #277, now basing on #281

mkalkbrenner’s picture

StatusFileSize
new17.98 KB

Ups, forgot a file. Now, same like in #277, now basing on #281

mkalkbrenner’s picture

StatusFileSize
new17.8 KB

First, i forgot a file. Then, the paths were wrong. Again, same like in #277, now basing on #281

alex.skrypnyk’s picture

Re-roll of #274 for 11.3.1

mkalkbrenner’s picture

StatusFileSize
new17.2 KB

voleger made their first commit to this issue’s fork.

voleger changed the visibility of the branch 11.x to hidden.

voleger’s picture

Created MR for 11.x branch based on the #286 patch.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.