Problem/Motivation

In Drupal 7, blocks are not fieldable entities. Because blocks are not entities, we cannot add fields to them. As a result, there are not easy ways to add fields like images to blocks without using custom modules.

Additionally, if blocks were entities, we would be able to:

- Promote consistency in the Drupal API
- Simplify the process of adding fields like images to blocks
- Potentially remove the need for custom modules to add fields to blocks and/or create blocks for nodes
- Redo or improve implementation of hook_block

Proposed resolution

In Drupal 8, make all blocks fieldable entities. To do this, a block_id is added to the block table. The new block_id field is used by the Field API to identify the block in question.

As part of the proposed change (last patch is #98 ), the block table is refactored into {block} and {block_instance}. One advantage of the block_instance table is that it can be used to support multiple instances of the same block within the same theme.

Remaining tasks

1. Set a plan of attack for how module blocks and custom blocks should differ in the database (#129 ).
2. Review the block_api module (http://drupal.org/project/block_api) noted on #110 and Bean module (http://drupal.org/project/bean) and see if either should be a starting point for a new patch.
3. (If proceeding with previous patch) Debug test failures using patch at #98 as a starting point
4. Address limitations of hook_block_configure() identified in #114.
5. Address usability concerns:
#1164702: “Block” has no meaning. (New users challenged by use of the term 'block')
#1164718: Improving the usability between "custom block" and "content"
#1164712: Users expect to preview blocks before saving changes

User interface changes

Addition of a manage fields/display fields tab for blocks.

There needs to be a decision reached about whether to separate out the config and content in a block (#111 ).

API changes

Potentially rewrite block module to do less direct querying of the database and to instead use the API (#127 ).

Original report by catch

I think we should consider changing custom blocks to be fieldable items, there's a few reasons for this:

1. Like making node->body a field, we can make the {boxes} table tidier
2. There would finally be a nice way to add things like images as blocks
3. We could possibly replace entire modules like http://drupal.org/project/nodeasblock via nodereference
4. Longer term, it might be a possible route towards replacing some implementations of hook_block - so to take views as an example, you could create block bundle which has viewfield attached to it, then the workflow would be:

'Add block'
choose 'view'
choose the view / display you want to show in the block.

As opposed to admin/build/block and find the view you defined in the disabled region.

Not given that a lot of thought, but simply replacing the textarea storage with a field and allow for fields to be attached to blocks would be a big change for one patch anyway.

CommentFileSizeAuthor
#98 block_fields.patch108.94 KBcatch
#96 block_fields.patch108.93 KBcatch
#94 block_fields.patch106.52 KBcatch
#93 430886-93-eojthebrave-fieldable_blocks.patch103.39 KBeojthebrave
#93 430886-93-eojthebrave-fieldable_blocks.patch187.67 KBeojthebrave
#91 430886-91-block_fields.patch104.68 KBPasqualle
#89 block_fields.patch104.27 KBcatch
#87 430886-87-eojthebrave-fieldable_blocks.patch102.61 KBeojthebrave
#84 430886-84-eojthebrave-fieldable_blocks.patch101.61 KBeojthebrave
#82 430886-82-eojthebrave-fieldable_blocks.patch101.95 KBeojthebrave
#79 430886-79-eojthebrave-fieldable_blocks.patch101.95 KBeojthebrave
#74 430886-74-eothebrave-fieldable_blocks.patch101.5 KBeojthebrave
#71 430886-71-eojthebrave-fieldable_blocks.patch102.51 KBeojthebrave
#70 430886-70-eojthebrave-fieldable_blocks.patch102.5 KBeojthebrave
#67 430886-67-eojthebrave-fieldable_blocks.patch93.72 KBeojthebrave
#63 430886-61-eojthebrave-fieldable_blocks.patch88.18 KBeojthebrave
#61 430886-56-eojthebrave-fieldable_blocks.patch56.04 KBeojthebrave
#56 430886-56-eojthebrave-fieldable_blocks.patch56.04 KBeojthebrave
#53 430886-53-eojthebrave-fieldable_blocks.patch53.42 KBeojthebrave
#47 430886-47-eojthebrave-fieldable_blocks.patch49.34 KBeojthebrave
#44 430886-42-eojthebrave-fieldable_blocks.patch35.61 KBeojthebrave
#42 430886-42-eojthebrave-fieldable_blocks.patch35.61 KBeojthebrave
#40 Picture 4.png68.04 KBjrglasgow
#39 Picture 3.png52.66 KBjrglasgow
#35 430886-35-eojthebrave-fielable_blocks.patch34.68 KBeojthebrave
#32 430886-32-eojthebrave-fieldable_blocks.patch34.68 KBeojthebrave
#26 430886-26-eojthebrave-fieldable_blocks.patch32.32 KBeojthebrave
#24 430886-24-eojthebrave-fieldable_blocks.patch29.61 KBeojthebrave
#16 430886-15-eojthebrave-fieldable_blocks.patch15.36 KBeojthebrave
#15 369409-6-eojthebrave-theme_block_to_block_module.patch5.53 KBeojthebrave
#13 eojthebrave-fieldable_blocks.patch6.64 KBeojthebrave
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

webchick’s picture

catch asked for an early assessment. To me, this makes tons of sense, and promotes consistency in our APIs. I've also far longed for a file upload field on blocks so that I didn't need to go and create a dummy node just to reference an image on my site. (I also have a whole rant about lack of block previews, but that's not for this patch. ;))

+1 for cleaning up the box table as well. In fact, unless I'm wrong, I don't think we need the box table at all after this, assuming "description" also gets made into a field, along with body.

The only tricky thing is "block.title" ... currently this can be set per-theme, and I'm not sure anything in Field API will deal with that currently.

bjaspan’s picture

Component: field system » block.module

Offhand I don't have a problem with this, though it is not a "field system" issue so I'm changing it to block.module.

Blocks do not currently have the concept of a "content type"/"bundle". Should all blocks share a single set of fields, like users currently do? Or should every block potentially have its own set of fields? If the latter, each block's bundle name would have to be unique because Field API does not have the concept of a per-object set of fields (I argued for this during design but everyone thought I was crazy).

Incidentally, I do not see any reason that fields should be limited to user-defined blocks. If we make $block->content renderable (perhaps we already have?) there is no reason I can think of we couldn't add fields to module-defined blocks.

nevets’s picture

Component: block.module » field system

I am missing something here, currently I tend to use custom blocks for displaying something that is not represented by a node or view. I just dump the html in the textarea and I am good to go. This seems to remove that capability and I am not sure that is a good thing.

catch’s picture

Component: field system » block.module

@bjaspan: I could go either way on that. My initial feeling is that if we make blocks fieldable, then we cut out a large number of the reasons to have hook_block() at all (instead you expose your module's stuff as a field and people can attach it to custom blocks if they want).

With block bundles - yes I think it'd make sense to support different bundles, but not sure how that would work yet though.

@nevets: the most basic setup would still be a block with a textarea. However if you want to have an image in your custom block, you've currently got no way to attach it (and etc.) - so this certainly wouldn't take the basic implementation away.

yched’s picture

Crosspost, refiling into 'block.module'.

nevets : you wouldn't lose that. What is discussed here would make that textarea be a 'field'.

As Barry pointed, the first design decision is probably 'what would be the set of bundles ?'. Each block being its own bundle probably makes sense.

bjaspan’s picture

Note that we currently have no CCK UI for attaching fields to arbitrary fieldable entities. Karen said it wouldn't be that hard to generalize the node-based UI for any fieldable type, and I don't see why it would, but we do not have it yet. So there will be no UI to actually add fields to blocks.

fgm’s picture

The problem (?) with having each block be its own bundle could be the fact that would only be one object instance for each bundle, which seems wasteful.

OTOH, maybe having instances be cached versions (per-user, per-role... depending on the block caching mode) might make sense.

dropcube’s picture

A custom block (what is stored in {boxes} table), is just a piece of content displayed in a region, under certain conditions (visibility, etc...). So, if we have some content types, whose nodes can be put in any region, then we will have the same, and will be reusing all we have for nodes.

In addition to the build modes currently core defines (full, teaser, rss, ...), a node can be built as a block. Think, for example, if you could configure what fields are displayed in teaser view, in full view, and in block view!!!

In the other hand, modules could export their stuff as fields, users can attach that fields to nodes, and build the nodes as block, in the regions they prefer.

With the 'nodes built as blocks' approach, block bundles are just the content types.

eojthebrave’s picture

Lets say, hypothetically speaking, a guy wanted to try and tackle this. In order to have fieldable blocks, and to allow each block to have it's own set of fields we're going to need a "machine_name" for each block. See @bjaspan's comment in #2. Is this something that should be configurable ala node.type or vocabulary.machine_name or could we just do something like $block['machine_name'] = $block['module'] . '_' . $block['delta'];

catch’s picture

Issue tags: +Fields in Core

I don't think it needs to be configurable - there's not much of a use-case for using that machine name elsewhere.

yched’s picture

Plus, $block['module'] . '_' . $block['delta'] is already used as an id for the block everywhere else.

eojthebrave’s picture

Okay, did a little poking around and here's what I'm thinking at the moment. Totally new to the whole attaching fields so bear with me.

Add a machine readable name to all blocks in _block_rehash() by combing $module and $delta like so.

$block['block_machine_name'] = $module . '_' . $delta;

Implement block_fieldable_info() and block_field_build_modes(). Each block becomes it's own bundle.

Add field_attach_create_bundle() for new blocks and field_attach_rename_bundle() for updated blocks in _block_rehash() and field_attach_delete_bundle()

block_admin_configure() gets field_attach_form() and block_admin_configure_validate() gets field_attach_validate_form()

Then in block_admin_configure_submit() implement

field_attach_presave()
field_attach_insert() for new blocks
field_attach_update() for updated blocks

Implement field_attach_load() in _block_load_blocks()

Add something like $block->content += field_attach_view() in _block_render_blocks()

Need to add field_attach_delete() somewhere, maybe in _block_rehash()

Update blocks so that body and title are fields.

Write tests

Cross fingers!

Sound reasonable?

eojthebrave’s picture

Here is a first pass at this, hoping to get some comments as to wether or not this is going in the right direction.

Currently this patch makes custom blocks (those defined be block.module) fieldable. Each block has it's own bundle instance. When a new block is created a field named block_body is automatically attached to the new instance. I had originally been thinking of making all blocks fieldable, but I think this is a better approach. See @catch's comment about making custom block's fieldable and then modules can expose their data as fields which can be attached to any custom block rather then having to implement hook_block()

The way it works currently you loose the ability to add body copy to the block when first creating it. You have to create the block and then edit it in order for the block_body field to show up. Adding/Editing field content works as expected, I have not yet done anything as far as making the new block_body field display as part of the block, though this should be pretty trivial.

One thing that could use some thought is how/where the field_attach_form() function is called. Currently this is being done in a hook_form_FORM_ID_alter implementation, it could however be done in hook_block_configure() if we modify that function to use $form and $form_state parameters. Without that modification the field_attach_form() function will attach the fields in $form['block_settings']['#fields'] instead of $form['#fields'] which confuses the Field API.

Assuming this is a good approach the next step will be to remove the current block.body code including the {box} table and provide an update path for existing blocks. Figure out the display/rendering stuff, and then write some tests.

lilou’s picture

Status: Active » Needs review
eojthebrave’s picture

Everything should be working now.

Giving the testing bot a crack at this. I expect 2 failures.

This is a result of this in testBoxFormat():

// Confirm that a user without access to Full HTML can not see the body field,
// but can still submit the form without errors.
$block_admin = $this->drupalCreateUser(array('administer blocks'));
$this->drupalLogin($block_admin);
$this->drupalGet('admin/structure/block/configure/block/' . $bid);
$this->assertNoText(t('Block body'));
$this->drupalPost('admin/structure/block/configure/block/' . $bid, array(), t('Save block'));
$this->assertNoText(t('Please ensure that each block description is unique.'));

// Confirm that the box is still being displayed using configured text format.
$this->assertRaw('<h1>Full HTML</h1>', t('Box successfully being displayed using Full HTML.'));

The current block system allows users to edit a block even if the body of the block uses for text format that they are not allowed to use. It does this by disabling the blocks body field for that edit.

Converting the body to a field means that users can still edit the block body it will just change the text format to a filter that the current user has permission to use. From what I can tell nodes act the same way. This could be a problem in the event that the administrator defines a block with custom php code in the body but still wants to allow users who do not have the php filter permission to make changes to the block setting.

I'm not really sure how to proceed with this. Thoughts?

Also, now that Fields UI is in core this patch should probably also provide a UI for adding fields to a block.

eojthebrave’s picture

Grr, wrong patch.

yched’s picture

+      'full' => t('User account'),

Doesn't sound right :-)

 /**
+ * Implement hook_form_FORM_ID_alter().
+ */
+function block_form_block_admin_configure_alter(&$form, &$form_state) {

Why don't we do this in the original form ? Isn't it defined in block.module ?

+    $field_form = array();
+    $field_form_state = array();
+    field_attach_form('block', (object) $block, $field_form, $field_form_state);

Dunno for sure, but this sounds weird. Not sure how this would affect field validation. Did you check that field errors are correctly reported ? (with a 'required' field, or a number field with min and max values...)

-    <?php print $content ?>
+    <?php print ($content) ?>

Hm :-). Did you mean render($content) ?

yched’s picture

+  $ret = array('#finished' => 0);
...
+  $ret = array('#finished' => 1);

Both lines are not needed. When an update function is not multipass (we sometimes say 'batched', but they are all batched, of course), it doesn't need to worry about #finished.
I did not really consider whether that update being single-pass is OK, though. I guess there are little chances that a site defines enough custom blocks to make this timeout.

eojthebrave’s picture

Status: Needs review » Needs work

@yched, thanks for the feedback.

/**
+ * Implement hook_form_FORM_ID_alter().
+ */
+function block_form_block_admin_configure_alter(&$form, &$form_state) {

See my comment in #13 about this. While the form is built in the block.admin.inc it is built with the assumption that the fields there are common to ALL blocks, this patch is intended to only make custom blocks fieldable. The function that builds the form invokes hook_block_configure($delta), which is where most modules currently add their custom fields to the block. However, since the hook implementation does not pass the full $form object or the $form_state it doesn't work to use field_attach_form there. The '#fields' element returned by field_attach_form needs to be at the top level of your $form array in order for it to do it's thing. Anything you return from hook_block_configure() is merged into $form['block_settings'] and not the top level.

Hope that helps clarify why it was done this way.

+    $field_form = array();
+    $field_form_state = array();
+    field_attach_form('block', (object) $block, $field_form, $field_form_state);

After doing some testing with this you're right, it only sort of works. It works for required fields, and it works in the case that you have an integer field with a string in it. However, if you have an integer field with a min/max and you enter a value outside that range it fails. This should be an easy fix though.

Also, just FYI, the above method was copied from user.module which does it in the same way, and exhibits the same symptoms outlined above. This should probably be fixed.

With regards to the hook_update_N() function. I agree that it is pretty unlikely that any site would have enough custom blocks to warrant using batch here. I'll remove the batch related code that wasn't really doing anything anyway unless someone else wants to chime in and prove that it would be worthwhile to use batch here.

I will try and re-roll with these changes and the other minor fixes shortly.

yched’s picture

While the form is built in the block.admin.inc it is built with the assumption that the fields there are common to ALL blocks, this patch is intended to only make custom blocks fieldable

Naive question 1: couldn't we just call field_attach_form there, within a if (block is custom) conditional ?
Naïve question 2: why do we restrict to custom blocks at all ? ;-) Bjaspan raised the question in #2, and I don't think it's been answered.

Also, just FYI, the above method was copied from user.module which does it in the same way, and exhibits the same symptoms outlined above. This should probably be fixed.

Not quite. Field validation on users is broken for different reasons (#549726: user_profile_form_validate() not called when submitting user_profile_form). IIRC, user module uses similar code this just to get a list of form elements that are added by fields and should therefore be neglected in the automatic save of any custom addition into $user->data. This is sick, BTW, this should be done using field_info_instances().
Here, you use $field_form and $field_form_state just to put fields elements in a separate fieldset.
- Is this *really* needed ?
- If you do that, you need to update $form['#fields'][$field_name]['form_path'] to array(''block_fields'', $field_name). See the PHPdoc for field_attach_form()
- It looks like, at least, $form_state should be the same. Some widgets might put stuff in there, we don't want to lose that data.

yched’s picture

Forgot about $form['#pre_render'] and $form['#extra_fields'], written by field_attach_form() (new from the Field UI patch)
So, having fields live under a fieldset wight really mess up fields and 'extra fields' (non-field elements that can be reordered through Field UI) reordering really messy, I do think we should avoid that...

yched’s picture

Side note : with #556390: Vertical Tabs on block visibility settings, the fieldset around block content (title, body, fields) shouldn't be needed anymore

sun’s picture

Issue tags: +i18n sprint

Tagging.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
29.61 KB

Okay, new approach. This patch makes all blocks fieldable, not just custom blocks. Doing it this way should get rid of any field validation issues encountered with the previous patches.

In order to make blocks fieldable I needed to add a 'block_id' to the block table. The new block_id column is an integer, used by Field API to identify the block entity in question. We can't just use the bid column because there are multiple rows which are essentially the same block just in different themes.

Added a block_save() function that can be used to save a block to the block table and will either generate a new block_id if appropriate or re-use an existing one if the block already exists in another theme.

Giving the test bot another go. I still expect 2 failures (see comment #15), which I could use some advice on how to handle.

Finally, there is now the entity loading stuff in HEAD #460320: Standarized, pluggable entity loading (nodes, users, taxonomy, files, comments), I'm not entirely sure yet how that effects blocks since the block module does not have any block_load or block_load_multiple functions. Thoughts?

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

Hmm. Lets see how this one does.

I removed some tests from filter.test testFilterHooks that were dependent on a custom blocks body and format fields. Which with this patch, no longer exist. I'm not 100% sure that these tests need to be replaced since there are still tests in place to verify that the appropriate hooks are called. The removed tests were just testing the filter delete hooks on a block making sure that if the default filter was deleted that the block body/filter fields were updated appropriately.

eojthebrave’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

re #24 block_id:
This would actually be alleviated by #368082: Non-numeric object ids and revision ids. But until that one is tackled (if it ever is), I guess fieldable blocks will need a numeric id common to all the themes the block appears in.
Not sure of the best way to avoid the unfortunate clash with bid (unique for each block in each theme), though.

dropcube’s picture

+++ modules/block/block.admin.inc
@@ -189,15 +195,21 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) {
+  $edit = db_query("SELECT block_id, pages, visibility, custom, title FROM {block} WHERE module = :module AND delta = :delta", array(
     ':module' => $module,
     ':delta' => $delta,
   ))->fetchAssoc();

Consider using db_select query builder.

+++ modules/block/block.admin.inc
@@ -254,11 +267,22 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) {
+    $edit['block_machine_name'] = $module . '_' . $delta;
+    $edit = (object) $edit;
+    field_attach_load('block', array($edit->block_id => $edit));
+    $edit = (object) $edit;
+    field_attach_form('block', $edit, $form, $form_state);
+    $edit = (array) $edit;

Try fetching $edit as object and work with object directly instead of converting it to object/array several times.

+++ modules/block/block.admin.inc
@@ -365,10 +393,18 @@ function block_admin_configure_validate($form, &$form_state) {
+  $edit = (object) $form_state['values'];
+  $edit->block_machine_name = $edit->module . '_' . $edit->delta;
+  field_attach_form_validate('block', $edit, $form, $form_state);

Consider using a variable name in context. Maybe $block instead of $edit.

+++ modules/block/block.admin.inc
@@ -365,10 +393,18 @@ function block_admin_configure_validate($form, &$form_state) {
+    $edit = (object) $form_state['values'];

The same.

+++ modules/block/block.admin.inc
@@ -431,7 +469,7 @@ function block_admin_configure_submit($form, &$form_state) {
+  return block_admin_configure($form_state, 'block_');

Seems like a hack. Would be good to add some inline comments to explain what's being done.

+++ modules/block/block.admin.inc
@@ -448,30 +486,30 @@ function block_add_block_form_validate($form, &$form_state) {
+    'visibility' => (int) $form_state['values']['visibility'],
+    'pages' => trim($form_state['values']['pages']),
+    'custom' => (int) $form_state['values']['custom'],

Is required to explicitly typecast that ?

+++ modules/block/block.module
@@ -560,6 +586,34 @@ function block_list($region) {
+ * @todo document
+ */
+function block_save($block) {

Add PHP docs.

+++ modules/filter/filter.test
@@ -787,33 +787,10 @@ class FilterHooksTestCase extends DrupalWebTestCase {
-    // Add a new custom block.
-    $box = array();
-    $box['info'] = $this->randomName(8);
-    $box['title'] = $this->randomName(8);
-    $box['body'] = $this->randomName(32);
-    // Use the format created.
-    $box['body_format'] = $format;
-    $this->drupalPost('admin/structure/block/add', $box, t('Save block'));
-    $this->assertText(t('The block has been created.'), t('New block successfully created.'));
-
-    // Verify the new block is in the database.
-    $bid = db_query("SELECT bid FROM {box} WHERE info = :info", array(':info' => $box['info']))->fetchField();
-    $this->assertNotNull($bid, t('New block found in database'));

If we are going to remove it, won't would be good to replace it with other test case ?

I'm on crack. Are you, too?

dropcube’s picture

Also I get this error when installing (after applying the patch). Not sure if it due to my php config...

Warning: Call-time pass-by-reference has been deprecated; If you would like to pass it by reference, modify the declaration of field_attach_submit(). If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file in \drupal7-cvs\modules\block\block.admin.inc on line 405 Fatal error: Exception thrown without a stack frame in Unknown on line 0 
eojthebrave’s picture

Status: Needs work » Needs review
FileSize
34.68 KB

@dropcube, thanks for the feedback.

Consider using db_select query builder.

This is how it was before, I simply added an extra field to the list of those returned. Leaving as is for now.

Try fetching $edit as object and work with object directly instead of converting it to object/array several times.

Done, good catch.

Consider using a variable name in context. Maybe $block instead of $edit.

Done, I had originally thought about doing this, but the code was using $edit already so I just stuck with that. However, I think that changing it to $block makes the code much more readable, and have done so now.

Seems like a hack. Would be good to add some inline comments to explain what's being done.

Done

Is required to explicitly typecast that ?

Probably not. However, the code that is is replacing does the explicit typecasting so there may be a reason that I'm unaware of. Leaving as is for now.

Add PHP docs.

Done

If we are going to remove it, won't would be good to replace it with other test case ?

See my comments in #26. I'm not sure that we need to replace it. FWIW, block.module is the only thing in core using the filter format delete hook and with this patch it doesn't need it anymore.

Pass by reference error should be fixed.

More tests should pass now, I'm still expecting 2 fails.

@yched, thanks for pointing out that non-numeric entity ids issue. I will take a look at it for sure. Though I'm not sure I have either the in depth knowledge of Field API nor the time to tackle it between now and code freeze.

dropcube’s picture

block.module is the only thing in core using the filter format delete hook and with this patch it doesn't need it anymore.

comment.module also implements this hook, could we try with comments instead of custom blocks in that test ?

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

@dropcube, I guess my grep skills failed me. I didn't see the one in comment.module thanks for pointing it out. However, I'm going to argue that I think that that test should actually be in comment.test and not filter.test and that the one I'm removing from filter.test should have been in block.test in the first place.

We are already testing that filter.module calls the appropriate hooks when a filter is deleted and since it is up to the implementing module to respond to these hooks in whatever way is appropriate I think that the other modules should be the ones to implement a test making sure that they are performing the right tasks when a filter is deleted.

If however there's a reason to test it in filter.module and not comment.module I can pretty easily write new tests to replace the block related ones removed in the current patch.

Hopefully this will pass tests, (still expecting 2 fails see comments above.). All of the block availability tests are passing locally.

eojthebrave’s picture

Status: Needs work » Needs review

err .. testing bot try this one on for size.

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

I can not for the life of me replicate the "block availability" test failure locally. The other two test I was expecting to fail. Any ideas?

jrglasgow’s picture

FileSize
52.66 KB

after applying the patch I got this attached error running update.php

jrglasgow’s picture

FileSize
68.04 KB

After a fresh install - after the patch was applied - I cannot see where to add fields to a custom block. Please let me know where I can go to find this feature after the patch.

eojthebrave’s picture

With custom blocks you have to create the block before you can add fields to it. This is necessary so that the blocks Field API bundle can be created. Once you've created the block you should see manage fields / display fields tabs.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
35.61 KB

Lets see how this one does. Required a few minor updates after #561970: Rename 'box' to the easier understandable 'custom block' (and {box} to {block_custom})... got in.

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
35.61 KB

Added implementation of hook_field_extra_fields() so you can now reorder all the form elements on the block configuration form around via Field UI.

Hopefully fixes more tests. Again, I'm still expecting 2 failures. We'll see how it goes.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review

Hm, isn't that the same patch as in #42 ? ;-)

eojthebrave’s picture

Why, yes, yes it is. It was supposed to be this one.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

The fails in the various 'Block availability' test are caused by a hiccup in block_menu().
Enable Poll module and go straight to admin/structure/block/configure/poll_recent: the menu path doesn't exist and the menu router displays admin/structure/block/configure (list of blocks for theme 'configure', which of course doesn't exist)
It seems the second time you try to go to the URL, the menu path exists and the correct page is displayed.

I'm not sure what motivated that change, but I'd say

-  $items['admin/structure/block/configure'] = array(
-    'title' => 'Configure block',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('block_admin_configure'),
-    'access arguments' => array('administer blocks'),
-    'type' => MENU_CALLBACK,
-    'file' => 'block.admin.inc',
-  );
+
+  $blocks = db_query('SELECT block_id, module, delta FROM {block} GROUP BY block_id');
+  foreach ($blocks as $block) {
+    $items['admin/structure/block/configure/' . $block->module . '_' . $block->delta] = array(
+      'title' => 'Configure block',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('block_admin_configure', 4),
+      'access arguments' => array('administer blocks'),
+      'type' => MENU_CALLBACK,
+      'file' => 'block.admin.inc',
+    );
+  }

is not a good pattern. We should keep a single menu path here and figure out the exact block in the callback.
Also, original paths use admin/structure/block/configure/[module]/[delta]. Moving to admin/structure/block/configure/[module_delta] will cause clashes for module names and / or 'delta' names containing '_'s (do you parse 'foo_bar_baz' as module 'foo', block 'bar_baz' or module 'foo_bar', block 'baz' ?)

yched’s picture

Figured out afterwards that the intent of the menu change is probably to provide actual paths to tie the Field UI 'Manage Fields / Display Fields' pages.
Then, I'd suggest using admin/structure/block/configure/%block as a single menu item, The %block placeholder will hold the bundle name (module+delta).

To avoid the name clashes I mentioned above, bundle names should use another separator than the underscore. Maybe simply 2 underscores : foo__bar_baz = module foo, block bar_baz.

nevets’s picture

I think 2 underscores is not the best approach, the difference between 1 and 2 underscores is not the obvious. What this really argues for is blocks having a unique block id that can be used in paths (like node ids).

yched’s picture

re #51: we don't want a serial block id to be used as our field bundle name, because serial ids depend on the site history and can vary from dev to staging to prod, making staging and deployment harder.

"the difference between 1 and 2 underscores is not the obvious". I'm not sure I agree + I don't think we care anyway. This 'module__blockdelta' string is only used internally, no module dev ever has to write or read it, and the only place it will be visible are in urls for the block config pages.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
53.42 KB

How about something like this.

Since we're already introducing the block.block_id which is unique numeric ID for each block as a pre-requisite for making them fieldable I changed the menu item to admin/structure/block/configure/%block and implemented a block_load(), block_load_multiple() for consistency, and a BlockController class.

This gives us urls like admin/structure/block/configure/23, which will load the $block object and create the appropriate bundle name "module_delta" for the block.

In order to get around the situation were someone will not know the unique block_id number for a block I've also added a block_entity_id($module, $delta) which will look up the block_id. So you can create paths like

'admin/structure/block/configure' . block_entity_id('system', 'powered-by')

Marking as needs review so the bot can test it.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review

OK, works too I guess. numeric ids are fine in urls, as long as we don't use them in our bundle names.
My remark in #50 about 'foo_bar_baz' means we still cannot use '_' as a separator in bundle names, though. If these don't end up in urls, we can use any separator we want, 'module|delta' or 'module:delta', for instance.

Side note: I'm wondering what are the remaining use cases for the original 'bid' property (unique to a block in a given theme) ? This, and the current structure of the {block} table with duplicated rows across different themes, really sound like a thing from the past. Well, not for this issue anyway.

eojthebrave’s picture

Changed the bundle identifier to 'module:delta'. Added an implementation of hook_modules_enabled() so that blocks are saved to the database and assigned a block_id when first enabled.

@yched, I agree that the {block} table is kind of a mess. Not sure if tackling that aspect of the block module fits within the scope of this patch. It would however probably make this feature much cleaner in the end. I'm beginning to feel like this is more of a band-aid solution. As far as I can tell the 'bid' property isn't used at all. Anyway, I'm tired, I'll have to think about this more tomorrow.

Status: Needs review » Needs work

The last submitted patch failed testing.

dropcube’s picture

block.module database structure needs a complete revamp, of course, not in this issue. But this issue would be lot more easy on top of a proper database schema.

#257032: Split block $ops into separate functions intended to solve that, sorry I did not have time to complete. It's something I will work for sure if the code freeze is extended ;), or in Drupal 8 maybe.

yched’s picture

Code freeze is Mon 7, so still one week to get this in :-)

hass’s picture

+

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
56.04 KB

Well, that took a lot longer than I had anticipated. After thinking about it for a few days I was really starting to not like the direction that the last patch was going. Trying to weld a unique block_id onto a system that was not built for it. So I started over again and this time have refatored the {block} table into {block} and {block_instance}.

This allows us to have a unique ID on the block table, and store theme/instance specific information in the {block_instance} table. Much cleaner. This approach would also serve as a good jumping point for the ideas being discussed in #257032: Split block $ops into separate functions which I would love to see happen in the long run.

After splitting the {block} table into two tables I also implemented block_load(), and block_load_multiple() functions and BlockController class that will handle loading of instance/role/node_type into the block object.

Once all of that was in place making blocks fieldable is pretty trivial.

I wasn't sure if this was getting to be to much scope creep for this issue so if need be I can provide a patch for the re-factoring part and a patch for the field API part. This is also why there are two new hook_update_N functions introduced by this patch. I wanted to keep it easy to split them up if need be.

Weirdness and things I could use some advice on.

When block_update_7002() or block_update_7003() runs everything works as expected but at the very end I get an error saying that it "aborted prematurely." However, all upgrades have been performed and work. There is also an entry in the watchdog table that looks like this.

Notice: Undefined index: current_set in _batch_next_set() (line 375 of drupal_dev/blocks/drupal/includes/batch.inc).

Lets see what the bot has to say.

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
88.18 KB

Wrong patch. I need to stop naming every directory on my computer drupal/

Status: Needs review » Needs work

The last submitted patch failed testing.

catch’s picture

The notices in update.php are in HEAD, so safe to ignore those.

This looks great. It's 99% internal refactoring with few changes to existing function signatures, so might be accepted under code slush conditions. I didn't do a proper review of the patch, but noticed vis_settings - I know it's long, but should be visibility_settings for all those, we don't abbreviate variable names.

The block instance table - does that allow us to have more than one instance of the same block? If so, it'll help the dashboard quite a lot.

yched’s picture

Just a quick test :
- I'm able to apply the patch and run the updates without any error or reports of updates 'aborted prematurely'.
- Existing blocks seem to be displayed as expected after the update.
- On my 1st visit to admin/structure/block/list, I get one 'The block X was assigned to the invalid region [whitespace] and has been disabled" message per block that was previously disabled.
- I can enable new blocks or reorder existing ones on Garland and Seven themes, works as expected (with the exception noted just below). But the messages mentioned above pop up whenever I submit the 'List of blocks' form.
- Doing a change in the blocks for Seven wipes all block settings for Garland: no more blocks on Garland.

The changes you describe sound like an excellent cleanup, but I won't be able to actually review that part of the code :-/.
I'll just say that although the concept makes perfect sense, using the word 'instance' to refer to the settings of a block within a given theme might end up quite confusing in a world with Field API and fieldable blocks ;-)

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
93.72 KB

Reroll, tracking head and should fix some of the failing tests. Also fixes @yched's issue in #66 displaying the 'disabled block' warning over and over. I have not been able to repeat the problem where making changes to blocks in Seven wipes the blocks in Garland.

I'm open to calling them something other than block instances, but haven't yet come up with any good ideas. Suggestions?

@catch, yes in theory the block_instance table should make it pretty trivial to support multiple instances of the same block in the same theme. This patch doesn't currently allow this but it should be pretty east to either adjust this patch or add that functionality after this lands. It'll mostly be a matter of figuring the UI stuff out.

Status: Needs review » Needs work

The last submitted patch failed testing.

webchick’s picture

FWIW, I do think this counts as the kind of API clean-up that is allowed during code slush. Though I'm a bit concerned about performance...

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
102.5 KB

This patch should fix a bunch of the tests, though probably not all.

In order to get things working properly I had to add a field_info_cache_clear() call to block_modules_enabled(). If I understand what is going on correctly the block_modules_enabled() function is called when a new module is enabled and in turn calls _block_rehash() so that the new modules blocks get added to the {block} table and assigned a unique ID. I believe the problem is that the _block_rehash() function is causing all the field and entity info functions to cache incomplete data.

You can repeat the problem by applying this patch with the call to field_info_cache_clear() removed. Enable a module like forum.module that provides custom blocks, and now before visiting any page that would trigger a cache wipe navigate to the admin/content page. In my tests I'm getting a WSOD and a bunch of PHP errors in my log related to not finding some entity info related things for taxonomy.module. Clear the cache and everything is back to normal.

Should this call to field_info_cache_clear() be placed somewhere else so that other modules don't run into the same problem? Or do we just expect those modules to deal with it as it comes up?

Perhaps the bigger problem here is the need to create a record in the {block} table for each module implemented block when the module is installed/enabled. If we don't do this right away we end up with a situation where the new blocks do not have an ID until you visit the block admin page and then a lot of tests fail because they can not retrieve the block ID they need without first visiting the block admin page. This is currently solved by using the hook_modules_enabled() function to check and see if the newly enabled module implements hook_block_info() and if it does calls _block_rehash() to make sure those new blocks are added to the DB. Perhaps there is a better way to solve this.

Marking as needs review so the bot can have a go at it.

eojthebrave’s picture

Hm. So it seems the trend here is my inability to attach the right patch. Previous one was missing a couple of fixes after merging changes with current HEAD.

Status: Needs review » Needs work

The last submitted patch failed testing.

sun’s picture

Issue tags: +API clean-up
eojthebrave’s picture

Status: Needs work » Needs review
FileSize
101.5 KB

How about this one bot.

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

Having trouble figuring out what is going on with some of these tests and could use some input. I think I've narrowed it down to an issue with caching. Both the forum.test and poll.test tests pass just fine if I add a drupal_flush_all_caches() into the tests.

I've tried to figure out what is going on with the poll module though no real luck so far. It appears that the problem may be occurring within the theme() function, though to be honest I'm not even sure about that. In the poll test at line #279 we are testing the recent poll block, logged in user, a new poll has just been created and the test browser navigates to /user expecting to the find the recently created poll in the block that was placed in the footer. It's not there. Adding drupal_flush_all_caches() just before this line fixes the test.

So far I've been able to trace it to the call to theme('poll_results' ... in poll_view_results() which is returning nothing. The template_preprocess_poll_vote() function is never called, the poll-results-block.tpl.php and it appears the $hook in theme() doesn't exist when it is asked for.

I'm stumped and could use some help getting pointed in the right direction.

yched’s picture

Just a quick note that I'm away from my coding env. for the next couple weeks, and won't be able to help with unblocking the tests myself :-/

Frando’s picture

Just back from vacation, catching up and just found this patch: Wow, this looks amazing. No time right now to do a proper review, but a huge thumbs up for block and block_instance and for using entity loading for blocks. Great to see this work so clean. I'll try to squeeze in a proper review soon.

eojthebrave’s picture

I've added a call to drupal_flush_all_caches() into block_modules_enabled() which should get more of the tests passing. We might want to consider moving this to the a module_enable() function so that other modules don't have to deal with this as well.

Still not 100% sure what is going on and why this is needed, but will keep digging as time allows.

eojthebrave’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
101.95 KB

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
101.61 KB

Status: Needs review » Needs work

The last submitted patch failed testing.

webchick’s picture

Issue tags: +D7 API clean-up

Id still really like to see this happen. Among other things, it would make #544360: D7UX dashboard module work a lot better.

eojthebrave’s picture

Status: Needs work » Needs review
FileSize
102.61 KB

I've had a shortage of free time the last few weeks and haven't been able to work on this much. I've attached a patch with where I am at right now. This one should fix a number of the tests, but there are still some that I'm unsure about how to fix. After the bot has had a chance to do it's thing I will report back with a list of the tests that are still failing that I could use some help with.

Pretty busy this weekend, but I may be able to set aside some time for this.

Status: Needs review » Needs work

The last submitted patch failed testing.

catch’s picture

Status: Needs work » Needs review
FileSize
104.27 KB

This is a straight re-roll without any attempt to fix the test failures yet. I resolved conflicts in block.module, and made it so block_update_7002() and block_update_7003() doesn't cause fatal errors due to $ret removal.

TODOs for anyone who wants to pick this up

1. convert insert an update queries in block.install to db_update() and db_insert() - update_sql() is dead but I only had time to change to db_query, and there's two SQL syntax errors in there now that the fatal errors aren't removed.
2. Debug the test failures.

Setting CNR just for the test bot.

Status: Needs review » Needs work

The last submitted patch failed testing.

Pasqualle’s picture

Status: Needs work » Needs review
FileSize
104.68 KB

reroll

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

Posting what I've got at the moment so catch can take over.

catch’s picture

Status: Needs work » Needs review
FileSize
106.52 KB

eojthebrave also posted this,not rolled in yet:

/* fixes query in dashboard_page_alter() */

$query = db_select('block', 'b');
$query->join('block_instance', 'bi', 'bi.block_id = b.block_id');
$block_list = $query
  ->condition('b.status', 1)
  ->condition('bi.theme', $theme_key)
  ->condition('bi.region', $region)
  ->fields('b')
  ->fields('bi')
  ->execute();

/* fixes dashboard_show_disabled() */

foreach ($blocks as $key => $block) {
  if (!isset($block['instances'][$theme_key]['region']) || !empty($block['status'])) {
    unset($blocks[$key]);
  }
}

/* in dashboard_show_block_content this ... */
$block_object = db_query("SELECT * FROM {block} WHERE theme = :theme AND module = :module AND delta = :delta", array(
  ":theme" => $theme_key,
  ":module" => $module,
  ":delta" => $delta,
  ))
  ->fetchObject();

/* ... can probably be replaced with something like */
$block_object = block_load(block_entity_id($module, $delta));

I managed to remove a lot of exceptions, but seem to have broken user logins in the process. This patch is still quite explosive but I'm about to go out and would like to see how bad the tests look now.

Status: Needs review » Needs work

The last submitted patch failed testing.

catch’s picture

Status: Needs work » Needs review
FileSize
108.93 KB

Here's progress so far.

Bugs fixed:

The sort code in _block_compare() was throwing hundreds of notices. I added even more isset()s than were already there, not at all pretty, something more serious is broken.

user/n/edit was throwing a fatal error due to a completely $form['block'] = $blocks; which needed just needed ripping out.

Empty blocks were being displayed because field_attach_view() unconditionally adds #attached to $content even if it's not attaching any fields, that needs its own issue but including here for now.

This should get us down to a slightly saner amount of test failures, still feels like quite a way off though (and I was getting bizarre ones lie infinite actions and color.module which suggests still some fatal errors lurking around.

Status: Needs review » Needs work

The last submitted patch failed testing.

catch’s picture

Status: Needs work » Needs review
FileSize
108.94 KB

Also fixed filter tests.

Status: Needs review » Needs work

The last submitted patch failed testing.

eojthebrave’s picture

I'm assuming at this point that this is stalled until D8 development gets underway and that I would be better off spending my time on more pressing issues in the interim. I fully intend to make sure this happens in D8 but plan on focusing the free time I have elsewhere for now.

I'm hoping that it will be possible to create a contrib module that provides a drop-in replacement for block.module or can at least extend it to make fieldable blocks in D7 and will try and spend some time in the next few weeks mocking something up and filling in any gaps in D7 that prevent this.

catch’s picture

Category: task » bug
Priority: Normal » Critical
Issue tags: +Release blocker

In #473268: D7UX: Put edit links on everything block access callbacks for all visible blocks are now called on every page, for every user, including anonymous. This patch adds block_load_multiple() as a wrapper around block_load(). Assuming we can call block_load_multiple() before the access callbacks are called (should be easy), this patch will then save a query, per block, per page, since the menu_load_objects() is triggered for every access callback, and we'll be fetching the block info from static instead of a direct query.

webchick also suggested this patch might get an exception since it can solve several dashboard wtfs. So I'm promoting this to a release blocker for both performance and usability.

lonelyrobot’s picture

subscribing.

David_Rothstein’s picture

As per discussion at #607244: Decrease performance impact of contextual links and #606640: Use proper menu router paths for the block module (but no argument loader functions) we do not need block_load() at all, so getting rid of that function completely (or at least not using it as a menu loader function anymore) seems like it would be the best way to solve the performance issue.

That said, this feature would indeed be useful for the dashboard, as well as in general, so.... subscribing :)

te-brian’s picture

Is this issue still considered a release blocker? It would be very useful indeed, but there hasn't been much action in a while so I'm wondering what the status is.

catch’s picture

Version: 7.x-dev » 8.x-dev
Issue tags: -Release blocker

The performance issue got solved elsewhere, there's still some outstanding dashboard issues, but I have a feeling the ones this patch hopes to solve are too late for D7, so very reluctantly moving this to 8.

te-brian’s picture

Awww, Boooo. I guess it was inevitable, with all the other important work going on. I'm sure a contrib drop-in will materialize at some point.

Pasqualle’s picture

Category: bug » feature
Priority: Critical » Normal
Issue tags: -i18n sprint, -Fields in Core, -D7 API clean-up
BenK’s picture

Subscribing...

indytechcook’s picture

Contrib module has been dropped http://drupal.org/project/bean

Now that I just found this issue, I will follow the patches lead on some UI elements.

sun’s picture

I've co-authored the http://drupal.org/project/block_api module with @jamestamr, which contains a (still hidden) sub-module that just simply attempts to do this: making block instances fieldable. To allow for this in the first place, the primary block_api module implements a revised notion of block types that spawn block instances, the latter being entities.

In other words, if this functionality is considered for core, then we can simply replace the related bits in block.module with block_api.module. The D7 version was actually written with this in mind right from the start. It's clean and mean, and properly documented.

But obviously, all of this somewhat circles back into the epic question of whether blocks are configuration or data, as well as the derived question whether configuration should be entities. If blocks are configuration and not entities, then they can't be fieldable. Once you've seen block_api in action, I think that the line is too blurry and really depends on your site's use-case as well as individual types of blocks, so it can't be solidly drawn. Therefore, I'd highly recommend to continue this effort of turning blocks into entities.

indytechcook’s picture

But obviously, all of this somewhat circles back into the epic question of whether blocks are configuration or data, as well as the derived question whether configuration should be entities.

I feel that we should separate out the config and content in a block. I see the block edit form being the fields and anything defined by the plugin, while the block config form is the cache level and visible info, etc. This would make the content an entity and fieldable while storing the configuration separately. Block types would always be configuration.

The approach I took in the 7.x-1.x branch of bean was to make every block type a ctools plugin thus defining any configuration on the plugin/block type level and only exposing the a content form or the fields for the user to edit on the block instance level in the UI. This separates the config in code only and exposes the block instance content to the entity. I'm currently working on adding the ability to add block types in the UI, but my idea was to still place all of the config on the type level and out of the entity.

larowlan’s picture

Tagging to align with one of the core Drupal 8 tracks

larowlan’s picture

effulgentsia’s picture

Sorry. Jumping in late here, and I haven't read the full issue, but one thing preventing not just custom blocks from being fieldable, but even module-coded blocks from being able to add field widgets within hook_block_configure() is that the hook doesn't take a $form_state parameter, and therefore, if any widget validation callbacks later call field_widget_field(), they can't access $field_state['field'];. The use-case I just found this on is #1153610: Saving Gallery Block causes 2 notices. Looks like there's another issue in the queue also interested in addressing this limitation of hook_block_configure(): #690828: hook_block_configure not AHAH compatible.

tstoeckler’s picture

Not that I'm personally involved, but I saw http://drupal.org/project/block the other day...

larowlan’s picture

Gábor Hojtsy’s picture

Issue tags: +D8MI

Tagging for Drupal 8 multilingual initiative. Re: http://groups.drupal.org/node/155634

moshe weitzman’s picture

FWIW, I think custom blocks should move to contrib and join forces with http://drupal.org/project/boxes. They can flourish there (and become fieldable).

indytechcook’s picture

You mean like this? http://drupal.org/project/bean

Gábor Hojtsy’s picture

@Moshe: well then we'd only need to kill this feature to change module provided block titles on the UI or make those entities :)

joachim’s picture

Shouldn't all blocks be fieldable, not just custom ones?

David_Rothstein’s picture

Usability testing seems to reveal the distinction between a custom block and nodes is blurring...
....
FWIW, I think custom blocks should move to contrib and join forces with http://drupal.org/project/boxes. They can flourish there (and become fieldable).

One way to combine those two ideas and being discussed at #1164718: Improving the usability between "custom block" and "content" is to remove custom blocks from core, but allow nodes to be exposed as blocks. Then we get this feature for free, since nodes are already fieldable. (Though we still don't get fieldable module-provided blocks, per @joachim in #121.)

indytechcook’s picture

I agree with blocks becoming content but they should not be nodes but their own entity type.

Here is some background about the Ideas behind the bean module's API first design. This was pulled from #1186800: Similar module - differences from Bean module? which is discussing the difference between the block_api module and the bean module.

Our goals are really inline. We both want to provide a way to create block types, then create instances of the block types. You approached it from a modifying the current state while I approached it from a clean slate. My idea was to make the API first, then make the UI an implementation of the API. The plugins are how you create new block types. I chose making the blocks as content (hence entities) because of that's what they are becoming. This also gives us fields built in (but not needed for the blocks).

I turned the block into content. It has a separate home on the UI /block/add, it has separate permissions then the block types. Blocks types are bundles on blocks and are completely in code (except for the UI implementation which will be exportable). Not a huge array in code like features, but really in code. I chose the boxes plugin methodology of OO based plugins that will be replaced with the Plugin system that Larry is working on.

My goal was to make the block system how I would want it from a coding/framework perspective. After looking over you code, I see many places I need to add to my code (thanks!) to make it more inline with the current block system.

Gábor Hojtsy’s picture

@indytechcook:

This also gives us fields built in (but not needed for the blocks).

Oh, what is the block title and body if not fields?

@David_Rothstein: what if we make the theme relation and visibility settings fields? That would allow you to blockify any entity type, such as nodes. We can pre-configure a node type to be a "block type". Sounds a bit far fetched, but I agree from a usability point of view, the resulting content creator UI would make a lot of sense.

indytechcook’s picture

The custom block is only an implementation of the API itself. Not needed for the core block API.

There would be a label (for admin listing purposes only), and a machine name. Everything else is either a field or implemented as part of the block types plugin. I know this issue is for custom blocks, but I feel the real issue is deeper. I apologize for this being the incorrect place for this comment.

Anonymous’s picture

Would it be possible to backport this to D7 when it's ready?

xjm’s picture

Title: Make custom blocks entities » Make custom blocks fieldable

#1206310: Missing API function: there is no block_save() came up today. This seems to share the same base issue: blocks should behave and be handled like proper entities. Currently, block.module does a lot of direct querying without using API. E.g., see in block_load() and block_admin_configure_submit().

catch’s picture

Title: Make custom blocks fieldable » Make custom blocks entities
joachim’s picture

Title: Make custom blocks fieldable » Make custom blocks entities

I've been pondering this one...

I don't think we should create / increase the division between module blocks in code and custom blocks in the database.

So what if all blocks are entities, and when a module defines, say, two blocks, it is defining block types, that is, entity bundles?

Then these are fieldable on a block-by-block basis, and we also get the ability to place a code block in more than one place (#79571: Allow blocks to appear in multiple regions) because a placed block is now an instance, or rather, an entity.

xjm’s picture

Title: Make custom blocks entities » Make blocks entities
joachim’s picture

The other thing I wanted to say was that the content that a module provides, eg the 'who's online' list of users, would then appear in the 'manage fields' UI as a greyed-out but draggable field, same as core node elements did with D6 CCK -- assuming that UI pattern is still available in D7.

joachim’s picture

Another thing to consider is existing block-providing modules that allow multiple blocks to be created, each with different settings.

A good example is menu_block, but so is this: http://drupal.org/project/jquery_countdown

How can we provide a system so these modules don't keep reinventing the wheel for their storage?

franz’s picture

A summary on this issue would be great.

JuliaKM’s picture

Problem/Motivation

In Drupal 7, blocks are not fieldable entities. Because blocks are not entities, we cannot add fields to them. As a result, there are not easy ways to add fields like images to blocks without using custom modules.

Additionally, if blocks were entities, we would be able to:

- Promote consistency in the Drupal API
- Simplify the process of adding fields like images to blocks
- Potentially remove the need for custom modules to add fields to blocks and/or create blocks for nodes
- Redo or improve implementation of hook_block

Proposed resolution

In Drupal 8, make all blocks fieldable entities. To do this, a block_id is added to the block table. The new block_id field is used by the Field API to identify the block in question.

As part of the proposed change (last patch is #98), the block table is refactored into {block} and {block_instance}. One advantage of the block_instance table is that it can be used to support multiple instances of the same block within the same theme.

Remaining tasks

1. Set a plan of attack for how module blocks and custom blocks should differ in the database (#129).
1. Review the block_api module (http://drupal.org/project/block_api) noted on #110 and Bean module (http://drupal.org/project/bean) and see if either should be a starting point for a new patch.
2. (If proceeding with previous patch) Debug test failures using patch at #98 as a starting point
3. Address limitations of hook_block_configure() identified in #114.
4. Address usability concerns:
#1164702: “Block” has no meaning. (New users challenged by use of the term 'block')
#1164718: Improving the usability between "custom block" and "content"
#1164712: Users expect to preview blocks before saving changes

User interface changes

Addition of a manage fields/display fields tab for blocks.

There needs to be a decision reached about whether to separate out the config and content in a block (#111).

API changes

Potentially rewrite block module to do less direct querying of the database and to instead use the API (#127).

Original report by catch

I think we should consider changing custom blocks to be fieldable items, there's a few reasons for this:

1. Like making node->body a field, we can make the {boxes} table tidier
2. There would finally be a nice way to add things like images as blocks
3. We could possibly replace entire modules like http://drupal.org/project/nodeasblock via nodereference
4. Longer term, it might be a possible route towards replacing some implementations of hook_block - so to take views as an example, you could create block bundle which has viewfield attached to it, then the workflow would be:

'Add block'
choose 'view'
choose the view / display you want to show in the block.

As opposed to admin/build/block and find the view you defined in the disabled region.

Not given that a lot of thought, but simply replacing the textarea storage with a field and allow for fields to be attached to blocks would be a big change for one patch anyway.

JuliaKM’s picture

Issue summary: View changes

updating issue description

franz’s picture

Nice summary

JuliaKM’s picture

JuliaKM’s picture

Issue summary: View changes

Fixing number in remaining tasks list

bryancasler’s picture

subscribe

indytechcook’s picture

I had a conversation with sun and zroger about a plan for block entities.

The goal here is not to replace system blocks (defined by hook_block_info) but to replace custom blocks with entities and bundles.

Blocks will be entities and block types will be the bundle. We will introduce new hooks to add block types.
We are using the OO version of the block entities form the http://drupal.org/project/bean without the OO for block types. This will reply on #1184944: Make entities classed objects, introduce CRUD support for creating the entities as classes.
Block types will use the http://drupal.org/project/block_api model to create the block types. A procedure based methodology.

New hooks will be introduced for the block types. Sun and I did have discussion about the how block types were going to be implemented. I favored the OO method using a plugin system to define the block types/bundle. Sun has the procedure method more like what content types, taxonomy currently use. We came to the agreement to use the procedure method for now and wait for the plugin system to be implemented into core. Making bundles into plugins is an entirely different issue.

Gábor Hojtsy’s picture

Usability-wise (both user facing and developer facing), using existing patterns from node type entities would be best IMHO. So if you are to introduce great new API stuff, make it consistent with nodes (introduce it there too). Having blocks as entities, but still very far away from node types might not be the best result.

indytechcook’s picture

Assigned: Unassigned » indytechcook

That's the idea Gábor Hojtsy.

I've been working on this a bunch but not ready to submit a page. I've made some great progress, I'm doing a code sprint on it (by myself ) this weekend during Drupal Camp Indy!

I'm going to assign it to myself so on one else spends time one it.

David_Rothstein’s picture

The goal here is not to replace system blocks (defined by hook_block_info) but to replace custom blocks with entities and bundles.

The current issue summary (at the top of this page) says this issue is actually about converting all blocks to entities, not just custom blocks... What is the rationale for changing that?

Note that if we only convert custom blocks to entities, this issue will directly conflict with #1164718: Improving the usability between "custom block" and "content". We can really only do one or the other. If we convert all blocks, though, then this issue makes sense either way (even if we remove the usability nightmare that is "custom blocks" from core later on, there will still be benefits from converting regular blocks to entities).

sun’s picture

The rationale is that we can all agree on custom blocks being user content, and thus, entities. In contrast, that's not the case for system/module provided blocks, for which we still need to have an epic discussion about whether they are configuration or content.

By converting custom blocks into entities, we introduce a new pattern of "block instances spawned out of a block 'type'". This means there can be multiple different block types. This ultimately allows us to move Menu Block module into core. (See #474004: Add options to system menu block so primary and secondary menus can be blocks rather than variables and also #503810: Convert primary and secondary menus to blocks and actually many others.)

#1164718: Improving the usability between "custom block" and "content" is a good discussion to have. But at this point, I believe it's vaporware. Not to mention that the talk over there has a unhealthy bias towards "Make everything Nodes", which I thought and hoped we already had forgotten about. -- Anyway, these efforts are not conflicting at all. Instead, pretty much the opposite: turning (custom) blocks into entities moves them closer to the user content pattern of nodes.

Whether or whether not we can move on and also turn system/module provided blocks into block instances afterwards, depends on a full range of discussions we need to have, major progress on various D8 initiatives, and ultimately, hard decisions to be made. Until then, we absolutely need to move forward. No one wants to see D8 without menu_block's functionality in core. That is, not only because of the added feature-set, but also, because it allows us to finally clean up lots of hard-coded and utterly confusing special cases around primary/secondary links, blocks, and menu trees.

joachim’s picture

> Whether or whether not we can move on and also turn system/module provided blocks into block instances afterwards

Surely there's a simple way to do this:

- make every block info returned by hook_block_info() into a bundle
- provide a built-in piece of content output 'block system output' which uses hook_extra_fields (or d7 equivalent) to be draggable within the field management
- adding code-provided block now becomes adding a new block of a particular type.

Not that you'd ever want two 'Powered by drupal' blocks. But there are definitely some blocks you'd want multiple copies of. In fact, having menu_block in core surely depends on being able to add multiple code-provided blocks since you configure each one.

indytechcook’s picture

It's not hard to actually make all blocks entities, it's more in the how the pattern will work. It's more in how it's going to fit into the WSCCI and other core initiatives. We do know that "custom blocks" will be entities but the jury is still out on "system" blocks. IMO I do think all blocks should be entities. But that introduces new patterns in core that we are not ready to make it. Once the plugin system is complete, then I'd like to have the discussion about block_types (and content_types) being plugins.

Until we are ready for that, we can proceed on this issue for custom blocks. Make all blocks into entities isn't that complicated once this issue is complete.

We also need to start separating out the rendering of blocks from the blocks themselves. This will help with the #1164718: Improving the usability between "custom block" and "content" discussion.

Part of my plan is to create a new module (block_custom) that contains all of the code for block entities and block types. Leave the rendering of the block to the block module. Make the block_custom module optional.

I'm following the content type pattern for creating block types. This will also implement the class based entities from #1184944: Make entities classed objects, introduce CRUD support which gives us a base patterns for blocks themselves.

So while they are discussion how blocks will fit into WSCCI, I'm going to make this concrete step. I do think that the block type patter will change again before D8. But that's a different issue.

indytechcook’s picture

franz’s picture

indytechcook, forgive me, but is there enough consensus on block = entity so that you start merging other issues in? It seems by your comment on one of the issues that you're still trying to convince everyone, so it might be better to go on with the discussion before hitting other issues? However, it's good to point to this issue so that everyone is aware of potential changes.

David_Rothstein’s picture

Part of my plan is to create a new module (block_custom) that contains all of the code for block entities and block types.

Splitting custom blocks into a separate module sounds like a great idea. This would eliminate a lot of confusion people have about which part of block.module is the API and which part is implementing its own API. It would also make it easy to remove custom blocks from core if that's the direction we eventually go in :)

There is admittedly a certain theoretical purity to saying "blocks are configuration, and the things displayed in them are content; thus the things displayed in them can be entities (and can be fieldable), and it's up to whichever module that provides each thing to decide".... That is basically the direction we'd be going in if we put all the entity-related code in the proposed 'block_custom' module rather than in the main block system itself. But based on the previous comments in this issue, it seems we'd also lose a lot by doing it that way.

Either way, this still seems like a big change in direction. Has anyone reviewed the latest patch (#98)? It's old, but isn't there anything salvageable from it?

joachim’s picture

> It's not hard to actually make all blocks entities, it's more in the how the pattern will work. It's more in how it's going to fit into the WSCCI and other core initiatives. We do know that "custom blocks" will be entities but the jury is still out on "system" blocks. IMO I do think all blocks should be entities. But that introduces new patterns in core that we are not ready to make it. Once the plugin system is complete, then I'd like to have the discussion about block_types (and content_types) being plugins.

Do we have to go as far as system blocks being plugins?
We really lose a lot by having a half-and-half approach. And I don't see how menu_blocks in core will work with this, unless it has a really naive approach of automatically creating one top-level slice block per menu. And that would be a very cut-down and fairly uninteresting subset of what menu_blocks is.

Gábor Hojtsy’s picture

Do we want to remove the functionality to customize/override built-in block titles? Or is that going to be an entirely different interaction compared to setting up a custom block with a custom title? (Note I'm all for using entities for blocks, absolutely, just thinking about the consequences of how we approach it).

indytechcook’s picture

At first, my thought would do use the current API to put the subject of the block to the using a title property on the block entity. I'm all for just putting everything in the content and doing all of the rendering from a block.tpl.php.

indytechcook’s picture

FYI, i'm working off of this sandbox for block entity. http://drupal.org/sandbox/indytechcook/1331338

It's a work in progress and not working yet.

xjm’s picture

fago’s picture

It's not hard to actually make all blocks entities, it's more in the how the pattern will work. It's more in how it's going to fit into the WSCCI and other core initiatives. We do know that "custom blocks" will be entities but the jury is still out on "system" blocks. IMO I do think all blocks should be entities. But that introduces new patterns in core that we are not ready to make it. Once the plugin system is complete, then I'd like to have the discussion about block_types (and content_types) being plugins.

What are the advantages of all blocks being entities?

I see blocks as pieces of renderable content. Yes, having custom block entities makes much sense. However, how does the entity fit into the concept once a module just provides a certain piece of renderable content as block?

The way I'd see it is that the renderable content of a block can be the entity-view of custom block entities, as well as any arbitrarily defined renderable content of any module.

sun’s picture

joachim’s picture

Maybe we should review what we want to accomplish:

- custom blocks should be fieldable
- module blocks should probably be fieldable so users can easily add extra content to them
- a module that provides built-in blocks with some configuration (eg menu_block, jquery countdown, etc etc) should allow multiple copies of its blocks to be added, each with different configuration. (This is what I'm calling cookie-cutter blocks.)

To me that all suggests that each module provides one or more block types. In most cases, block type corresponds to delta, but for a cookie-cutter block each type you add a new block that's an instance. For custom blocks, users can define multiple types and instances of each type: in which case they're very much like nodes.

The problem with that is that just moving a block from 'disabled' to a region becomes a more complicated process where you create an instance of a block type and then place it in a region.

Jon Pugh’s picture

I like everything listed above. Even the "problem" is something that needs to be addressed anyway.

The problem with that is that just moving a block from 'disabled' to a region becomes a more complicated process where you create an instance of a block type and then place it in a region.

I think the problem is with the whole "disabled" region concept to begin with. Listing all of the "disabled" blocks in the draggable blocks UI contributes to that page being a horrible pain to use. If we were to remove them completely, and replace with an "Add Block" link, which would then list all of the "Block Types" for you to choose from, it would greatly enhance the process of "building" a site.

I would say 99.9% of the sites I've built never, ever use the default blocks that come with a module or drupal core anyway. So that list of (draggable!) "disabled" blocks is always in the way and just adds to the slowness of that page loading.

If we were to replace this model with a "Add Block" > "Choose Block Type" > "Configure this Block" paradigm, it would greatly simplify Site Building, and provide much more flexibility to the end users. For instance, instead of aggregator.module creating a "disabled" block for every single feed, you could create new Aggregator Feed blocks for only the feeds you want blocks for.

I know this is a big task, but I think its about time the block admin UI issues were addressed

indytechcook’s picture

module blocks should probably be fieldable so users can easily add extra content to them

This would require that all blocks be entities. While I am for that, others are highly against.

@joachim, your comment in #155 is the pattern I took in http://drupal.org/project/bean. This is the pattern I really want to take. It does introduce bundle types being plugins/classes. I'm wondering if I should just go ahead and do this in core or try to make it more abstract pattern for all entities. This is the reason I have made very little progress. I'm just not sure which direction to go.

@fago, with blocks being entities, someone could use references to pull in content from other entities.

This issue is focused on how the blocks are created, now how they are rendered. While that's very important, I think it should be kept in a separate issue.

indytechcook’s picture

This is a summary of an IRC conversation with Crell, EclipseGc, webchick, sun and some others about what the WSCCI team has been working on and how block as entities fits in.

Discussion Review

I was advocating for all blocks as entities. Everyone else was against the concept. The main discussion was more around what I thought a block should be and what the current direction of blocks are. The trend is to move blocks towards a general piece of content with some configuration on a page.

Easy Agreement.

What is currently known as a custom block in D7 will become block entities.

Blocks as Plugins.

EclipseGC showed me what he has currently down to turn blocks into plugins. http://drupalcode.org/sandbox/Crell/1260830.git/tree/refs/heads/wscci-pl.... This is dependent on the Context API and the Plugin System. The basic block plugin is based upon http://drupalcode.org/sandbox/Crell/1260830.git/blob/refs/heads/wscci-pl.... From my perspective, these are blocks that are meant to be placed once and never moved or changed. For example, the Main content block, the search block, the Powered By Block, etc. They do not have any configuration around them in the UI. Now this is a very early implementation and I'm sure it will change.

If block continue down this path then a custom block would be a block plugin. This implementation is also focused on blocks be structure. We didn't get into the discussion about what this plugin should look like. At this point it's just to early to implement the CustomBlock plugin with the API is such flux.

My Thoughts
I'm very excited about having a Plugin System in core. What EclipseCG and Crell has done so far is very promising for the core of blocks. I am worried about the timeline. The uncertain about when/if the dependencies for the BlockPlugins get into core means that relying on this pattern could hurt the Block Entity implementation.

The Bean Pattern

I've been asked several times for more clarities on my ideas for block entities. So here we go. Most of this is based upon what I implemented in http://drupal.org/project/bean and turning blocks into content.

Blocks are Content

With a few exceptions, blocks are content. They are driven by content, controlled and placed by editors. I do mean editors and not site administrators or builders. I'm not talking about a blog or brochure site. I'm talking about a content driven site. Where the site editors decide where the blocks are placed, not based upon some what content type you are looking at. True editorial driven site layout.

I feel blocks being pushed in two different directions but forced to share a connection. The WSCCI implementation is staying the traditional track of blocks being configuration. In the past few projects, we have been moving more to blocks being content that is controller by site editors and not administrator. Maybe it's time for a more defined split. Would we use two separate systems? One is based upon content, the other is based upon structure. What do these two systems share?

Definitions

To help clarify, here are some definitions to terms I'm use what wait they mean in the context of this post.

  • Content: What a Site Editor would enter on a site without the need for non administrative permissions. Content is volatile and changed often.
  • Configuration: Configuration is controlled by the site builders. It requires a knowledge of how Drupal works. Configuration rarely changes in a production setting. With CMI, configuration is all in files for easy deployment.
  • End User: The site visitor who just looks at the content on the page and doesn't care what's behind it or how it works.
  • Site Editor or Editor: A person whose primary job is not to know how Drupal works. They add and edit content on the site. they could also be the content approvers.
  • Site Administrator/Site Builder: Someone who has knowledge of Drupal and is in charge of the back end configuration and management of the site.

Block Types

With blocks being entities, block types are bundles. For most people this means they can have fields, but in the Bean Pattern they are plugins that define how that block type behaves.

A block type Interface would define the following:

  • Values: The values defined in this block type and the default for the values. The block type would in charge of using the values.
  • Form: The form that is rendered. This does not include fields or common components. This form is exposed to a site editor on the block add and edit pages along with the other fields and common componets. The block type also has access to the form validate.
  • View/Render The block type would be responsible for returning the render array used by the theme system.

See the interface BeanTypePluginInterface at http://drupalcode.org/project/bean.git/blob/refs/heads/7.x-1.x:/includes.... Most of the methods are handled by the default abstract class. The main methods are value, form and view.

For use cases for Block plugins, you don't have to look any further then the bean project page.

The goal is to put more power in the site editors hand. The "configuration" is no longer configuration, it's content. Site Editors require the ability to control what would traditionally be configuration.

For a very simple example, take a listing block where you want a more link at the bottom. You want the user to select where the more link will go and what the link will say. Here is an implementation https://gist.github.com/1463915. It's very easy to see how this would expand to other aspects of the query. Turn what was once configuration in Views to content on the Block Type.

I feel that the developer experience for Block Types is very simple. Maybe because I made it :)

Rendering the Block

The Block should not care how it's rendered. Each Block type has the ability to create new theme functions. Since Blocks would be entities, view modes and field formatter would be used for theming. This makes them very familiar to other parts of Drupal content.

Build Block Types in the UI

One of the block plugins is a Custom block plugin. It is in charge of keeping track of the block types create in the UI. The UI for these is the same as any other entity bundle builder (like content types).

Placing the Block

The placement of block has traditionally been part of the configuration. It appears to me as if the Context API continues down this path. Blocks as content doesn't necessarily fit into this traditional model.

While placement of blocks is out of scope for block entities, my thoughts here help enforce the block as content argument. Not only are the blocks content, but the placement of the blocks on the page is content.

In D7 we do this with the block reference module, a page node and the field_group module. The field group module is used to place css classes around the block reference fields. The CSS classes refer to GRID classes and placement on the page. So we have a block reference field for left, center right for a 3 column page. The site editor is exposed to the node form where they see a field called "Right Blocks". It's an autocomplete field where they can select the block they just created in the block add/edit form. Now the site editor has just created the block and the block placement. According to my definition, the block and the block placement have just become content.

Here are the screenshots of a 3 column landing page from Energy.gov. The page was long so I had to split it into 2 different screenshot.
https://skitch.com/indytechcook/gs6yk/create-landing-3-column-department...
https://skitch.com/indytechcook/gs6ym/create-landing-3-column-department...

Caveats

The big picture of what WSCCI is doing is still a little fuzzy to me. I understand the concepts individually and from an academic nature, but I struggle to see how they are implemented in Drupal. I am looking forward to the unified architecture for Context and Plugins. I have read just about every piece of information I could find on the Initiative and have looked through the current implemented code. All of my concerns, thoughts, comments might be totally out of line of where Drupal is heading. My main reference is where Drupal is now and what I would like to see changed.

I do not know how the instances of the blocks will be managed. I can only speculate that they will be on a similar admin UI as the current blocks system, though I'm probably wrong here.

What next?

I'm not sure.

Option 1: Wait on WSCCI: We wait to see how the WSCCI implementation of blocks plugins gets implement. Then we add a custom block plugin to turn custom blocks into entities. This covers the most basic implementation of blocks as content and fits in with how most bundles are now.

Option 2: Implement against what we have.: We continue down the current path of building block types similar to content types. Basically we implement the Content Type pattern with blocks.

Option 3: The Bean Pattern: Block Content is separated out from Blocks. The patterns discussed above are implemented.

With option 1 and 2, the block types are built in the UI with fields. All as configuration. This basically voids all of my Block Type patterns mentioned above. I feel this is very limiting.

I can see implementing the Bean Pattern inside of the WSCCI. Especially if the block types use the Plugin implementation from WSCCI. The part I have thought out is how the Context fits into the Bean Pattern.

If I just start on Option 3, I'm introducing YAPP (Yet Another Plugin Pattern). While blocks as entities would make blocks more like other parts of Drupal, the block type pattern is new. I have ideas of making bundles into plugins with this same pattern. Currently the entity controller is the closest we have but it's too high level to be able to swap out.

I have no intention of disrespecting anyone. I have the highest respect and admiration for all of you. I love what's going on in WSCCI and I'm an advocate for change. Please do not take anything said here personally. I really want a solution that will fill as many use cases as possible. I love everyone :)

joachim’s picture

Thanks for that very clear and comprehensive post, indytechcook! Lots to think about there.

> With a few exceptions, blocks are content. They are driven by content, controlled and placed by editors. I do mean editors and not site administrators or builders. I'm not talking about a blog or brochure site. I'm talking about a content driven site. Where the site editors decide where the blocks are placed, not based upon some what content type you are looking at. True editorial driven site layout.

Here's my take on that bit. In my experience of site building, blocks are a mixture of both.

There are blocks like the site navigation, or site headers and footers, that if a Site Editor accidentally tinkered with or moved or removed, would leave the site totally broken. Because of that, I take the approach that Site Editors shouldn't go anywhere near Block admin (or Context admin).
Where blocks do need to be content, I've worked round that by using something like Nodequeue and Views to make a block (or what looks like a list of blocks) and so give Site Editors indirect control over what is shown in blocks. Modules like Ad and Node Blocks accomplish the same sort of pattern too. The block's placement is fixed, frequently determined by a Context based on node type.

The block reference technique looks extremely useful, as it would give Site Editors ability to create and edit landing pages without Site Building knowledge. That would still leave blocks whose content should be editable but whose placement is more complex.

I think this gives us:

A) Structural blocks which must never change, or whose content is automatic
B) Structural blocks whose contents can be changed by Site Editors, but not placement.
C) Content blocks whose placement and content can be changed by Site Editors

A split between content blocks and configuration blocks would be extremely useful, provided that we don't end up with two completely divorced systems: one block should be able to participate in either system.

webchick’s picture

Dashboard module, the red-headed stepchild of Drupal 7, actually lays out a good model for this I think.

We struggled for a long time how to handle the UI and API for that module. We wanted to give site editors an interface where they could customize and move blocks around in a way that gave them a good overview of their particular site. But not all blocks. I mean, there's no reason anyone other than Drupal.org would ever want "Powered by Drupal" block in their Dashboard. :P Or would they? It was not always cut-and-dried.

We debated adding a totally new, separate block type ("widgets" or something) just for Dashboard or other modules with similar "Content Block" needs. However, this would create extra work for people, having to create two blocks in views, exposing one as a "widget" to Dashboard.

In the end, what we decided on was an interface where you could configure, on a per-site basis, where that line on YOUR site was drawn between "blocks that should be exposed to site editors" and "blocks that should be for site builders only." I wonder if abstracting that functionality out beyond ashboard module's the right thing to do here.

indytechcook’s picture

A conversation with Webcheck helped me to clarify my position more on the block type pattern. What I'm really looking for is a entity bundle configuration plugin. That part of the discussion is being moved here #1374116: Move bundle CRUD API out of Field API

I'm still very interested in comments on my approach.

EclipseGc’s picture

Ok, so I'm going to weigh in at this point with my own vision of how these things should be working.

In essence, a lot of this is over complicating the mission I'm on, so perhaps I can clarify that as a starting point and we can all start to move together towards a shared end goal. One of drupal's primary problems today is the fact that people go all cowboy on getting their content on a page. That's fine during the early life time of a tool, but 10 years in and we need to start adding some structured bits here to give everyone the ability to work with the same goals in mind.

What do you mean?

Great question! So, Crell's laid a lot of this out with his whole "dependency injection" desires, and that's great, but I want us to go a little further. What I mean by this is that we need a standardized wrapper for the output of all information on the screen. I don't care if we're discussing administration forms, nodes, users, individual fields on an entity... if it's output of any sort, we need it to conform to a stricter wrapper methodology. This is OBVIOUSLY block. And with that statement made you can probably see why blocks are not entities to me. Yes blocks can certainly display entities, and having a block plugin that allows you to add fields to it directly might be an awesome idea, but that's a rather small corner of the bazaar I'd like us to agree to build.

What does that look like?

It's actually not all that complicated, and really in a lot of ways blocks get simpler, not more complicated. What I mean by this is that a block becomes self contained, its bits and pieces are all in one place and thus easier to find and grok. Any display of a block on a page is just an instance of the class that represents what you want (with a configuration object specific to the instance you've requested). That means that a block never needs to know where it appears (i.e. region, weight, etc) we need a wrapper that knows these things and really THIS is where the complexity lives. This model easily allows us to display the same block (with even the same configuration) multiple times in a single layout, and bingo, that's one big core issue we all hate gone. More over this implies that "layout" probably needs to be separate from "theme" and in a lot of ways this is beneficial. This also doesn't preclude themes from providing layouts, it just means that layouts are reusable across themes, and really things like responsive design, grid themes, and other such innovations become unlocked from a given theme and instead are locked to the layouts.

How do we get there?

In a word, WSCCI. We get there by actually focusing on the initiatives and devoting our time and resources there. Understand, we all want to see our improvements get into core, and I understand the official "company line" is that you don't need to contribute to the initiative that your improvements might be in to get it in, but the initiatives have a serious chance of simply failing if people don't commit to them. I want to see plugins in core, I want to see a more robust and capable block system in core, I want to see dependency injected content everywhere. I deal with drupal at THAT level every day, and I'm constantly hacking around core's inconsistencies and general lack of respect for the fact that its administration (for example) should be WAY more generic. I don't get improvements for any of that stuff if the community doesn't buy into and contribute to wscci and the plugin architecture contained therein. So I would like to respectfully request that improvements to the block system go somewhere along the lines of what I've outlined here, and that it be done in a wscci branch that is attempted to keep merged with where Crell is headed.

DjebbZ’s picture

Arriving late here thanks to Crell's tweet. I must admit that I completely agree with EclipseGC.

Remember the usability study of Drupal 7 ? For non-Drupal people (aka normal people :p), everything that appears in a page is a piece of content, whether it's a menu, a core block, a node, a views' block, etc. And we already have core entities like nodes that represent very well the concept of content. And nodes (as entities in general) are very flexible : fieldable, with build modes, an extensive api for manipulation at all every step possible, etc. Why introduce yet another type of content when nodes and other entities already do the job ? Why make the hierarchy between nodes as first class citizen for content and blocks as second class content even more complex ? EclipseGC proposal really simplifies the problem : don't use blocks as a mean of creating bastard and low quality Drupal content. At all. But make blocks a wrapper for all other content in Drupal, and so agnostic that it can be used in every way possible. It will really help these "normal" people as well as Drupal developers, because basically the approach at the end user/site builder level and at the developer level is EXACTLY the same. We pull blocks of content and put them in a page.

Edit : typo (I think so...)

@EclipseGC : Question. What do you mean exactly by "layouts", especially

"layout" probably needs to be separate from "theme" and in a lot of ways this is beneficial

I don't really get the idea.

Personal opinion : your comment about WSCCI is so right to my eyes. To me, WSCCI is what will reconcile developers (like me) with Drupal, make it stay on top, and even shine brighter than ever. Without WSCCI, I don't give Drupal a long lifespan...

Crell’s picture

I think there's an even deeper question here. To a casual user/editor/content creator, "content" is the page, and they throw stuff onto their page canvas until it's what they want, because that's what they did in Dreamweaver and Frontpage.

To a CMS, "content" is, well, abstract data, which then gets displayed. What is then shown on screen is various facets and subsets and orders OF that data.

I think nowhere is that more clear than in the dual meaning of "Content types". Core uses that for node sub-types, a data abstraction. Panels uses it for "thingie on the page".

It's really easy to then turn around and say "oh, well, that means content (stuff on the page) should map directly to content (abstracted data), because that's what new users expect." (I.e., blocks should be entities.)

That statement is also, quite simply, WRONG. That statement is "users expect FrontPage, so we should redesign Drupal to be FrontPage." As in, not a CMS, but a server-side hosted HTML GUI. That is not, never has been, nor ever should be, Drupal's role in life. There are other tools for that. Like, say, FrontPage. :-)

The real question we should be asking is "how do we bridge the gap between 'I see stuff on the page' and 'I have stuff in my data store'," that is, how do we help users to understand the distinction, not how do we eliminate the distinction.

And that is primarily a UX question, not an engineering question, which is why it should be discussed in a UX thread. Like, say, this one: http://groups.drupal.org/node/199938 :-)

(And also, "What EclipseGc said".)

EclipseGc’s picture

Just to clarify a few points, in case I muddied the waters. I'm not against "custom blocks" as entities. This isn't a bad notion really, in fact it makes a great deal of sense to me. My objective here is to provide a plugin foundation capable enough to handle it.

@DjebbZ

Reduce a theme down to it's most basic components and you end up with a handful of things. We have essentially the CSS that styles it, any JS specific to it, Images it might utilize, and then the HTML output. The HTML in the form of tpl.php files are essentially overrides of core's existing tpl files, for whatever purpose. This goes off mostly without a hitch because in truth, your node override, or cart, or form or whatever are really specific to the theme, however this doesn't hold true with the layout... i.e. "regions". Every theme (excluding those that share a common base) have "layout" code (generally html and CSS, occasionally some js as well). When you switch themes, this all goes to hell in a hand basket and you get to rebuild the block layout for your site (by whatever method you might be using). This is not true in panels-land though, and that notion is a good one for Drupal core. It separates the "regions" code from the styling of the theme itself and allows us to leverage the same layout across as many different themes as we would like. This is what I'm proposing, and it's for a number of reasons beyond those I've already laid out. Chief amongst these reasons is block placement. Blocks really shouldn't keep track of where they appear, a given layout should keep track of what block instances should appear within it and where. This simplifies a block significantly (no more region and weight tracking) which also removes some of the issues we've had surrounding multiple instances of the same block.

Hopefully this answers your question.

Eclipse

joachim’s picture

I like the sound of this, and I like the sound of making blocks be just dumb wrappers that show something.

So you'd add a block and tell it where you want it shown, and then you'd then pick what you want it to show. What we currently think of as 'blocks' would become plugins, eg the 'who's online' plugin, the 'menu block' plugin. And the 'show this content' plugin.

> And nodes (as entities in general) are very flexible : fieldable, with build modes, an extensive api for manipulation at all every step possible, etc. Why introduce yet another type of content when nodes and other entities already do the job ?

A big case for having a separate entity to put into blocks (into the 'show this content' plugin) is that you don't want them to have paths. Eg, the fragment of editable content that sits at the top of your landing page shouldn't also pop up at node/1234. And also that that fragment doesn't need to be commentable, votable, or anything else like that.

DjebbZ’s picture

@EclipseGc : crystal clear. I see the parallel with Panels. Reusable layouts is a good idea. Thanks !

@joachin : indeed, there's a need for these small pieces of content, that nodes don't address directly because they're too big (path, commentable, votable etc.). The thing is that, apart from the path, everything you said is an option in a node : comments and votes are not mandatory at all. Most of contrib use the concept of node type to specify which kind of content to enhance with their own functionality. If the path is the only blocker, making it an option in the content type form could work. So that Drupal would ship with a content type named "block" (naming to be defined) that would represent this kind of fragment of content. I don't know how much refactoring node module need to make optional hard-coded path thing.

The thing is, even without a node view path (node/1234), this fragment of content still needs (from a WSCCI perspective) to be reachable by a web service. We don't want some content to be imprisoned in Drupal. We need even the small fragment of text to be accessible from {whatever-but-surely-node}/1234 with a HTTP header like Content type : application/json. So basically, removing the path option as I said above should just remove the node view page, but keep the core url for web services.

Edit : added the last paragraph

David_Rothstein’s picture

The discussion from the last couple of comments (custom blocks vs. nodes, and whether they need to have a path) has already been going on for a while at #1164718: Improving the usability between "custom block" and "content", so I suggest you comment there...

@DjebbZ's point about needing a URL for web services is an interesting one, so I just linked to it from that issue now.

sun’s picture

This is what I'm proposing, and it's for a number of reasons beyond those I've already laid out. Chief amongst these reasons is block placement. Blocks really shouldn't keep track of where they appear, a given layout should keep track of what block instances should appear within it and where. This simplifies a block significantly (no more region and weight tracking) which also removes some of the issues we've had surrounding multiple instances of the same block.

Sorry, but I feel a need to clarify matters: This merely moves the code that tracks which block is supposed to appear where and in which theme to somewhere else. I understand that the primary idea is to separate concepts, and that there's ultimately going to be just one instance of a block - possibly being used in multiple themes - and that this is going to untangle the current concept of "blocks", but ultimately, it just moves code around.

Also, I understand that there is a good chunk of people who favor the "Panels way of populating individual, independent pages", but I want to stress on the fact that there's a similarly large crowd of people having or dealing with sites for which that use-case does not apply. Based on what I've seen and learned on Drupal events and in drupal.org issues, the latter crowd is - despite being large - not "developer-ish" and thus, typically underrepresented in discussions like this.

Aside from that, I'm eager to to see more review-able results in your sandbox and potentially get my hands dirty on that with you.

That said, based on what I've seen so far, it seems like it would really be helpful to get a major drive forward and find a solution for #1290658: Move all module-provided classes to PHP namespaces (PSR-0 or similar), and autoload them without the registry [policy, no patch], as it seems to be a huge blocker for all "plugin"-related issues (like this). That is, because given a solution there, I'd like to see an actual core patch for the proposed Block system changes here (to untangle them from other WSCCI changes, which we badly need to do).

EclipseGc’s picture

@sun,

I'm going to leave the discussion on layout stuff till the end of this post because I REALLY want to focus on the other things you said. Namely +1000000000000. The whole plugin system resides in wscci right now, and wscci can benefit from it majorly, but I'm not sure it needs to be part of the main wscci commit. I think it could go in earlier as long as all the major parties are on the same page as to its components. I look forward to working with you on all of this stuff.

In regard to layouts, yes we move the logic a bit, but it has a bigger effect in these ways:

  1. Layouts tracking block placement (instead of the other way around) means that the same block can have multiple instances in a single layout.
  2. Layout separation from Themes means we don't track blocks per theme, we track them per layout.
  3. Layouts can be switched when themes change but that's not actually the default response in this model.

All of this means that we actually end up with sites whose themes can be changed at any time w/o the need to rebuild all of our block placement, but it doesn't preclude us from having theme specific block placement if we want it. I understand there's some concern about the "panels approach" and I take no offense to that comment, but the objective here is not to rebuild panels, but to learn from what it's done and evaluate our other failings and come up with a solution. I think both sets of concerns can be addressed in the long run and that's all I'm trying to say.

Crell’s picture

For historical accuracy: Plugins are being developed under the WSCCI umbrella with the intent that they be used for other stuff in WSCCI, but the intent from the very beginning has always been that they can be committed to core before the big routing/layout changes happen. There's plenty of other things that plugins are good for that can and should be worked on in parallel.

mjreich’s picture

Thought it might be worth chiming in to this discussion with a timely project. We’re working with a client to develop a D7 solution to the per-page layout problem, and are touching on a couple of the major areas that are being discussed here and and on the WSCCI threads, including block instances, layouts, web services, mobile/responsive design. We have initial agreement from the client to contribute the work we’re doing, so hopefully this can be helpful in providing an demonstration approach for some of the issues/approaches being talked about here.

The high level goal of the project is provide a streamlined workflow for creating per-page layouts. As part of the project, we did an assessment of the current D7 solutions, focusing mainly on Panels/Panelizer. The question was whether we could simplify the Panels architecture/workflow in a way that would be easy to understand for users, while also opening up the underlying module API to allow for different Layout UXs. I’m happy to post the detailed assessment if people would find if useful.

Because of some of the particulars of this project, the decision was made to try a new approach to this functionality and create a Layouts system core from the ground up. We’re a couple of sprints into the development and would love to gather feedback on approach, and help this conversation by providing an implementation that closely resembles some of what is being talked about for D8.

Generally, the module architecture is focused on a couple of key ideas.

  1. Layouts

    The core of the project is providing a simple workflow, on a single page, that allows users to assemble a page by dragging different elements into regions of the page. We wanted to reduce the complexity of the system over Panels/Panelizer so that a user doesn’t need to understand the underlying design assumptions drupal makes about page architecture - rather it would ‘just work’. Essentially, Layouts operates as a new display layer on top of themes, overriding the $content variable with the block/region configuration set by the user.

  2. Every ‘page’ is a page

    As @EclipseGc mentioned above, novice users expect Drupal to operate in a different way than it does. They want to be able to ‘edit’ what they see in their browser, and customize the page look-and-feel without having to come to the development team. In the site IA, we’re trying to use editable nodes wherever possible to ensure that there is something to edit. Custom functionality is always a block (see next point).

  3. Everything is a block

    We made the decision, from the UX perspective, to treat every chunk of content on the page as a block. The attempt here is to treat blocks as the base unit of page construction, and give users the ability to construct a page, any page, out of blocks. We’re looking at the feasibility of using BEAN to provide some of this functionality.

  4. Block Instance Configuration

    One of the things we’re working on is providing an alternative way to configure blocks from within the Layout user interface. This way, we can reduce the overall number of blocks, and simplify the UX for configuring a page, by providing the configuration options on the same screen as the layout UX. For example, we can create a single block called ‘Node Fields’ that displays the fields for a given node. When a user wants to add a title to the page, they can drag the Node Fields block into the page, then configure the block to display the Node title. This means we don’t have to create separate, essentially static blocks for everything that needs to show up on the page.

Wanted to put this out there to see if we can contribute to the conversation. Its always nice to have a client who is willing to pay for the development of a new approach, and what they need is very similar to what's being talked about on this thread. Pretty quickly we’ll have a fairly complete working version we’re hoping to share (via screencasts if nothing else) with the community. Also happy to provide details on specific technical approaches we've taken if anyone is interested. We'd love to get as much feedback as possible from the community.

yoroy’s picture

mjreich: yes & awesome. Check out our UX vision for Pages and Components if you haven't already: http://groups.drupal.org/node/160144 if you haven't already. And http://groups.drupal.org/node/199938 :)

I feel bad joining this discussion with only a quick snippet, but I haven't done the deep dive yet and only skimmed the conversation. What I'm getting is that the property of 'has path' is one of the most basic distinctions between what is a page and what is a block on that page. Pages have paths, Components don't. An important question seems to be how content in the sense of our current nodes fit into this. They don't :) We're describing Pages as the canvas or container (that has an url you can go to) and Blocks as the main unit for stuff you can put on that page. The current node-based system kinda falls inbetween these two.

My hunch at this moment is that indeed 'all content' should be presented as blocks first, one big bucket with stuff like content items (nodes), slideshow widgets, menus, banners and all the x number of related content, who's online, latest comment listings you might need. Of course we can make sections in that bucket. Individual content items like Articles or Forum posts are the special case in the sense that for these there's a checkbox somewhere that says 'Provide a path so that item of this content type can be requested specifically', meaning 'Automatically provide a page display for this content type'. So yes "blocks as the base unit of page construction" as @mjreich describes it above. Everything is a block, but there are different kinds of blocks. The first important distinction seems to be 'primary content blocks' (meaning these have their own path and thus bring their own Page display, equal to the current 'full node' display mode) vs. 'supporting content blocks', all the widgets that don't necessarily need a path for a 'stand-alone' display.

I realize that any distinction we make here is at some technical level 'arbitrary', but from discussing this with @Crell, that's what we're looking for here: which assumptions/constraints do we wilfully design into this so that people can make sense of it and master the flexibility of all this power under the hood.

moshe weitzman’s picture

@EclipseGC,

Those benefits in your list are all great. But they are pretty easily achieved by introducing a layout concept and then adjusting block module to work with it. We really don't need WSCCI to get there. Leaving that aside, the wscci branch that we have been discussing has none of this 'panels everywhere' code. IMO, we can't commit WSCCI until it realizes this benefit. At commit time, only a few pages should be fully built the modern way. We can do the hundreds of others later. But the full vision has to be expressed. My .02.

EclipseGc’s picture

@Moshe

You'll get no argument from me there, this is why, instead of trying to convince everyone that this is what we should do, I'm just trying to DO IT. Thus far WSCCI has suffered a lot in the sense that it is often very controversial, and this has made a lot of people (understandably) gun shy about trying to produce working code. I am not a one many army, I probably can't do all of this myself, but I will do my best to continue showing how these things work with legitimate examples, and see who else I can pull on board.

In short I think your .02 is right on the money, but the only way I see of succeeding here is by doing. Thus our do-ocracy :-)

@mjreich

Sort of off topic for this thread (then again so am I in general I guess) but I'd really suggest against doing that. There's a lot of architecture sitting under Page_manager/Panels/Panelizer already, specificly context, and rebuilding that stuff is going to be a lot of pain for you. I'd suggest (if you haven't already) looking at the panels_everywhere module and the In place Editor (IPE) for panels inside the panels module. The IPE has a lot of thought and effort put into it, and it can be extended and even replaced (as I understand it) so chances are, if you're simply unhappy with the UI you might be able to get a lot of bang for buck there w/o reproducing an awful lot of pre-existing work.

Gábor Hojtsy’s picture

Issue tags: +language-content

Tagging for the content handling leg of D8MI.

litwol’s picture

node is content storage medium (abstract to entities), blocks are not. in a way, block is nothing more than a 'node view mode'. nodes have view modes of 'full page', 'teaser', 'search result', 'rss' .... why not introduce new view mode 'block'?

mjreich’s picture

Hi All, follow up to the post I did above and the Layouts announcement from Dries, we've put together a screencast of the latest version of our approach to per-page layouts. (Layouts is the working title for the module, we'll be changing to something final in the near future).

https://vimeo.com/37867040

Thoughts and feedback on the approach will be really helpful. Next steps are to build out functionality on this framework, including:

  • BEAN/Block Intance Configuration in the Layout Builder interface
  • Admin interface for defining layouts and defaults for each entity type
  • Mobile specific layout interface for cutting down which blocks are loaded on mobile devices (compliment for responsive design, not a replacement)

We're hoping to do a BOF at DrupalCon to walk over the final version of the module as well as start a conversation about where this could go for Drupal 8. Let me know if you are interested.

dodorama’s picture

Impressive. Is there a dev version of the module already?

indytechcook’s picture

mjreich, very cool video. Probably best to keep that conversation on the blocks & layouts page now. http://groups.drupal.org/drupal-8-blocks-layouts-everywhere-initiative

Let's try to keep this post on topic now, since I was the one who got it off topic ;)

a1russell’s picture

I just wanted to say that I agree with #111 and think that content and configuration for blocks should be separate. In fact, I created tickets http://drupal.org/node/1183178 and http://drupal.org/node/1183174 to try and raise this issue in contrib. It would be great if this was addressed in core!

gdd’s picture

I talked with EclipseGC a bit about this earlier, and it seems this issue has become part of SCOTCH in all likelihood. So untagging from configuration system and adding scotch.

ardas’s picture

+1000 for making block to be entities.

Here is our feedback on this change:
1. Using all entity features for blocks could be very usefull
2. Having fieldable blocks will provide an easy way to add more fields to blocks that is quite an often task on custom projects
3. Fieldable block data (field values) will be cached in cache_fields and will be read using only one SELECT which will solve the block storage problem - now modules which extend blocks need to store data in their own tables and the result is a lot of separate SELECTs. Now we have blocks, block_roles, block_content, block_custom, block_languages (D8) which means 5 SELECTs to get all information about the block!!!
4. Blocks as entities will receive a JSON exportable feature.
5. An ability to be cached with entity_cache module for high load sites.

Thanks!

sun’s picture

Issue tags: +Plugin system
Gábor Hojtsy’s picture

Anybody want to actually work on this? If custom blocks are neither entities nor config, they will not be translatable or even have language support.

EclipseGc’s picture

Custom blocks as entities is on my list of todos, I think indy is on tap to do most of the entity side and we'll work together to get this squared away.

Eclipse

xjm’s picture

Status: Needs work » Closed (duplicate)
David_Rothstein’s picture

Status: Closed (duplicate) » Needs work

The patch in that issue is currently 420 KB and doesn't yet do anything to convert blocks to entities. And I don't get the impression people want to see it hit 500 KB :)

There are some followup issues (two separate ones) but I'm not sure that really touches on some of the issues here, such as fieldability, etc., or whether that separation is exactly the right one.

#1871696: Convert block instances to configuration entities to resolve architectural issues
#1871772: Convert custom blocks to content entities

tim.plunkett’s picture

This is a duplicate of #1871772: Convert custom blocks to content entities.
That will make them fieldable entities.

xjm’s picture

Status: Needs work » Closed (duplicate)

Yeah the earlier approach doesn't really work anymore after the block/plugin conversion. Edit: which is why I closed this issue in the first place. :) Previously, converting custom blocks to fieldable content entities was part of the blocks-as-plugin's issue's scope, and we've since spun it into the followup Tim linked.

David_Rothstein’s picture

Status: Closed (duplicate) » Needs work

That's custom blocks, not all blocks.

Several people in this issue wanted all blocks to be fieldable (including whoever wrote the issue summary).

Personally, custom blocks only makes sense to me - or more generally, leaving it up to the module which provides the block's content to decide if the content itself is fieldable rather than making the blocks themselves fieldable... partly because that's the way it already works for certain blocks and having fields on top of fields would make my head spin :)

But it would mean in practice that many blocks cannot have fields at all. So I think this should be discussed before closing?

David_Rothstein’s picture

Title: Make blocks entities » Make all blocks fieldable entities

Making the issue title match the issue summary...

tim.plunkett’s picture

I'm not playing status wars, but I would then encourage someone who wants fieldable non-custom blocks to work on #1833872: Allow ConfigEntity types to be fieldable

xjm’s picture

I agree with @tim.plunkett. Can we close this and leave it closed?

David_Rothstein’s picture

Version: 8.x-dev » 9.x-dev

Agreed with the last bullet point, at any rate. Moving to Drupal 9.

I don't see what issue this would be closed in favor of though (would have to be a new one?) and the architectural discussions here do look relevant still.

David_Rothstein’s picture

Issue summary: View changes

Linked comments.

catch’s picture

Status: Needs work » Postponed (maintainer needs more info)
Issue tags: +Needs issue summary update

Even if the discussion is still relevant, the issue summary needs a complete rewrite and this will have multiple dependencies - so moving to 'needs more info'.

EclipseGc’s picture

Title: Make all blocks fieldable entities » Make content blocks fieldable entities

Updating the title to match the intent. Blocks in general should never be fieldable, just a special subclass of them.

Eclipse

plach’s picture

Then we can mark this fixed, I think, as content blocks are fieldable :)

webchick’s picture

Version: 9.x-dev » 8.0.x-dev
Status: Postponed (maintainer needs more info) » Fixed

Agreed, unless I'm missing something.

xandeadx’s picture

@webchick module blocks still can not have fields (i can not add "class field" to any system block, only for custom blocks)

andypost’s picture

Component: block.module » block_content.module

@xandeadx there's special block_content module in core for that

Crell’s picture

xandeadx: Per #197, that's by design, works as intended.

David_Rothstein’s picture

Title: Make content blocks fieldable entities » Make all blocks fieldable entities
Version: 8.0.x-dev » 9.x-dev
Component: block_content.module » block.module
Status: Fixed » Closed (won't fix)

Making all blocks fieldable is exactly what this issue is about (see for example comment #2 and patch #24, plus later patches also).

I'm not really sure the argument for rejecting it, but #1833872: Allow ConfigEntity types to be fieldable was closed as "won't fix" also. This way at least it's clear what the issue is about, and someone can reopen it or propose it again if they want to.

plach’s picture

Makes sense, thanks

Version: 9.x-dev » 9.0.x-dev

The 9.0.x branch will open for development soon, and the placeholder 9.x branch should no longer be used. Only issues that require a new major version should be filed against 9.0.x (for example, removing deprecated code or updating dependency major versions). New developments and disruptive changes that are allowed in a minor version should be filed against 8.9.x, and significant new features will be moved to 9.1.x at committer discretion. For more information see the Allowed changes during the Drupal 8 and 9 release cycles and the Drupal 9.0.0 release plan.