Layout Builder created blocks do not clean up when removed from its layout.

Created on 22 March 2019, over 5 years ago
Updated 28 July 2024, 4 months ago

I'm not sure if this is intended or not, but it looks to me like when a layout builder created block (aka non reusuable) is removed from a layout, it removes visually from the layout on the edit or view mode, but the block itself remains in the database, as a non-reusable block. This essentially makes an orphaned block, as it is no longer accessible from the UI. This poses a scalability problem, when over time, a site has the potential of have numerous useless rows in the database.

My proposed solution would be to have a nonreusable block removed from the `block_content` table (and related field tables) when removed from its layout, or at the very least providing a way for a user to remove these blocks from the database.

I'm looking for feedback on this idea before putting time into a solution on it. Any side-effects or challenges that could be raised against this?

πŸ› Bug report
Status

Needs work

Version

11.0 πŸ”₯

Component
Layout builderΒ  β†’

Last updated 2 days ago

Created by

πŸ‡¨πŸ‡¦Canada mark.labrecque Vancouver

Live updates comments and jobs are added and updated live.
  • Blocks-Layouts

    Blocks and Layouts Initiative. See the #2811175 Add layouts to Drupal issue.

Sign in to follow issues

Comments & Activities

Not all content is available!

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

  • πŸ‡¨πŸ‡¦Canada robbdavis

    This is still an issue.

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

    Just ran into this issue as well. Not deleting my page, so my unused block type will have to remain for now. Deleted the block from the page, deleted all the fields from the block type, ran cron, nothing will allow me to get rid of it. :\

  • πŸ‡³πŸ‡±Netherlands seanB Netherlands

    Attached patch implements the suggestion in #7. I think adding a revision ID and langcode is the only way to properly track if blocks are still used in older revisions. Did not work on the tests yet, but this should give a rough idea on what this could look like.

  • last update over 1 year ago
    Custom Commands Failed
  • πŸ‡³πŸ‡±Netherlands seanB Netherlands

    Another patch to fix an issue not tracking blocks for non-affected translations (they still have usage obviously).

  • πŸ‡³πŸ‡±Netherlands seanB Netherlands

    Sorry, my latest assumption was wrong. It was the missing use statement causing the issue.

  • last update over 1 year ago
    29,957 pass, 1 fail
  • last update over 1 year ago
    29,957 pass, 1 fail
  • πŸ‡³πŸ‡±Netherlands seanB Netherlands
    +++ b/core/modules/layout_builder/src/InlineBlockUsage.php
    @@ -36,6 +37,8 @@ public function addUsage($block_content_id, EntityInterface $entity) {
    +        'layout_entity_revision_id' => $entity instanceof RevisionableInterface ? $entity->getRevisionId() : NULL,
    

    Just found this can be a problem when saving new revisions. Usage is added for blocks from layout_builder_entity_presave(). When saving a new revision for an entity the revision ID is set to NULL.

    So this is a nice one, we need to save the blocks first, so we can properly store the block revision IDs in the layout. To track the usage for the blocks though, the layout entity needs to be saved as well.

    I think we might need to move the usage tracking to an after save hook to get this to work.

  • πŸ‡³πŸ‡±Netherlands seanB Netherlands

    This should fix it.

  • πŸ‡¬πŸ‡§United Kingdom chrisscrumping

    Tested #50 and getting an error trying to apply the patch.

    Unable to decode output into JSON: Syntax error                                                                                                        
                                                                                                                                                             
      TypeError: Drupal\layout_builder\InlineBlockEntityOperations::handlePreSave(): Argument #1 ($entity) must be of type Drupal\Core\Entity\EntityInterfa  
      ce, null given, called in /var/www/web/core/modules/layout_builder/layout_builder.post_update.php on line 125 in Drupal\layout_builder\InlineBlockEnt  
      ityOperations->handlePreSave() (line 172 of /var/www/web/core/modules/layout_builder/src/InlineBlockEntityOperations.php).

    I also can't delete a test block after testing layout builder on a dev branch, which is blocking me from moving to another branch without layout builder as I can't import the config until all the blocks are gone.

  • πŸ‡¬πŸ‡§United Kingdom chrisscrumping

    I was able to get passed this by moving the handlPresave inside of the $revision instanceof condition.

    Finally once I had deleted all my test nodes and ran cron I was able to delete the block type (after applying #50).

    As said previously in this thread feels like an issue that could do with a better work around at very least. At least some way of seeing what content is stopping the delete would be useful.

  • last update about 1 year ago
    Custom Commands Failed
  • πŸ‡§πŸ‡―Benin delacosta456

    hi
    if it may help the workaround for me without patching (until stable patch) is

    1. n database run select * from key_value where name = "field.field.deleted" or name = "field.storage.deleted";
    2. in terminal run drush cr
    3. Navigate to admin/config/system/cron and run cron or navigate to admin/config/system/cron/jobs scroll down and at row
      Purges deleted Field API data

      click Run

    hope it's help
    Thanks

  • πŸ‡³πŸ‡ΏNew Zealand atowl

    Hello,
    I wondered where we are with this issue? As I've tried both the MR patch and the patch in #50.

    As i see it the MR works, if you don't have revisioning turned on. It gets triggered once a block is removed, but because there would be a revision of the page, it returns early, not removing the block, and then is not triggered again, to actually clean up any block that was placed, (once revisions have been deleted).

    For the patch in #50, this works.. kinda. Because it makes a new primary key it is truncating the inline_block_usage table. While this doesn't destroy a page layout, you can re-populate this table by saving the page, writing back the usage to the table. BUT if you run cron inbetween that time, it sees that the layout_entity_type and layout_entity_id fields are null, and will start removing the blocks, which then DOES destroy page layouts, like all of them. Not ideal.

    I am wondering if we should start back with the first MR, but hook it into the page save.
    For psuedo code It would
    * Iterate over the blocks associated to that node
    * Skip if included in any revisions
    * Else set layout_entity_type, layout_entity_id to null (layout_builder_cron() cleans this up later)
    * Not reusable block? delete from block_content table also.
    I am not sure however if there are more places to remove the block from if any.

    Now we also would need to do a cron task, (or just on a dbupdate), to remove unused blocks that are are already in the block_content table.
    i think this is as easy as
    * Get id from block_content table
    * If id is not in inline_block_usage table, delete.

    I get the feeling that there should be some bit here that looks into the blob of the node__layout_builder__layout table (or another table) for usage. But unsure which, if any.

    thanks

Production build 0.71.5 2024