Problem/Motivation

Drupal 8 has an Entity Reference field that allows you to reference block instances (config) or custom blocks (content); but it does not allow you to reference both at the same time. Also, a block instance (config) is tied to a theme, where a piece of content is not. This creates an odd relationship where content is dependent on a theme.

Proposed resolution

Possible Solutions

  1. Formatter
    If you create a reference field to a block instance (config) and you reference an instance of a custom block (content) Drupal 8 doesn't render anything. We could simply create a formatter for custom blocks (content) that are block instances (config) to be rendered properly. In this formatter we'd have an option to specify the view mode of a custom block (content). However, this does not resolve the problem where a block instance (config) is tied to a specific theme. You also have to have a list "Disabled" blocks in the admin which seems like a bad user experience.
  2. Combo Reference Field
    We could ditch the built-in reference field completely and create our own that allows you to reference either a block instance (config) or a custom block (content) for each delta in the field. This allows a single field to have either or for each value. This would be somewhat similar to Dynamic Entity Reference. However, this still does not get around the theme and block list issue.
  3. Block Instances
    Perhaps the "best" option would be to not reference block instances (config) or custom blocks (content) at all, but instead let you create instances inline. This is similar to what's been done in Display Suite. When you create a "Block Field" it's a completely new instance of a block and it allows you to specify the config of the block (it's similar to the "Place Block" modal). This allows a block instance to be created without tying the block instance to a specific theme. It also keeps the block list clean and allows the user to have different block config on a per-reference basis. Display Suite stores these block instances as a custom config entity (which makes sense for them). However, for us; it's not as clear. On one hand we could store it as custom config and then just allow the References field to reference the config. This is a little odd because we'd have a single piece of content that relates to a single config entity. This would probably become a huge mess of the config. The only alternative is to serialize the config in the database. This isn't ideal, but it seems nearly impossible to normalize the config and the alternative of storing the config as a config entity seems like a worse solution.

    Remaining tasks

    1. Decide on Solution
    2. Open 8.x branch
    3. Start Creating Drupal 8 issues

    User interface changes

    Many

    API changes

    Complete Overhaul

    Data model changes

    Probably extensive.

    Original report by sachbearbeiter

    hi,

    will there be a D8 port of "Block reference"?

    Thansk and regards sb

Comments

rudiedirkx’s picture

Maybe, some day, probably. I have no plans at all to port anything to D8. I'm not starting with D8 until my office starts doing D8 websites.

You're very welcome to give it a go =)

davidwbarratt’s picture

Doesn't Drupal 8 let you reference blocks with an Entity Reference field?

davidwbarratt’s picture

It looks like in Drupal 8, you can create an Entity Reference field and reference either Custom Blocks (content entity) or Plugin Blocks (configuration entity), but not both.

sachbearbeiter’s picture

Does someone has an idea how to show the complete referenced entity without this module? Do we still need this module because of the remark of #3?

rudiedirkx’s picture

I can reference Block entities, and they have a Rendered entity display format.

Output:

<div id="block-bartik-branding" class="contextual-region clearfix site-branding block block-system block-system-branding-block">
  <a href="/" title="Home" rel="home" class="site-branding__logo">
    <img src="/core/themes/bartik/logo.svg" alt="Home">
  </a>
  <div class="site-branding__text">
    <div class="site-branding__name">
      <a href="/" title="Home" rel="home">
        Whatever 8
      </a>
    </div>
  </div>
</div>

So that seems to work fine. No need for this module in D8?

davidwbarratt’s picture

The only problem that I see is around Custom Blocks. You can't reference it until you place the block in "Disabled" (or in some region), but even if you do that you can't reference it. The only solution I can see right now is to have two fields (one for config blocks and one for custom blocks), not the cleanest solution; but it works.

I suppose we could make a custom entity reference field that allowed you to specify either. This would allow you to specify the custom block without having to actually place it on the page.

davidwbarratt’s picture

Alternatively, it would probably be a lot less invasive if we just figured out how to render a custom block when you use a config block reference field. It would require people to add the block to "Disabled" but that's the same process we have now with Bean.

rudiedirkx’s picture

You're right. I picked a random block instance, but blocks are much weirder in D8, so just existing is not enough anymore. They're really part of a theme now =(

I only have Block in the entity reference type dropdown, not Custom Block.

I'm definitely not up to it. You wanna have a go?

davidwbarratt’s picture

Title: Block reference: Do you plan a Drupal 8 port » Drupal 8 Port (if needed?)
Version: 7.x-2.0 » 7.x-1.x-dev
Issue summary: View changes
davidwbarratt’s picture

Title: Drupal 8 Port (if needed?) » Drupal 8 Port
davidwbarratt’s picture

Issue summary: View changes
davidwbarratt’s picture

Issue summary: View changes
davidwbarratt’s picture

I've updated the issue summary with the solutions that I've come up with, please add/modify them if you can think of anything else. If a maintainer could choose a direction that would be incredible. :)

davidwbarratt’s picture

Issue summary: View changes
rudiedirkx’s picture

Fantastic summary, great work!

I know too little about D8 blocks to choose the best method.

In D7 you also have blocks and block instances, sort of, but some data (like title) is shared between them. Other data is theme specific (region, weight etc). All blocks exist in all themes, whether they're used (placed) or not. The best reference (2.x) references a block (module + delta) and ignores the theme, because there's no relevant theme-specific data.

How does D8 do this? There's a block type thing now, right? And then block instances, and then per-theme instances?? How would you reference a specific block across all themes? In D7 that would be user-online, which exists for every theme. Does D8 have this too? Or is module-delta now MyBlockType and it can have instances with arbitrary ids?

In the D8 block interface, I can create new blocks on the fly, per theme, multiple per type (?). Would we need that kind of instance, or just the type? Is just the type specific enough? (I imagine 1 type could make 1 block per user, or something semi-structural like that.)

Like I said, I'm a D8 n00b. I haven't done any block creating yet. I have used the block interface, which seems cool, and very different.

rudiedirkx’s picture

This is how I image D8 block hierarchy works:

1. mymodule.module creates a "Server Status" block type: ServerStatusBlock
2. mymodule.module creates several Server Status blocks: ServerStatusBlock-wheezy, ServerStatusBlock-lollipop, ServerStatusBlock-icloud
3. Themer creates (and places?) Server Status block instances in theme Seven: seven_server_status_wheezy_big, seven_server_status_wheezy_small, seven_server_status_lollipop_small, seven_server_status_icloud_small etc
4. Idem for another theme: bartik_big_server_status_lollipop, bartik_big_server_status_wheezy etc

I know 1, 3 and 4 are possible. I don't know about 2, but I thought that was a very cool D8 addition.

In that case, what would the right reference be? 1, 2 or 3/4? I'd say 2: specific block instance, theme agnostic. The problem is that 1 and 2 don't have any block settings, because the real instance doesn't even exist.

rudiedirkx’s picture

They're called 'derivatives', The system menu block uses it. I guess the block's 'id' + the optional derivative's index/key make a specific block instance that makes a good refererence. I'd have to look at the block UI forms to see what exactly makes a block.

I'm not putting any real work into this any time soon though. If you want to, please do. When you have something, you can have the 8.x branch =)

berdir’s picture

Derivatives are just plugins, as a consumer of plugins, you don't have to care about that. They behave and work exactly like other block type plugins. Block content/custom block entities are exposed as a plugin derivate.

See the related core issue: #2530686: Add entityreference formatter option to "ignore access checks"

I don't think it makes sense to reference instances since they're specifically tied to a theme, region and have visibility conditions that you have to work around as written there.

As suggested there, I think what makes most sense would be to base this on the plugin project (https://www.drupal.org/project/plugin) which offers a field type that stores a plugin ID and configuration for it.

rudiedirkx’s picture

What's a "Plugin ID" in this case? The block type + derivative? In the case of system menu's, Blockreference would have to know which menu to render, and that's not part of the block config. Blocks that don't have derivatives have another ID format, I'd think.

Like I said, I know very little about D8.

rudiedirkx’s picture

A block ID seems to be Plugin:Derivative, or Plugin if none exist. For example system_menu_block:admin and views_block:who_s_online-who_s_online_block have derivatives and devel_execute_php doesn't.

berdir’s picture

Yes. As a user of plugins, you do not need to know that derivatives even exist. the plugin ID is always enough to reference a plugin, whether it is a derivative or not is not relevant for you.

If you ask a a plugin manager for the list of plugins/plugin definitions, you get them all. Derivatives are just a helper to expose the same plugin class as multiple plugins, the same would be possible using an alter hook. You just have to worry about selecting a certain plugin, allowing to configure it using its configuration form, store that and later create a plugin instance with that configuration and do whatever that plugin type is designed to do (In the case of blocks, it's rendering a block).

rudiedirkx’s picture

Sounds easy. I'll check out Plugin some time to see how BR can build on top of that.

davidwbarratt’s picture

I've opened #2623892: Workaround for saving Block config which should resolve my issue. :)

james.williams’s picture

Given that #2533048: Add a block plugin field formatter has been added to the Plugin module, I'm not sure what BR would do on top of / instead of that? It would seem (though I haven't tested) that Plugin module's field type allows referencing a block, and then formatting it. Core's entity reference (ER) can reference block config entities (i.e. blocks placed in a region), which is pretty much exactly what BR does otherwise too.

So either BR's use case is now covered by Plugin and ER, or BR needs to find a new niche in D8? Perhaps referencing block config entities (i.e. placed blocks) without all the access checks that using ER would do. (Visibility conditions are implemented as entity access checks, but also placing a block into the disabled region effectively unpublishes it, so it's no longer going to be accessible.) Or is there a case for only allowing blocks placed in specific themes/regions? I suspect that could still be implemented by ER + a view for selection, filtered to theme/region, so I'm not sure even that is an open problem space!

So just to be clear: I believe everything BR currently does is covered by Plugin module and/or core entity reference (at least once the core issue #2532968: Block plugin forms assume they are top-level is fixed anyway). Therefore, blockreference is either just not needed in D8, or needs to find its own problem space to solve.

asgorobets’s picture

Block Field seems to be doing what is needed from Block instance as a field perspective, should we list Block Field as recommended module for Drupal 8? https://www.drupal.org/project/block_field

rudiedirkx’s picture

Such a waste, all these D8 modules with different namespaces. jrockowitz could have had this one.

Anyway, block_field seems to do this, so I think BR is obsolete. If anyone verifies that, I'll update the project page.

anybody’s picture

Anyway, block_field seems to do this, so I think BR is obsolete. If anyone verifies that, I'll update the project page.

6 years later and running into this issue again, I'm confirming this @rudiedirkx! ;)