Problem/Motivation

See #2946333-42: Allow synced Layout override Translations: translating labels and inline blocks

If you delete a translation with inline blocks, the blocks will not be deleted until the whole entity is deleted.

Proposed resolution

  • Add a langcode column to the table
  • Make sure langcode is correctly set when adding a new usage

Remaining tasks

  • Validate approach.
  • Fix @todos in current patch.
  • Upgrade test

User interface changes

N/A

API changes

N/A

Data model changes

  • A new column on the inline_block_usage database table

Comments

johndevman created an issue. See original summary.

johnwebdev’s picture

Issue tags: +multilingual, +Blocks-Layouts
johnwebdev’s picture

... working on this!

johnwebdev’s picture

Status: Active » Needs review
Issue tags: +Needs tests
StatusFileSize
new5.17 KB
johnwebdev’s picture

Status: Needs review » Needs work

still working on this

johnwebdev’s picture

Status: Needs work » Needs review
StatusFileSize
new7.71 KB
new2.37 KB
johnwebdev’s picture

StatusFileSize
new7.71 KB

Forgot to change the @group on the test back. :P

johnwebdev’s picture

Issue summary: View changes
tedbow’s picture

Status: Needs review » Needs work

Looking good. Thanks for breaking this out.

  1. +++ b/core/modules/layout_builder/layout_builder.install
    @@ -92,8 +92,13 @@ function layout_builder_schema() {
    +      'langcode' => [
    +        'type' => 'varchar_ascii',
    +        'length' => 12,
    +        'not null' => TRUE,
    +      ],
    

    Need a description here. Also probably default looking at other langcode fields.

  2. +++ b/core/modules/layout_builder/layout_builder.install
    @@ -136,3 +141,24 @@ function layout_builder_update_8602() {
    +  $spec = [
    +    'type' => 'varchar_ascii',
    +    'length' => 12,
    +    'not null' => TRUE,
    +  ];
    

    Description and default

  3. +++ b/core/modules/layout_builder/src/InlineBlockEntityOperations.php
    @@ -137,6 +137,18 @@ public function handleEntityDelete(EntityInterface $entity) {
    +   * @param EntityInterface $entity
    +   *   The parent entity translation.
    

    Need to fully namespace @param

  4. +++ b/core/modules/layout_builder/src/InlineBlockUsage.php
    @@ -38,12 +39,21 @@ public function __construct(Connection $database) {
    +      // @todo
    

    Is this @todo done?

  5. +++ b/core/modules/layout_builder/tests/src/Kernel/InlineBlockUsageTest.php
    @@ -0,0 +1,83 @@
    +    $this->assertCount(1, $this->inlineBlockUsage->getUnused());
    

    We should probably confirm the correct block_content_id is returned.

  6. +++ b/core/modules/layout_builder/tests/src/Kernel/InlineBlockUsageTest.php
    @@ -0,0 +1,83 @@
    +    $usage = $this->inlineBlockUsage->getUsage(2);
    

    We could also test

    $this->inlineBlockUsage->getUsage(1)
    

    and both calls to

    getUsage()
    

    before the translation is removed.

  7. +++ b/core/modules/layout_builder/layout_builder.install
    @@ -92,8 +92,13 @@ function layout_builder_schema() {
    +      'langcode' => [
    +        'type' => 'varchar_ascii',
    +        'length' => 12,
    +        'not null' => TRUE,
    +      ],
    

    Needs a description

  8. We could also test removeByLayoutEntity(). it wasn't changed here but it will be removing more rows now.
tedbow’s picture

johnwebdev’s picture

Status: Needs work » Needs review
StatusFileSize
new9.18 KB
new3.88 KB

#9

1. Added description.
2. Fixed.
3. Fixed.
4. Properly passed the language manager with dependency injection and removed @todo.
5. Fixed... however :(

$this->assertSame(['2'], $this->inlineBlockUsage->getUnused());

It looks like ::getUnused() returns an array of IDs as strings, and not integers.

6. To assert the values are not NULL? I could do that, but we could rather expand test coverage on those methods instead.

7. Fixed.

6-8: We have #2992844: Add test coverage for InlineBlockUsage class Not entirely sure what you mean with removeByLayoutEntity() removing more rows though.

Status: Needs review » Needs work

The last submitted patch, 11: 3013340-11.patch, failed testing. View results

tedbow’s picture

Status: Needs work » Needs review
StatusFileSize
new10.12 KB
new968 bytes
  1. re #11.6 Actually looking at getUnused() I don't think we need the extra test coverage here because that is unrelated to this change.
  2. re #8 nevermind.
  3. +++ b/core/modules/layout_builder/layout_builder.install
    @@ -136,3 +142,26 @@ function layout_builder_update_8602() {
    +    'initial' => \Drupal::languageManager()->getDefaultLanguage()->getId(),
    

    I realize now that we can't just set the initial value to the site default language.

    Even though the layouts could not be translated before this patch you could still have entities that where the default language was not the sites default language. So inline blocks used in those entities should have the langcode of the entities.

    But as it is now we have to have an initial value here because langcode column can't be null.

    Maybe langcode should be allowed to be null.

  4. +++ b/core/modules/layout_builder/src/InlineBlockUsage.php
    @@ -38,12 +50,20 @@ public function __construct(Connection $database) {
    +    if ($entity instanceof TranslatableInterface && $entity->isTranslatable()) {
    +      $data['langcode'] = $entity->language()->getId();
    +    }
    +    else {
    +      $data['langcode'] = $this->languageManager->getDefaultLanguage()->getId();
    +    }
    

    If the entity isn't transable we assign the site's default language here. But maybe we shouldn't.

    The entity is not translatable maybe should have null for langcode.

  5. attaching patch that just fixes test failure for now
johnwebdev’s picture

Status: Needs review » Needs work

#13.3 I'd prefer not using NULL to stay consistent, with that being said the current approach for the update is wrong either way so setting this back to NW.

Currently not working on this.

tedbow’s picture

Status: Needs work » Needs review
StatusFileSize
new5.18 KB
new11.23 KB
  1. @johndevman yes I agree we shouldn't set this to NULL.
    This patch sets the initial value to LanguageInterface::LANGCODE_NOT_SPECIFIED

    And then attempts to update all the records

    Since there could be thousands of records I didn't want to have to load all the entities.
    Also would loading the entities even work because it would give us the latest revision and this might not be the revision that where the inline block was used which could have a different language value(I think).

    This also has to consider config entities like entity view displays which do have a language returned.

  2. +++ b/core/modules/layout_builder/src/InlineBlockUsage.php
    @@ -38,12 +50,20 @@ public function __construct(Connection $database) {
    +    if ($entity instanceof TranslatableInterface && $entity->isTranslatable()) {
    +      $data['langcode'] = $entity->language()->getId();
    +    }
    +    else {
    +      $data['langcode'] = $this->languageManager->getDefaultLanguage()->getId();
    +    }
    

    I think regardless of whether entity is translatable or not
    $data['langcode'] = $entity->language()->getId();
    will give use the correct value since language() is on EntityInterface and it should always return a language object.

johnwebdev’s picture

#15.1

I decided to try it out:

  1. I added a new language (Swedish)
  2. I enabled content translation for Basic page
  3. I create a new node (nid: 1) in English.
  4. I resaved the node, to create a new revision
  5. I now have 2 revisions.
  6. I change the language to Swedish and save
  7. When I go to revisions, there is only one revision displayed (current)
  8. I cannot revert back to a revision with English language.
  9. If I now create an English translation, I can see the revisions that was done earlier when I created the node as english.
  10. If i try to revert to one of those revisions it crashes. :P
  11. If I create some more revisions, I can revert back to those, but not the revisions created before the language change.

With that being said, I'm not entirely sure what the expected behaviour of Drupal is when doing the steps above. Is this a bug?

2 Yep. Good change.

tedbow’s picture

  1. #16 @johndevman thanks testing. I followed you steps and got the same error, which read "The default translation flag cannot be changed" which looks like it comes from here \Drupal\Core\Entity\ContentEntityBase::onChange()

    I could find an existing issue. It seems like bug just because of the fatal error but it is always a pretty edge case series of steps. But not related layout builder but maybe tells as far as what might not be possible.

    I think the problem would be

    1. user creates english node.
    2. user creates layout override with inline block creating new revision
    3. user changes node to spanish
    4. layout_builder_update_8701 runs
    5. since node is currently spanish this will be added to the inline_block_usage_table
    6. user creates an english translation
    7. user deletes the english translation
    8. This would delete the revision that use the line block but not the inline_block_usage row or the block_content entity.(need to test to confirm)

    This series of step leaves an orphaned non-reusable block_content entity that isn't referenced anywhere which is suppose to happen
    it is not horrible because:

    1. it would only happen to entities before this update where the language is set and then changed with an inline block being added before the change
    2. the block would still get deleted when the entity is deleted completely
    3. it won't happen for inline blocks after this update because will be adding the langcode as we go.

    I am trying to think of situation where you could delete a translation and the inline block is deleted when is shouldn't be(as opposed to not deleted when it should be) but I can't think of one.

  2. Here is the start to an update test. I had to make the a fixture with layout builder enabled for the inline_block_usage table to be there. I s there a way to do this without an install fixture?
    I made a patch without the fixture for review
tim.plunkett’s picture

Status: Needs review » Needs work

NW for more tests

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.

tim.plunkett’s picture

Status: Needs work » Postponed

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.

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.

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.

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.

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.

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.

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.

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.

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.