Problem/Motivation

As raised on #1938062-54: Convert the recent_comments block to a view it might be really useful to provide additional dropdown links
on the block overview page.

Some examples could be an edit link for a menu, and edit link for the view, the aggregator feed configuration etc.

Proposed resolution

Add a new method to all block plugin using deriver to add extra operation links.

For menu_ui and views_ui use hook_entity_operation().

Remaining tasks

Update patch, use the one in #183 or #196.
Add test
Add before and after screen shots to the Issue Summary
Add change record
Review
Commit

User interface changes

Before
before patch menu
before patch block

After
after patch menu
after patch block

API changes

Added new \Drupal\Core\Operations\OperationsProviderInterface to add extra opertaion links.

Data model changes

None

Original report by @dawehner

As raised on #1938062-54: Convert the recent_comments block to a view it might be really useful to provide additional dropdown links
on the block overview page.

Some examples could be an edit link for a menu, and edit link for the view, the aggregator feed configuration etc.

CommentFileSizeAuthor
#292 1956134-290.patch23.16 KBMutasim Al-Shoura
#289 1956134-289.patch23.2 KBsmustgrave
#289 interdiff-286-289.txt309 bytessmustgrave
#286 1956134-286.patch23.2 KBsmustgrave
#286 interdiff-283-286.txt879 bytessmustgrave
#283 1956134-283.patch23.27 KBsmustgrave
#283 interdiff-282-283.txt297 bytessmustgrave
#282 1956134-282.patch22.86 KBsmustgrave
#282 interdiff-275-282.txt1.17 KBsmustgrave
#276 After patch.png68.01 KBRinku Jacob 13
#276 Before patch.png50.5 KBRinku Jacob 13
#275 1956134-275.patch21.46 KBsmustgrave
#275 interdiff-269-275.txt6.39 KBsmustgrave
#269 1956134-269.patch24.87 KBsmustgrave
#269 interdiff-264-269.txt9.75 KBsmustgrave
#264 interdiff_261-263.txt790 bytesNitin shrivastava
#264 1956134-263.patch22.63 KBNitin shrivastava
#261 1956134-261.patch22.63 KBsmustgrave
#261 interdiff-259-261.txt895 bytessmustgrave
#259 interdiff-255-259.txt1.16 KBsrilakshmier
#259 1956134-259.patch22.49 KBsrilakshmier
#255 1956134-255.patch22.5 KBsmustgrave
#255 interdiff-253-255.txt5.38 KBsmustgrave
#253 1956134-253.patch22.28 KBsmustgrave
#253 interdiff-251-253.txt2.22 KBsmustgrave
#251 1956134-251.patch22.25 KBsmustgrave
#251 interdiff-249-251.txt4.77 KBsmustgrave
#249 1956134-249.patch21.98 KBsmustgrave
#249 interdiff-247-249.txt5.9 KBsmustgrave
#247 1956134-247.patch20.2 KBsmustgrave
#247 interdiff-241-247.txt6.93 KBsmustgrave
#244 1956134-244.patch20.87 KBsmustgrave
#244 interdiff-243-244.txt325 bytessmustgrave
#243 1956134-243.patch20.43 KBsmustgrave
#243 interdiff-241-243.txt7.19 KBsmustgrave
#241 1956134-241.patch22.14 KBsmustgrave
#241 interdiff-239-241.txt2.38 KBsmustgrave
#239 1956134-239.patch22.77 KBsmustgrave
#239 interidff-237-239.txt3.16 KBsmustgrave
#237 1956134-237.patch22.15 KBsmustgrave
#237 interdiff-235-237.txt1.18 KBsmustgrave
#235 1956134-235.patch21.96 KBsmustgrave
#235 interdiff-233-235.txt2.2 KBsmustgrave
#233 1956134-233.patch22 KBsmustgrave
#233 interdiff-231-233.txt1.24 KBsmustgrave
#231 1956134-231.patch22.01 KBsmustgrave
#231 interdiff-227-231.txt3.81 KBsmustgrave
#229 1956134-229.patch18.89 KBGunjan Rao Naik
#227 1956134-227.patch22.02 KBsmustgrave
#227 interdiff-225-227.txt5.69 KBsmustgrave
#225 1956134-225.patch21.94 KBsmustgrave
#225 interdiff-218-225.txt9.82 KBsmustgrave
#224 1956134-223.patch25.53 KBsmustgrave
#224 interdiff-218-223.txt12.89 KBsmustgrave
interdiff-218-223.txt12.89 KBsmustgrave
1956134-223.patch25.53 KBsmustgrave
#218 1956134-218.patch20.23 KBsmustgrave
#218 interdiff-214-218.txt6.65 KBsmustgrave
#217 afterpatch.jpg13.01 KBgaurav-mathur
#217 beforepatch.jpg4.76 KBgaurav-mathur
#214 1956134-214.patch20.46 KBsmustgrave
#214 interdiff-207-214.txt533 bytessmustgrave
#211 After_patch-Menu-Block.png242.42 KBManibharathi E R
#211 After_patch-custom-block.png243.89 KBManibharathi E R
#211 Before_patch-Menu-Block.png241.01 KBManibharathi E R
#211 Before_patch_Custom-block.png245.68 KBManibharathi E R
#207 1956134-207.patch20.48 KBsmustgrave
#207 interdiff-206-207.txt3.98 KBsmustgrave
#206 1956134-206.patch21.12 KBsmustgrave
#206 interdiff-204-206.txt2.41 KBsmustgrave
#204 1956134-204.patch19.24 KBsmustgrave
#204 1956134-204-tests-only.patch9.42 KBsmustgrave
#204 before_patch_block.png24.52 KBsmustgrave
#204 before_patch_menu.png65.21 KBsmustgrave
#204 after_patch_block.png28.93 KBsmustgrave
#204 after_patch_menu.png86.85 KBsmustgrave
#196 interdiff-193_196.txt631 bytesOscaner
#196 1956134-196.patch13.88 KBOscaner
#193 provide_helpful_editing_links_202001221649.patch5.51 KBOscaner
#191 edit_menu.png19.21 KBOscaner
#191 edit_block_content.png19.61 KBOscaner
#191 provide_helpful_editing_links_202001101129.patch5.55 KBOscaner
#183 1956134-183.patch19.83 KBManuel Garcia
#183 interdiff.txt625 bytesManuel Garcia
#180 provide_helpful_editing-1956134-180.patch19.67 KBjibran
#180 interdiff-11caef.txt2.61 KBjibran
#178 provide_helpful_editing-1956134-178.patch17.06 KBjibran
#178 interdiff-d41d8c.txt11.14 KBjibran
#178 conflict-7d0227.txt2.67 KBjibran
#172 1956134-172.patch6.74 KBdawehner
#167 interdiff-1956134-160-163.txt872 byteslokapujya
#167 interdiff-1956134-160-163.txt872 byteslokapujya
#163 helpful-block-links.163.patch6.71 KBmgifford
#160 helpful-block-links.160.patch7.56 KBjgeryk
#151 helpful-block-links.151.patch7.5 KBlarowlan
#151 interdiff.txt860 byteslarowlan
#149 helpful-block-links.149.patch7.48 KBlarowlan
#147 interdiff-1956134-145.txt1.66 KBlokapujya
#146 1956134-145.patch7.54 KBlokapujya
#146 1956134-145.patch7.54 KBlokapujya
#145 interdiff-1938930-151.txt3.35 KBlokapujya
#145 1938930-151.patch23.65 KBlokapujya
#140 block_links-1956134-140.patch7.21 KBmgifford
#138 interdiff.txt2.06 KBolli
#138 block_links-1956134-138.patch7.18 KBolli
#125 interdiff.txt566 bytesdawehner
#125 block_links-1956134-125.patch7.77 KBdawehner
#123 block_links-1956134-123.patch7.79 KBdawehner
#123 interdiff.txt2.79 KBdawehner
#121 interdiff.txt3.66 KBdawehner
#121 block_links-1956134-121.patch7.85 KBdawehner
#117 block_links-1956134-117.patch8.38 KBdawehner
#113 block-links-1956134.113.patch9.13 KBlarowlan
#113 interdiff.txt3.38 KBlarowlan
#110 block-links-1956134.110.patch7.34 KBlarowlan
#109 interdiff.txt811 byteslarowlan
#109 block-links-1956134.109.patch73.42 KBlarowlan
#107 block-links-1956134.107.patch7.34 KBlarowlan
#107 interdiff.txt605 byteslarowlan
#105 block-links-1956134.105.patch7.34 KBlarowlan
#105 interdiff.txt2.39 KBlarowlan
#99 block-links-1956134.99.patch8.87 KBlarowlan
#99 interdiff.txt2.94 KBlarowlan
#97 block-links-1956134.97.patch7.7 KBlarowlan
#97 Screenshot 2014-09-05 20.17.30.png24.29 KBlarowlan
#93 block_links-1956134.patch5.79 KBdawehner
#88 interdiff-1956134-85-88.txt1.28 KBjbloomfield
#88 block_links-1956134-88.patch5.84 KBjbloomfield
#85 interdiff-1956134-82-85.txt927 bytesjbloomfield
#85 block_links-1956134-85.patch5.86 KBjbloomfield
#82 interdiff-1956134-77-82.txt615 bytesjbloomfield
#82 block_links-1956134-82.patch5.79 KBjbloomfield
#77 block_links-1956134-77.patch5.77 KBjbloomfield
#71 block_links-1956134-71.patch5.73 KBgrisendo
#69 block_links-1956134-69-1.patch5.72 KBgarphy
#67 block_links-1956134-60.patch7.2 KBdawehner
#60 block_links-1956134-60.patch7.2 KBdawehner
#55 Capture.PNG8.53 KBelachlan
#54 drupal-1956134-54.patch7.82 KBafeijo
#47 drupal-1956134-44.patch7.77 KBelachlan
#46 Blocks___Drupal_D8_Dev.png27.82 KBjessebeach
#46 Blocks___Drupal_D8_Dev.png38.22 KBjessebeach
#44 drupal-1956134-43.patch7.77 KBdawehner
#44 interdiff.txt4.51 KBdawehner
#40 Blocks___Drupal_D8_Dev.png34.53 KBjessebeach
#37 1956134-37.patch6.96 KBjibran
#37 interdiff.txt1.04 KBjibran
#33 1956134-33.patch7.19 KBjibran
#33 diff.txt5.19 KBjibran
#30 drupal-1956134-28.patch6.86 KBelachlan
#28 drupal-1956134-28.patch6.87 KBelachlan
#23 drupal-1956134-23.patch6.49 KBdawehner
#12 edit_menu.png17.7 KBxjm
#9 drupal-1956134-9.patch6.64 KBdawehner
#9 interdiff.txt661 bytesdawehner
#7 drupal-1956134-7.patch5.99 KBdawehner

Issue fork drupal-1956134

Command icon Show commands

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

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

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jibran’s picture

Issue tags: +Blocks-Layouts, +Block plugins

Tagging

damiankloip’s picture

At the moment this will be really difficult, as there is no easy/nice way to add to the operation links in list controllers. Me and Gabor were talking about this last week. I think this will be dependent on some sort of operations API?

dawehner’s picture

It seems to be that operations API is way to complex, not sure. You could for sure always add a new method on the Block Interface that allows you to specify some links depending on your block.

damiankloip’s picture

Yeah, that would work ok. I guess that it would be nice if we had this for configuration entities in general.

dawehner’s picture

So basically the entityInterface would get a new method which returns the links in a non-render version (something which can be utilized/tested easily).

Then the listing controller and views could ask the entity to return it's links. On top of that the block entity would ask the block plugin about it's links which then would know how to link to the menu edit link.

I vote to make it as easy as possible that we can shift towards the operations api later.

damiankloip’s picture

Yep, we talked about this is IRC, I think that is a good plan forward. We need to ask this on a per entity level, so we get the flexibility. So probably the getOperations() method on the controller can also ask the entity for it's links. The implementation across entities can get/add this data how they please.

dawehner’s picture

Status: Active » Needs review
FileSize
5.99 KB

Started with some basic and really simple code adding this to the entity and block plugin interface and using it for edit menu links.

Needs review more in like "needs more discussion".

Status: Needs review » Needs work

The last submitted patch, drupal-1956134-7.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
661 bytes
6.64 KB

For sure, views breaks this :)

xjm’s picture

xjm’s picture

Actually, marked that one as a duplicate of this.

xjm’s picture

FileSize
17.7 KB

Here's what this patch does:

edit_menu.png

Two out-of-scope things I noticed:

  • The existing operation links on the block admin page haven't been capitalized yet.
  • The existing links are also missing some context for accessibility and translatability.
xjm’s picture

Issue tags: +Usability

My original suggestion in #1938062-54: Convert the recent_comments block to a view was for the block library page or the block instance editing form rather than the theme/display block instance admin listing, but we should probably consider all of the above and see which are the most helpful and non-confusing.

For custom blocks, I think we might want to make the link say "Edit block content".

dawehner’s picture

I agree that it should be actually on both places? I guess users want to save time, if possible.

Bojhan’s picture

Just wondering, if there is overlap between instance and object settings? E.g. menu instance settings, and menu settings?

klonos’s picture

I think that it is best not to expose the term "instance" the same as it is not a good idea to expose "plugin". How about we have "Edit block"/"Delete block" and "Edit block type"/"Delete block type". Code-wise we'll know that by "type" we actually refer to the respective plugin and UI-wise the non-"type" actions refer to the configurations.

Also, using the term "Delete" all over does not feel right. Perhaps we should use "Remove" when the actual thing is simply removed from where it was placed and reserve "Delete" for when we are actually deleting.

xjm’s picture

I think that it is best not to expose the term "instance" the same as it is not a good idea to expose "plugin". How about we have "Edit block"/"Delete block" and "Edit block type"/"Delete block type"

Agreed about "instance". The problem though is that "block type" is already the bundle (like the content type) of custom blocks. Even if it weren't, it would be "Menu block," "Views block," "Content block," etc.

dawehner’s picture

I'm wondering whether we should add both test coverage for operation links in general + operations links on blocks + the available operation links on menu block?

xjm’s picture

jibran’s picture

#9: drupal-1956134-9.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Usability, +Blocks-Layouts, +Block plugins

The last submitted patch, drupal-1956134-9.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
Issue tags: +VDC
FileSize
6.49 KB

Rerolled. Adding vdc tags just because we add vdc tags to pretty much everything ;)

dawehner’s picture

#23: drupal-1956134-23.patch queued for re-testing.

jessebeach’s picture

+1 to this integration. I half-expected this existed already.

jibran’s picture

#23: drupal-1956134-23.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Usability, +VDC, +Blocks-Layouts, +Block plugins

The last submitted patch, drupal-1956134-23.patch, failed testing.

elachlan’s picture

Status: Needs work » Needs review
FileSize
6.87 KB

Rerolling patch because of error.

dawehner’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Entity/Entity.phpundefined
@@ -530,6 +530,13 @@ public function isTranslatable() {
+  ¶
+  /**
+   * Implements \Drupal\Core\Entity\EntityInterface::getOperationLinks().

+++ b/core/lib/Drupal/Core/Entity/EntityInterface.phpundefined
@@ -323,4 +323,12 @@ public function getNGEntity();
+  public function getOperationLinks();
+  ¶

+++ b/core/modules/block/lib/Drupal/block/BlockBase.phpundefined
@@ -224,4 +224,11 @@ public function submit($form, &$form_state) {
+  ¶
+  /**
+   * Implements \Drupal\block\BlockInterface::getOperationLinks().
+   */

+++ b/core/modules/block/lib/Drupal/block/BlockListController.phpundefined
@@ -240,6 +240,7 @@ public function buildForm(array $form, array &$form_state) {
+		  $links = array();

@@ -248,6 +249,7 @@ public function buildForm(array $form, array &$form_state) {
+		  $links += $entity->getOperationLinks();

+++ b/core/modules/block/lib/Drupal/block/Plugin/Core/Entity/Block.phpundefined
@@ -172,4 +172,13 @@ public function preSave(EntityStorageControllerInterface $storage_controller) {
+   * Implements \Drupal\Core\Entity\EntityInterface::getOperationLinks().

+++ b/core/modules/menu/lib/Drupal/menu/Plugin/Block/MenuBlock.phpundefined
@@ -30,5 +30,19 @@ public function build() {
+  ¶
...
+   * Implements \Drupal\block\BlockInterface::getOperationLinks().

+++ b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemMenuBlock.phpundefined
@@ -42,4 +42,18 @@ public function build() {
+   * Implements \Drupal\block\BlockInterface::getOperationLinks().

+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.phpundefined
@@ -1140,6 +1140,13 @@ public function onChange($property_name) {
+  ¶

Let's provide an @inheritdoc and remove all this kind of whitespace/tabs ...

elachlan’s picture

FileSize
6.86 KB

Removed the white spaces.

Not sure about providing @inheritdoc.

Also when I manually tested it, it seems like the functionality described in #12 did not work.

dawehner’s picture

Why are you not sure about the {@inheritdoc}?

elachlan’s picture

I am new and don't know how to go about doing it.

Where does it need it?

jibran’s picture

Category: feature » task
Status: Needs work » Needs review
FileSize
5.19 KB
7.19 KB

If #1938062: Convert the recent_comments block to a view is block on this how come this is a feature request. Rerolled #23
@elachlan Thank you for contributing to drupal please see https://drupal.org/node/1354#inheritdoc for more info on inheritdoc.

dawehner’s picture

#33: 1956134-33.patch queued for re-testing.

dawehner’s picture

+++ b/core/modules/menu/lib/Drupal/menu/Plugin/Block/MenuBlock.phpundefined
@@ -31,4 +31,18 @@ public function build() {
+   * Implements \Drupal\block\BlockInterface::getOperationLinks().

{@inheritdoc}

Status: Needs review » Needs work

The last submitted patch, 1956134-33.patch, failed testing.

jibran’s picture

Status: Needs work » Needs review
FileSize
1.04 KB
6.96 KB

Reroll and fixed #35.

dawehner’s picture

That allows us to provide better UX, so +1 (though i mostly wrote the code).

afeijo’s picture

Status: Needs review » Reviewed & tested by the community

+1
it is very nice to have that handy Edit link there!
(I had to ccache and save the blocks page to reflect it)

jessebeach’s picture

FileSize
34.53 KB

I applied the patch in #37 and cleared cache; saw no change. I reinstalled; saw no change. This is what I'm seeing for the recent comments View block.

Blocks___Drupal_D8_Dev.png

I'm a little lost as to what I should do to see a change. Hint?

afeijo’s picture

@jessebeach
did you try what I wrote? save the blocks admin page, no need to change anything
after I did that, the page noticed the new menu items

dawehner’s picture

Status: Reviewed & tested by the community » Needs work
jessebeach’s picture

@afeijo, I just tried that and I saw no change. Is there some file I could put a breakpoint in to verify that the code is running correctly or not?

dawehner’s picture

Status: Needs work » Needs review
FileSize
4.51 KB
7.77 KB

This time it even works.

afeijo’s picture

Status: Needs review » Reviewed & tested by the community

Yay, now I just need to apply the patch, hit F5, and the Operations buttons show the Edit menu link

I did it 3 times with git reset --hard, F5 (gone), git apply -v {patch file}, F5 (show)

jessebeach’s picture

Alright! I'm getting an "Edit menu" option for my custom menu and the build-in menus.

Blocks___Drupal_D8_Dev.png

"Edit menu" should be lowercase as "edit menu" to follow the pattern currently established in the list of operations.

I'm still not seeing an option to edit a view on the the "Recent comments" view block.

Blocks___Drupal_D8_Dev.png

elachlan’s picture

FileSize
7.77 KB

Changed to lower case.

elachlan’s picture

Status: Reviewed & tested by the community » Needs work
dawehner’s picture

I thought we decided somewhere to use uppercase for new links?

jessebeach’s picture

I thought we decided somewhere to use uppercase for new links?

Perhaps, but I'd rather keep consistent with the pattern that's there now, even if it's the wrong one. Being inconsistent looks worse than capitalized or uncapitalized.

Bojhan’s picture

Capitalised is the new standard.

afeijo’s picture

I'd love to do the patch to capitalize all labels

May I? In this issue or a new one?

elachlan’s picture

afeijo, just do it in this issue for the ones relevant to the menu we are working on.

afeijo’s picture

Status: Needs work » Needs review
FileSize
7.82 KB

Here it is, elachlan :)

elachlan’s picture

FileSize
8.53 KB

Looks good! Test passed.

screencap

elachlan’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Needs a reroll...

curl https://drupal.org/files/drupal-1956134-54.patch | git apply --check
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8006  100  8006    0     0   3600      0  0:00:02  0:00:02 --:--:--  4649
error: patch failed: core/modules/block/lib/Drupal/block/BlockListController.php:240
error: core/modules/block/lib/Drupal/block/BlockListController.php: patch does not apply
elachlan’s picture

Issue tags: -Usability, -VDC

I believe the problems with BlockListController.php are caused by the changes done in #2027857: Blocks operations cannot be altered

It added this:

/**
   * {@inheritdoc}
   */
  public function getOperations(EntityInterface $entity) {
    $uri = $entity->uri();
    $operations = array();
    $operations['configure'] = array(
      'title' => t('configure'),
      'href' => $uri['path'],
      'options' => $uri['options'],
    );
    $operations['delete'] = array(
      'title' => t('delete'),
      'href' => $uri['path'] . '/delete',
      'options' => $uri['options'],
    );

    return $operations;
  }

So I think we just have to change that instead.

elachlan’s picture

Issue tags: +Usability, +VDC

I don't know why the tags were removed.

dawehner’s picture

Status: Needs work » Needs review
FileSize
7.2 KB

There we go.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

This patch has a complete lack of tests.

+++ b/core/modules/system/lib/Drupal/system/Plugin/Core/Entity/Menu.phpundefined
@@ -60,4 +60,16 @@ class Menu extends ConfigEntityBase implements MenuInterface {
+    if (user_access('administer menu')) {

We should not be using user_access here anymore. We probably will have to use Drupal::request() here but that's better than calling out to user_access().

+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.phpundefined
@@ -1243,4 +1243,12 @@ public function mergeDefaultDisplaysOptions() {
+  public function getOperationLinks() {
+    return $this->storage->getOperationLinks();
+  }

AFAICS there is no getOperationLinks() method on Drupal\views\Plugin\Core\Entity\View

dawehner’s picture

AFAICS there is no getOperationLinks() method on Drupal\views\Plugin\Core\Entity\View

The ViewUI class is a decorator around entites, so everytime you add new methods, you have to implement that. In general I would like to see some views related links on the View entity object.

jibran’s picture

Status: Needs work » Needs review
Issue tags: -Usability, -Needs tests, -VDC, -Blocks-Layouts, -Block plugins

#60: block_links-1956134-60.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Usability, +Needs tests, +VDC, +Blocks-Layouts, +Block plugins

The last submitted patch, block_links-1956134-60.patch, failed testing.

jibran’s picture

Issue tags: +Needs reroll

Needs reroll as per #65.

dawehner’s picture

Status: Needs work » Needs review
FileSize
7.2 KB

just a rerole, there are no tests yet.

Status: Needs review » Needs work

The last submitted patch, block_links-1956134-60.patch, failed testing.

garphy’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
5.72 KB

Rerolled.

benjy’s picture

Issue summary: View changes
Status: Needs review » Needs work
Issue tags: +Needs reroll

Needs a reroll

grisendo’s picture

Status: Needs work » Needs review
FileSize
5.73 KB

Rerolled

andypost’s picture

custom block have no 'edit/configure' link now, seeps this hunk could be added here

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

custom block have no 'edit/configure' link now, seeps this hunk could be added here

Yeah, let's open a follow up for that.

andypost’s picture

star-szr’s picture

Status: Reviewed & tested by the community » Needs work

Tagging for reroll.

jbloomfield’s picture

Assigned: Unassigned » jbloomfield

Attempting a patch re-roll.

jbloomfield’s picture

Assigned: jbloomfield » Unassigned
Status: Needs work » Needs review
FileSize
5.77 KB

Re-rolled patch.

First time so be nice :)

benjy’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Entity.php
    @@ -397,5 +397,12 @@ protected function routeProvider() {
    +  ¶
    

    remove white space.

  2. +++ b/core/modules/system/lib/Drupal/system/Entity/Menu.php
    @@ -90,4 +90,16 @@ public function isLocked() {
    +    if (user_access('administer menu')) {
    

    Should be \Drupal::currentUser()->hasPermission()

  3. +++ b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemMenuBlock.php
    @@ -42,4 +45,18 @@ public function build() {
    +    list(, $menu) = explode(':', $this->getPluginId());
    

    Maybe we should add a @todo to replace once http://drupal.org/node/1874498 lands.

jbloomfield’s picture

Hi benjy,

As I am new to this, is it up to me to fix your changes above or the original patch creator? I don't mind either way, I was just doing my first patch re-roll.

Cheers
John.

dawehner’s picture

As I am new to this, is it up to me to fix your changes above or the original patch creator? I don't mind either way, I was just doing my first patch re-roll.

There is no rule at all, who has to fix things. If you can fix those, please do it. Thank you!

jbloomfield’s picture

Assigned: Unassigned » jbloomfield

Will do, thanks.

Patch Re-roll.

jbloomfield’s picture

Assigned: jbloomfield » Unassigned
FileSize
5.79 KB
615 bytes

Re-rolled the patch and also created an interdiff.

There are already @todo's throughout the file mentioned below.

+++ b/core/modules/system/lib/Drupal/system/Plugin/Block/SystemMenuBlock.php  
jbloomfield’s picture

Benjy, sorry I have just spotted what you meant about the @todo.

In the public function getOperationLinks() it needs one. I will re-roll another patch later tonight.

jbloomfield’s picture

Assigned: Unassigned » jbloomfield
Status: Needs review » Active

Will re-roll another patch to add a @todo.

jbloomfield’s picture

Assigned: jbloomfield » Unassigned
Status: Active » Needs review
FileSize
5.86 KB
927 bytes

Re-rolled patch again to add a @todo.

jbloomfield’s picture

Issue tags: -Needs reroll

Removed "Needs reroll" tag

jbloomfield’s picture

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

Ok, so I have tested this on a fresh D8 install and the "Edit Menu" link fails.

It goes to a path of "/admin/structure/menu/manage/admin/edit"

The actual path should be "/admin/structure/menu/manage/admin"

Will fix the "Edit Menu" link.

jbloomfield’s picture

Assigned: jbloomfield » Unassigned
Status: Needs work » Needs review
FileSize
5.84 KB
1.28 KB

Fixed the "Edit Menu" path.

New patch and interdiff.

tim.plunkett’s picture

dawehner’s picture

88: block_links-1956134-88.patch queued for re-testing.

The last submitted patch, 88: block_links-1956134-88.patch, failed testing.

klonos’s picture

dawehner’s picture

Status: Needs work » Needs review
FileSize
5.79 KB

Reroll.

Status: Needs review » Needs work

The last submitted patch, 93: block_links-1956134.patch, failed testing.

larowlan’s picture

Assigned: Unassigned » larowlan

rerolling

larowlan’s picture

Assigned: larowlan » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
24.29 KB
7.7 KB

Not sure where the changes to Menu entity came in, removed them.
Added some tests.
Screenshot

dawehner’s picture

Thank you so much for the reroll!

  1. +++ b/core/lib/Drupal/Core/Block/BlockPluginInterface.php
    @@ -174,4 +174,12 @@ public function getVisibilityCondition($instance_id);
    +  /**
    +   * Returns a list of operation links available for this block.
    +   *
    +   * @return array
    +   *   Array of operation links.
    +   */
    +  public function getOperationLinks();
    

    I wonder whether we should extract the operation links interface from blocks and entities into a generic one?

  2. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
    @@ -134,4 +145,24 @@ protected function getRequiredCacheContexts() {
    +      $links['menu-edit'] = array(
    +        'title' => $this->t('Edit menu'),
    +        'route_name' => 'menu_ui.menu_edit',
    +        'route_parameters' => array(
    +          'menu' => $menu,
    +        ),
    +        'weight' => 50,
    +      );
    

    On the longrun we could think of using a link object but this would be inconsistent with the other operations for now.

larowlan’s picture

98.1 fixed
98.2 agreed, started off using Url objects but then realised that list builders don't work that way.

Dave Reid’s picture

+++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
@@ -134,4 +145,24 @@ protected function getRequiredCacheContexts() {
+    if ($this->currentUser->hasPermission('administer menu')) {
+      $links['menu-edit'] = array(
+        'title' => $this->t('Edit menu'),
+        'route_name' => 'menu_ui.menu_edit',
+        'route_parameters' => array(
+          'menu' => $menu,
+        ),
+        'weight' => 50,

Seems like extraneous implementer effort here to manually check access here. Could we automatically determine if the user has access to that link based on the route_name and route_parameters provided?

dawehner’s picture

Seems like extraneous implementer effort here to manually check access here. Could we automatically determine if the user has access to that link based on the route_name and route_parameters provided?

We can indeed and we should, see #2302563: Access check Url objects

larowlan’s picture

Status: Needs review » Postponed
Related issues: +#2302563: Access check Url objects
Xano’s picture

What exactly does a BlockPluginInterface do? What are the operations for? If the operations a block instance provides are specific to that instance, then this approach is okay. If the operations are not specific to that instance, but to all instances of that plugin, then we need to let plugins define an operations provider.

In short: plugin instances should have a single task. It's not good if we instantiate plugins for different 'scopes'.

larowlan’s picture

Status: Postponed » Needs work

Blocker is in, needs reroll to remove access check

larowlan’s picture

Status: Needs work » Needs review
FileSize
2.39 KB
7.34 KB

Addresses 100
Re 103: Yes specific to an instance - eg example here applies to specific instance of menu block derivative (SystemMenuBlock) - we have derivative and plugin id in scope.

Status: Needs review » Needs work

The last submitted patch, 105: block-links-1956134.105.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
605 bytes
7.34 KB

Menu route name changed

Status: Needs review » Needs work

The last submitted patch, 107: block-links-1956134.107.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
73.42 KB
811 bytes
larowlan’s picture

Wrong patch

The last submitted patch, 109: block-links-1956134.109.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 110: block-links-1956134.110.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
3.38 KB
9.13 KB

menu ui module doesn't always exist

dawehner’s picture

I am fine with the current status, anyone up for a review?

tim.plunkett’s picture

+++ b/core/lib/Drupal/Core/Block/BlockPluginInterface.php
@@ -26,7 +27,7 @@
-interface BlockPluginInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface, CacheableInterface, DerivativeInspectionInterface {
+interface BlockPluginInterface extends ConfigurablePluginInterface, PluginFormInterface, PluginInspectionInterface, CacheableInterface, DerivativeInspectionInterface, OperationsProviderInterface {

+++ b/core/lib/Drupal/Core/Entity/EntityInterface.php
@@ -12,7 +12,7 @@
+interface EntityInterface extends AccessibleInterface, OperationsProviderInterface {

I can't tell if its just that this patch only does a couple conversions, or if this is all of it, but I'm hesitant to force this on each interface. Why not let the specific classes (or even just the base class) implement it, and add a simple instanceof check to the relevant calls?

larowlan’s picture

Block content will add one (see postponed ref issue)
Views will use it.
We have base implementations for both so there is no work for most plugins.

dawehner’s picture

@tim.plunkett
Great idea!

larowlan’s picture

+1 RTBC, thanks @dawehner

tim.plunkett’s picture

  1. +++ b/core/lib/Drupal/Core/Block/BlockPluginInterface.php
    @@ -12,6 +12,7 @@
    +use Drupal\Core\Entity\OperationsProviderInterface;
    

    This can be removed now.

  2. +++ b/core/lib/Drupal/Core/Entity/OperationsProviderInterface.php
    @@ -0,0 +1,23 @@
    + * Contains \Drupal\Core\Entity\OperationsProviderInterface.
    ...
    + * Defines an interface for providing operations links.
    

    I think either this should be moved out of the Entity namespace, or the description should be much more specific about what it is used for.

  3. +++ b/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php
    @@ -86,6 +88,19 @@ protected function setUp() {
    +      'mail' => 'tony@magicalponies.com',
    

    Currently magicalponies.com is not registered (what an opportunity!) but I think it should be example.com or something just in case :)

larowlan’s picture

@tim.plunkett

  1. Good catch
  2. Sounds reasonable - any suggestions
  3. boo - but yeah
dawehner’s picture

Thank you for the review!

Currently magicalponies.com is not registered (what an opportunity!) but I think it should be example.com or something just in case :)

Meh.

tim.plunkett’s picture

+++ b/core/modules/block/src/Entity/Block.php
@@ -42,7 +42,7 @@
+class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginBagsInterface, \Drupal\Core\Operations\OperationsProviderInterface {

@@ -181,7 +181,7 @@ public function getVisibility() {
+    if ($plugin instanceof \Drupal\Core\Operations\OperationsProviderInterface) {

PHPStorm--

dawehner’s picture

meh!!!! SO yeah, why does storm not solve all the problems!

Wim Leers’s picture

Status: Needs review » Needs work

This very much reminds me of contextual links. So:

  1. Why doesn't this just use the contextual links system (of ContextualLinkManager + *.links.contextual.yml, rather than creating a similar (I'd say parallel) system?
  2. Alternatively, why isn't the contextual links system removed in favor of this one, so that contextual links also uses OperationsProviderInterface?
  3. The contextual links system allows other modules to define new operations. This doesn't AFAICT. That prevents us from adding e.g. a Translate operation. Isn't that a problem?

Code review

Just one stupid nitpick:

+++ b/core/modules/block/src/Entity/Block.php
@@ -41,7 +42,7 @@
+class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginBagsInterface, \Drupal\Core\Operations\OperationsProviderInterface {

No need for a fully qualified class here.

dawehner’s picture

Status: Needs work » Needs review
FileSize
7.77 KB
566 bytes

@Wim Leers
Thank you for your review.

So you back to the almighty operations API which will just be impossible to solve. Note: This patch just exposes entity operations onto plugins.
Everyone would love to have one, which would allow you to configure which contextual links / entity operations / sibling local tasks you want to see, but yeah I don't think this is feasible at least in 8.0.x
For example noone came up with an idea how to support things like creation links.

No need for a fully qualified class here.

storm--

Wim Leers’s picture

For example noone came up with an idea how to support things like creation links.

But that's not an operation on an existing thing, so … I don't see why that's needed?

I know that my question kind of leads to the "almighty operations API" discussion, but OTOH, we want to make sure we don't have two ways for doing the same thing. And this is even worse: it forces us to define the same things twice! Contextual links *are* for operations after all — I'd argue it should be renamed to Operation Links in D9.
So while I don't want to slow things down unnecessarily, I think it's essential to have a discussion here about contextual links. I don't understand how this issue could've come to comment 125 without having discussed contextual links at all? :/

Conclusion: Am I missing something, or why can't we reuse *.contextual.links.yml for these operation links?

dawehner’s picture

@Wim Leers
Maybe I don't 100% get your point.

Conclusion: Am I missing something, or why can't we reuse *.contextual.links.yml for these operation links?

Well, mostly because these links are used as part of the entity listing as well, admin/structure/block is the one you will look at. Do you really want to rewrite all of the operations
in core to support contextual links as part of this issue? On top of that contextual links are tight to a specific visual representation atm. which we will need to decouple in order to make this happen.

Wim Leers’s picture

On top of that contextual links are tight to a specific visual representation atm. which we will need to decouple in order to make this happen.

Oh! I think I know see why you misunderstand me :)

I didn't mean use contextual links at admin/structure/block to provide operations links, I meant use the data that powers contextual links at admin/structure/block to provide operations links!

I think the data in *.links.contextual.yml is directly reusable?

dawehner’s picture

Oh I see, well on an abstract level you certainly could. On a congrete level this would require a lot of work, as for example you would have to provide multiple groups: one for the entity type, and one for the entity type together with the specific block plugin.

Wim Leers’s picture

But the "multiple groups" thing is already the case for contextual links and works fine there, right?

olli’s picture

Couldn't find an issue to add an "Edit view" link so I filed #2346285: Provide 'Edit view' link on "admin/structure/block".

olli’s picture

So, what is the way forward here? Is #125 the one to review?

Not sure how #126-#130 would work but adding an "Edit view" link on top of #125 in ViewsBlockBase was easy even for me =). Would it be possible to have a similar method that would automatically add contextual links for my block? Even without adding them in *.links.contextual.yml?

Xano’s picture

OperationsProviderInterface was already added elsewhere, but no code in core uses it yet. I opened #2398601: Improve OperationsProviderInterface to improve on what we have now.

dawehner’s picture

@olli
Yes, this is what we need at that given point in time. At the same time I would bet that we need a reroll as well.

Status: Needs review » Needs work

The last submitted patch, 125: block_links-1956134-125.patch, failed testing.

dawehner’s picture

Issue tags: +Needs reroll

.

olli’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
7.18 KB
2.06 KB

Here's a reroll.

olli’s picture

  1. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
    @@ -211,4 +223,21 @@ protected function getRequiredCacheContexts() {
    +    if ($this->moduleHandler->moduleExists('menu_ui')) {
    +      $links['menu-edit'] = [
    +        'title' => $this->t('Edit menu'),
    +        'url' => Url::fromRoute('entity.menu.edit_form', ['menu' => $menu]),
    

    Would it be possible to load the menu and check if it has an edit-form link rather than checking moduleExists()? Also, shouldn't this check if user can access the url or edit the menu?

  2. +++ b/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php
    @@ -173,6 +189,14 @@ public function testSystemMenuBlockConfigDependencies() {
    +    $links = $block->getOperationLinks();
    +    $menu_link = [
    +      'title' => 'Edit menu',
    +      'url' => Url::fromRoute('entity.menu.edit_form', ['menu' => $this->menu->id()]),
    +      'weight' => 50,
    +    ];
    +    $this->assertEqual($links, ['menu-edit' => $menu_link]);
    

    How about adding another method to test getOperationLinks?

mgifford’s picture

this should be a straight re-roll.

RavindraSingh’s picture

  • +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
    @@ -54,11 +62,14 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
    +  public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $menu_active_trail, ModuleHandlerInterface $module_handler) {
    

    Line needs to break after if chars count > 80

  • +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
    @@ -211,4 +223,21 @@ protected function getRequiredCacheContexts() {
    +
    

    Remove White Space

  • tim.plunkett’s picture

    Disregard the first part of #141. It's an 80 character limit but for comments.

    RavindraSingh’s picture

    Oh yes, it is 80. Corrected

    tim.plunkett’s picture

    Regardless, we don't break lines of PHP no matter how long they are.

    lokapujya’s picture

    Moved the test to it's own method.

    So, we don't need the viewsUI operation links in this patch that was removed in #117?

    lokapujya’s picture

    FileSize
    7.54 KB
    7.54 KB

    Wrong patch. Redo.

    lokapujya’s picture

    FileSize
    1.66 KB

    and the interdiff.

    dawehner’s picture

    Great work!. It is good to see, that this issue got momentum again.

    I would love to see edit links to views but we can for sure do that later as well.

    larowlan’s picture

    re-roll - I think this is rtbc now but have worked on it a few times, so disqualified

    andypost’s picture

    Patch looks great, except one nit.
    RTBC +1

    +++ b/core/modules/system/src/Tests/Block/SystemMenuBlockTest.php
    @@ -177,6 +193,27 @@ public function testSystemMenuBlockConfigDependencies() {
    +  public function testOperationLinks() {
    +
    +    $block = entity_create('block', array(
    

    extra line is not needed, also use Block::create() according #2225347: [META] Replace calls to ENTITY_TYPE_load() and ENTITY_TYPE_load_multiple() with static method calls

    larowlan’s picture

    fixes #150

    andypost’s picture

    Status: Needs review » Reviewed & tested by the community

    Thanx :)

    Wim Leers’s picture

    Status: Reviewed & tested by the community » Needs review
    +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
    @@ -205,4 +217,21 @@ protected function getRequiredCacheContexts() {
    +  public function getOperationLinks() {
    +    $menu = $this->getDerivativeId();
    +
    +    $links = [];
    +    if ($this->moduleHandler->moduleExists('menu_ui')) {
    +      $links['menu-edit'] = [
    +        'title' => $this->t('Edit menu'),
    +        'url' => Url::fromRoute('entity.menu.edit_form', ['menu' => $menu]),
    +        'weight' => 50,
    +      ];
    +    }
    +    return $links;
    +  }
    

    Seeing this made me wonder: "how is this different than contextual links?".

    … turns out I wondered the same 6 months ago. See #124#132.

    Sorry, but I really think we should formulate a proper answer to that. I imagine a committer would ask that question too.

    mgifford’s picture

    Who is best to formulate a proper answer to "how is this different than contextual links?"

    Just nudging this issue as it's been sitting here for 4 months. Can someone get assigned to look at this?

    dawehner’s picture

    Seeing this made me wonder: "how is this different than contextual links?".

    … turns out I wondered the same 6 months ago. See #124 — #132.

    Sorry, but I really think we should formulate a proper answer to that. I imagine a committer would ask that question too.

    Well, this is not only about your loved contextual links but also about links on the block UI.

    Status: Needs review » Needs work

    The last submitted patch, 151: helpful-block-links.151.patch, failed testing.

    MattA’s picture

    Issue tags: +Needs reroll

    Didn't think so...

    jgeryk’s picture

    Assigned: Unassigned » jgeryk

    Going to reroll

    jgeryk’s picture

    Assigned: jgeryk » Unassigned
    Issue tags: -Needs reroll
    FileSize
    7.56 KB

    rerolled

    MattA’s picture

    Status: Needs work » Needs review
    EclipseGc’s picture

    Status: Needs review » Needs work
    +++ b/core/modules/block/src/BlockListBuilder.php
    @@ -342,6 +343,10 @@ public function getDefaultOperations(EntityInterface $entity) {
    +    if ($entity instanceof OperationsProviderInterface) {
    +      $operations += $entity->getOperationLinks();
    +    }
    +
    
    +++ b/core/modules/block/src/Entity/Block.php
    @@ -54,7 +55,7 @@
    +class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginCollectionInterface, OperationsProviderInterface {
    

    This seems completely unnecessary to me. The block entity can have this method without needing some instanceof check. If we want to implement the interface explicitly on the entity, that's fine (or have BlockInterface extend it), but the ListBuilder certainly doesn't need to explicitly check. We know this is part of the contract.

    The rest of this patch seems pretty straight forward and obvious. Having plugins implement the interface (and subsequent instanceof checks as appropriate) is super sensible. Likewise, to Wim's question, it seems to me as though the contextual links code should probably call this as well.

    Eclipse

    mgifford’s picture

    Status: Needs work » Needs review
    FileSize
    6.71 KB

    Ok, then we should be able to nix this too.

    +use Drupal\Core\Operations\OperationsProviderInterface;

    andypost’s picture

    1. diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php
      old mode 100644
      new mode 100755
      

      not needed

    2. +++ b/core/modules/block/src/Entity/Block.php
      @@ -54,7 +55,7 @@
      -class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginCollectionInterface {
      +class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginCollectionInterface, OperationsProviderInterface {
      

      this needs CR

    3. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -41,6 +45,11 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
      +   * @var \Drupal\Core\Extension\ModuleHandlerInterface.
      ...
      +  protected $moduleHandler;
      

      nit, needs description

    4. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -53,11 +62,14 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
      +   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
      +   *   The module handler service.
      

      The module handler.

    EclipseGc’s picture

    Can we get interdiffs? Makes subsequent reviews a LOT faster.

    Eclipse

    catch’s picture

    Priority: Normal » Major
    Issue tags: +blocker
    lokapujya’s picture

    Providing an interdiff.

    EclipseGc’s picture

    Status: Needs review » Needs work
    +++ b/core/modules/block/src/BlockListBuilder.php
    @@ -347,10 +346,6 @@ public function getDefaultOperations(EntityInterface $entity) {
    -      $operations += $entity->getOperationLinks();
    

    This still needs to be done, but since it's on the entity directly, there's no need to check the instanceof check since this is a builder literally for that entity.

    Honestly, there's a lot of extra code here, odds are in the BlockListBuilder, we could circumvent doing anything with the Entity at all (in terms of new interfaces and such) and instead do:

    
    if ($entity->getPlugin() instanceof OperationsProviderInterface) {
      $operations += $entity->getPlugin()->getOperationLinks();
    }
    
    

    That would circumvent all the additional code for the block Entity itself and get straight to the job of checking the block plugin for operation links (which has to happen anyway).

    I don't like all the additional code added to the Block plugin just to check if menu_ui is installed. Perhaps that's unavoidable, but it sucks.

    Eclipse

    Version: 8.0.x-dev » 8.1.x-dev

    Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

    Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

    yoroy’s picture

    Version: 8.1.x-dev » 8.2.x-dev
    Issue tags: +ux-workflow

    Version: 8.2.x-dev » 8.3.x-dev

    Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

    dawehner’s picture

    FileSize
    6.74 KB

    Just rerolled the patch and addressing the feedback of @andypost

    andypost’s picture

    +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
    @@ -193,4 +207,21 @@ public function getCacheContexts() {
    +    if ($this->moduleHandler->moduleExists('menu_ui')) {
    +      $links['menu-edit'] = [
    +        'title' => $this->t('Edit menu'),
    +        'url' => Url::fromRoute('entity.menu.edit_form', ['menu' => $menu]),
    

    Maybe better to move that to menu_ui module?

    tim.plunkett’s picture

    Priority: Major » Normal

    Can this be closed now that Settings Tray is in core?

    Bojhan’s picture

    I am not sure? Accessing these settings from the blocks page is still not that easy?

    tim.plunkett’s picture

    Well instead of editing it from admin/structure/block, you would be able to edit it from the front end

    Version: 8.3.x-dev » 8.4.x-dev

    Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

    jibran’s picture

    Title: Provide helpful editing links on "admin/structure/block" for different blocks (menu, views etc.) » Provide helpful editing links on "admin/structure/block" for deriver blocks (menu, views, block content, etc.)
    Issue summary: View changes
    Status: Needs work » Needs review
    Issue tags: -Needs issue summary update
    FileSize
    2.67 KB
    11.14 KB
    17.06 KB

    Re: #177: I still think we should keep this.
    Re: #173: I think it is fine. If we move the links then we need a hook alter for this.

    • Rerolled the patch.
    • Conflict resolution file is attached.
    • Added extra operation links to all deriver blocks ack -l `find core/ -type f -path \*src/Plugin/Block\*` --match deriver.
    • Added missing piece which is removed in #163 so #162 is still pending. I think adding a new interface is fine.
    • Updated issue summary.
    • Added tests for \Drupal\views\Plugin\Block\ViewsBlockBase and \Drupal\block_content\Plugin\Block\BlockContentBlock

    Status: Needs review » Needs work

    The last submitted patch, 178: provide_helpful_editing-1956134-178.patch, failed testing.

    jibran’s picture

    Status: Needs work » Needs review
    FileSize
    2.61 KB
    19.67 KB

    Fixed the fails.

    dawehner’s picture

    +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
    @@ -185,4 +186,18 @@ protected function getEntity() {
    +    return [
    +      'block-edit' => [
    +        'title' => $this->t('Edit block'),
    +        'url' => $entity->toUrl('edit-form')->setOptions([]),
    +        'weight' => 50,
    +      ],
    
    +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
    @@ -181,4 +195,21 @@ public function getCacheContexts() {
    +      $links['menu-edit'] = [
    +        'title' => $this->t('Edit menu'),
    +        'url' => Url::fromRoute('entity.menu.edit_form', ['menu' => $menu]),
    +        'weight' => 50,
    +      ];
    

    Shouldn't we apply access checking here?

    jibran’s picture

    Re #181: is it needed? I'm not sure.
    @dawehner told me to make my case whether this issue is still helpful or not.

    I have never use outside_in or quickedit on a production site in D8. I was never a fan of IPE in D7 as well but I like that views blocks have the ability to override views settings. I even use ctools_views module which further enhances this functionality so for me, this is more in line with that.

    Manuel Garcia’s picture

    Just tested the latest patch, I really like this!

    One thing I'd like to add to it is that when you click on edit view, or edit custom block, after you save it, you don't go up back at the block layout page.

    Attached my humble approach to doing this =)

    Version: 8.4.x-dev » 8.5.x-dev

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

    tim.plunkett’s picture

    Had completely forgotten about this issue!

    1. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -185,4 +186,18 @@ protected function getEntity() {
      +        'url' => $entity->toUrl('edit-form')->setOptions([]),
      

      This setOptions([]) looks both pointless, but also probably important?
      Can a comment be added to explain it?

    2. +++ b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php
      @@ -0,0 +1,81 @@
      +      'name' => 'tony',
      +      'mail' => 'tony@example.com',
      

      nit: Most of our test users are named either "test user" or "foobar". Who's tony? :)

    3. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -181,4 +195,21 @@ public function getCacheContexts() {
      +    if ($this->moduleHandler->moduleExists('menu_ui')) {
      
      +++ b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
      @@ -206,4 +220,24 @@ protected function addContextualLinks(&$output, $block_type = 'block') {
      +    if ($this->moduleHandler->moduleExists('views_ui')) {
      

      I personally hate moduleExists checks like this. Seems to always indicate an inflexible system. If core has to resort to this approach, how could core swap in a better one?

      Could menu_ui and views_ui swap out or decorate the plugin themselves?

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

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

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

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

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

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

    mlncn’s picture

    Um.... bump?

    I came looking to find or file an issue about putting an edit link on the configure block page—not on the block listing page like this issue, but the individual block configuration pages such as /admin/structure/block/manage/example

    Anyone who worked on this issue know if there's an issue for that... and might this other approach be less likely to take a biblical number of years? I guess that depends on if adding a tab that takes one to another tab context—Edit has Delete and Manage display as sibling tabs, and now also Configure block, but pressing on Configure block takes away the Delete and Manage display tabs and adds anything that a contrib module adds, such as Automatic label, but also has the Edit tab that, again, switches the context of sibling tabs when pressed.

    Anyhow, with that idea put out there as an addition (or if worst comes to worst an alternative) to this issue, let's see if this patch still applies...

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

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

    Oscaner’s picture

    For core 8.7.x
    But i don't know how to write test script, so need guys help me to implement the Test.

    Manuel Garcia’s picture

    Status: Needs review » Needs work

    Had a brief look at this, and thought I'd share a status update for anyone willing to push this forward.

    The patch to work on is #183, which needs a reroll, however this happened since: #2647124: Remove unused OperationsProviderInterface
    So this means the reroll needs a decision to be made about this, I see two options:

    • Restore OperationsProviderInterface
    • Re-implement this without it.
    Oscaner’s picture

    SKAUGHT’s picture

    Issue tags: +Drupal 9

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

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

    Oscaner’s picture

    FileSize
    13.88 KB
    631 bytes

    I need quick work for me on Drupal 8.8.x, so used Restore OperationsProviderInterface solution.

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

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

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

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

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

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

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

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

    3CWebDev’s picture

    Patch from #196 applied cleanly on Drupal 9.4.1 and added context links to Edit Block Content on the block over page. No issues found. What are the steps to get this functionality in core?

    rootwork’s picture

    Status: Needs work » Reviewed & tested by the community

    I'm guessing this needs some submaintainer reviews given the length of time since it was last closely looked at (despite the fact that it still applies).

    However not knowing which might be required, I'm going to set this as RTBC, given that it does apply, to see if that gets it more attention.

    quietone’s picture

    Issue summary: View changes
    Status: Reviewed & tested by the community » Needs work
    Issue tags: -Drupal 9

    @rootwork, to be committed a patch much pass the core gates. The contributor guide on Drupal.org has information about the process to Review a patch or merge request.

    This is a bit confusing. The patch in #183 was reviewed in #185. Yet the patches from #191 to #196 change different files and do not include the tests from the earlier patch. I don't know enough about this to say which is preferred. Someone familiar will need to check the patch in #183 and #196 to decide which to use. Setting to NW

    This is tagged for a change record, that needs to be added

    smustgrave’s picture

    Reading #203 decided to start at #183

    Left a comment for #185.1
    Updated #185.2 but there are other instances of tony in core just fyi.
    #185.3 I removed the moduleExists for menu_ui but left it for views_ui. I see instances where it was currently used in views core src folder. Also there could be scenario where views_ui is disabled so would make sense to not have an edit link.

    Added back OperationsProviderInterface even though it was removed in https://www.drupal.org/project/drupal/issues/2647124. Appears to have a purpose now.

    Uploaded before/after screenshots.

    Uploaded a tests-only patch based on the tests previously there.

    @quietone what kind of change record should be made? For the new interface?

    Leaving in NR to address change record and to see if tests pass.

    smustgrave’s picture

    Issue tags: -blocker

    Removing blocker as that ticket was closed as duplicate.

    smustgrave’s picture

    Noticing failures in #204 test run.

    Adding moduleExists back to menu_ui seems to fix some of them.

    smustgrave’s picture

    Cleaned up the tests some.

    Fixed the views link not showing.

    leaving in NW for change record.

    smustgrave’s picture

    Closed https://www.drupal.org/project/drupal/issues/2407761 as a duplicate of this. If someone could please move over credit.

    smustgrave’s picture

    Issue summary: View changes
    Status: Needs work » Needs review
    Issue tags: -Needs change record

    Took a shot at the change record. Sure it will need some work but getting it moving!

    The last submitted patch, 204: 1956134-204-tests-only.patch, failed testing. View results

    Manibharathi E R’s picture

    Patch #207 tested and applied successfully on Drupal 9.5.x.

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

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

    nod_’s picture

    Status: Needs review » Needs work
    Issue tags: +Needs reroll

    Patch or MR doesn't apply
    The last patch or MR doesn't apply to the target branch, please reroll the code so that it can be reviewed by the automated testbot.

    smustgrave’s picture

    Rerolled for 10.1.x

    larowlan’s picture

    Issue tags: +Needs tests

    Oh, hello old issue, long time no see

    1. +++ b/core/lib/Drupal/Core/Operations/OperationsProviderInterface.php
      @@ -0,0 +1,18 @@
      +namespace Drupal\Core\Operations;
      

      This would be the first usage of this namespace - is there somewhere else it could fit that already exists? e.g Drupal\Core\Entity

      Or if its block specific, should it just be in the block module?

    2. +++ b/core/lib/Drupal/Core/Operations/OperationsProviderInterface.php
      @@ -0,0 +1,18 @@
      +   * Returns a list of operation links available for this block.
      

      This seems to indicate it is block specific, so perhaps block module is the best spot for it?

    3. +++ b/core/lib/Drupal/Core/Operations/OperationsProviderInterface.php
      @@ -0,0 +1,18 @@
      +   * @return array
      +   *   Array of operation links.
      

      Lower we're using $operation['url'] so should we document what the expected keys are on the returned items?

    4. +++ b/core/lib/Drupal/Core/Operations/OperationsProviderInterface.php
      @@ -0,0 +1,18 @@
      +  public function getOperationLinks();
      

      Can we add the :array return type hint here, thanks

    5. +++ b/core/modules/block/src/BlockListBuilder.php
      @@ -365,6 +366,14 @@ public function getDefaultOperations(EntityInterface $entity) {
      +      $operation['url']->setOption('query', ['destination' => 'admin/structure/block']);
      

      We're overriding any existing query params here, should we be adding to the existing ones instead?

    6. +++ b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php
      @@ -0,0 +1,66 @@
      +      'description' => "Provides a block type that increases your site's spiffiness by upto 11%",
      

      😀 I hope this wasn't my doing, otherwise I'm laughing at my own jokes. Edit nope it was jibran ❤️

    7. We have tests for each of the respective plugins that implement the method, but the only thing we're missing is a test that the links show up at admin/structure/block - adding needs tests for that

    Thanks for moving this along again @smustgrave 💪

    gaurav-mathur’s picture

    Assigned: Unassigned » gaurav-mathur
    gaurav-mathur’s picture

    Assigned: gaurav-mathur » Unassigned
    FileSize
    4.76 KB
    13.01 KB

    Patch #214 applied successfully work fine.

    smustgrave’s picture

    FileSize
    6.65 KB
    20.23 KB

    Tried to address #215

    1. Agreed and moved the interface to the block module. Renamed BlockOperationsProviderInterface
    2. Same as above
    3. Tried to update the comment if that makes more sense
    4. Add :array as the return type actually breaks. But using breakpoints I see the return is an array of array links.
    5. This seems to be specific to block content, not sure if it's an issue?
    6. I like the description haha
    7. is that not covered in the block-content kernel test BlockContentTest

    andypost’s picture

    The block module is not required comparing to system and user, so this interface should live in core or in system module

    1. +++ b/core/lib/Drupal/Core/Entity/EntityListBuilder.php
      @@ -3,6 +3,7 @@
      +use Drupal\block\BlockOperationsProviderInterface;
      

      not sure it's good idea to pollute core namespace with module's one

    2. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -24,7 +27,7 @@
      -class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterface {
      +class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterface, BlockOperationsProviderInterface {
      

      it brings dependency on block module to system one - IMO that's no-go

    andypost’s picture

    +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
    @@ -213,4 +214,19 @@ protected function getEntity() {
    +  public function getOperationLinks() {
    +    $entity = $this->getEntity();
    +    // Set url options to an empty array.
    +    return [
    +      'block-edit' => [
    +        'title' => $this->t('Edit block'),
    +        'url' => $entity->toUrl('edit-form')->setOptions([]),
    +        'weight' => 50,
    +      ],
    +    ];
    

    Curious if this array should provide "access" for each link, like hook_entity_operation() doing

    smustgrave’s picture

    Status: Needs review » Needs work

    Good point. Probably all of the scenarios should check permission right? If they have menu or views permission.

    tim.plunkett’s picture

    1. +++ b/core/lib/Drupal/Core/Entity/EntityListBuilder.php
      @@ -143,6 +144,10 @@ protected function getDefaultOperations(EntityInterface $entity) {
      +    // Add operation links from entity.
      +    if ($entity instanceof BlockOperationsProviderInterface && $entity->getOperationLinks()) {
      +      $operations += $entity->getOperationLinks();
      +    }
       
      

      IMO this should move to an implementation of hook_entity_operation() in block.module

    2. +++ b/core/modules/block/src/BlockListBuilder.php
      --- /dev/null
      +++ b/core/modules/block/src/BlockOperationsProviderInterface.php
      

      I think this can live in system.module. Not the best place, but better

    smustgrave’s picture

    Addressed #220 by adding access check to all 3 spots. Also added additional test coverage if that user doesn't have correct permission.
    Moved BlockOperationsProviderInterface to system.
    Moved the changes from

    smustgrave’s picture

    FileSize
    12.89 KB
    25.53 KB

    Not sure how the patches #223 got uploaded without being attached to a comment.

    smustgrave’s picture

    FileSize
    9.82 KB
    21.94 KB

    #224 had some files from another ticket.

    This should be the correct one.

    andypost’s picture

    1. +++ b/core/modules/block/block.module
      @@ -315,3 +317,19 @@ function block_configurable_language_delete(ConfigurableLanguageInterface $langu
      +function block_entity_operation(EntityInterface $entity) {
      ...
      +  foreach ($operations as $operation) {
      +    $operation['url']->setOption('query', ['destination' => 'admin/structure/block']);
      

      looks like it has collision with \Drupal\Core\Entity\EntityListBuilder::ensureDestination()

    2. +++ b/core/modules/block/src/BlockOperationsProviderInterface.php
      @@ -0,0 +1,21 @@
      +   * Returns a list of operation links available for this block.
      ...
      +   * @return array
      +   *   An array of operation links. Each operation link will contain a
      +   *     * title
      +   *     * URL route.
      +   *     * weight
      
      +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +214,21 @@ protected function getEntity() {
      +  public function getOperationLinks() {
      ...
      +    if (\Drupal::currentUser()->hasPermission('edit any' . $entity->bundle() . ' block content')) {
      
      +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -232,4 +246,21 @@ public function getCacheContexts() {
      +  public function getOperationLinks() {
      ...
      +    if ($this->moduleHandler->moduleExists('menu_ui') && \Drupal::currentUser()->hasPermission('administer menu')) {
      
      +++ b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
      @@ -233,4 +246,24 @@ public function getViewExecutable() {
      +  public function getOperationLinks() {
      ...
      +    if ($this->moduleHandler->moduleExists('views_ui') && \Drupal::currentUser()->hasPermission('administer views')) {
      

      I think it should mention about checking access.
      Probably the best approach is to add required method argument a current user

    smustgrave’s picture

    FileSize
    5.69 KB
    22.02 KB

    Something like this?

    BlockContent and ViewBlock actually were using an AccountInterface already. Add to add a parameter for SystemBlockMenu.

    joachim’s picture

    Status: Needs review » Needs work

    Looks like a very useful addition!

    1. +++ b/core/modules/block/block.module
      @@ -315,3 +317,24 @@ function block_configurable_language_delete(ConfigurableLanguageInterface $langu
      +function block_entity_operation(EntityInterface $entity) {
      +  $operations = [];
      +  if ($entity instanceof BlockOperationsProviderInterface) {
      

      This hook is for adding operations to entities you don't control.

      But in this case, we do control block entities. So this should be done in BlockListBuilder::getOperations() instead of in a hook.

    2. +++ b/core/modules/block/src/Entity/Block.php
      @@ -59,7 +60,7 @@
      +class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginCollectionInterface, BlockOperationsProviderInterface {
      
      @@ -354,4 +355,16 @@ public function preSave(EntityStorageInterface $storage) {
      +    if ($plugin instanceof BlockOperationsProviderInterface) {
      

      I don't understand what's going on with this interface.
      It's getting used by BOTH the entity class AND some plugins?

    3. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +214,24 @@ protected function getEntity() {
      +    $entity = $this->getEntity();
      

      Clearer to say $custom_block rather than $entity.

    4. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +214,24 @@ protected function getEntity() {
      +    if ($this->account->hasPermission('edit any ' . $entity->bundle() . ' block content')) {
      

      What if the user has the 'edit all blocks' permission? This should use a call to $entity->access(), not check permissions directly.

    5. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +214,24 @@ protected function getEntity() {
      +        'title' => $this->t('Edit block'),
      

      (Aside: I'm astounded that we don't already have this functionality for custom blocks! How do users currently go to edit them?)

    6. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -232,4 +258,22 @@ public function getCacheContexts() {
      +    if ($this->moduleHandler->moduleExists('menu_ui') && $this->user->hasPermission('administer menu')) {
      

      Same as above, I would use access() on the menu entity. There is only the one admin permission for editing menus in core, but a contrib module might add permissions per-menu.

    7. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -232,4 +258,22 @@ public function getCacheContexts() {
      +        'url' => Url::fromRoute('entity.menu.edit_form', ['menu' => $menu]),
      

      Huh! Menu entities don't have any entity links defined! Is there an issue for this yet? There should probably be one! We should use entity links rather than hardcoded route.

    8. +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
      @@ -86,6 +92,19 @@ protected function setUp(): void {
      +    $user = User::create([
      

      Use setUpCurrentUser() for this?

    9. +++ b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
      @@ -233,4 +246,25 @@ public function getViewExecutable() {
      +    [$view, $display_id] = explode('-', $delta, 2);
      

      This is already in the constructor. Can we avoid this repetition by setting the view and display ID as properties there?

    10. +++ b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
      @@ -233,4 +246,25 @@ public function getViewExecutable() {
      +    if ($this->moduleHandler->moduleExists('views_ui') && $this->user->hasPermission('administer views')) {
      

      Same - use $entity->access()?

    11. +++ b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
      @@ -233,4 +246,25 @@ public function getViewExecutable() {
      +        'url' => Url::fromRoute('entity.view.edit_display_form', [
      

      Same - wot no entity link templates??? [1]

    [1] Cultural context: https://en.wikipedia.org/wiki/Kilroy_was_here

    Gunjan Rao Naik’s picture

    Added patch against #227 in 10.1.x version

    smustgrave’s picture

    @Gunjan Rao Naik thank you for the interest but the patch #227 applied to 10.1 fine so #229 was not needed. Removing credit as it's a duplicate. Actually appears to be removing some of the fix too.

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    3.81 KB
    22.01 KB

    #228

    Thank you for the detailed review.

    1. I don't see a function getOperations in listBuilder?
    2. Think that is correct? If you create a custom block while placing a block maybe
    3. Changed variable name
    4. There is no edit all block permission. But fixed
    5. You would have to go under custom block library (which will soon be moved to under content so even less clear when on the block layout page)
    6. Fixed
    7. I don't know that but checking other examples in core and that's how they're getting the route to the specific menu.
    8. We can
    9. Fixed
    10. Fixed
    11. I don't know that but checking other examples in core and that's how they're getting the route

    Status: Needs review » Needs work

    The last submitted patch, 231: 1956134-231.patch, failed testing. View results

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    1.24 KB
    22 KB

    Fixed incorrect access check for views.

    Also reverted back #231.8

    joachim’s picture

    Status: Needs review » Needs work

    > 1. I don't see a function getOperations in listBuilder?

    Sorry, I got the name wrong. It's this: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21...

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    2.2 KB
    21.96 KB

    Fixed #231.1

    Status: Needs review » Needs work

    The last submitted patch, 235: 1956134-235.patch, failed testing. View results

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    1.18 KB
    22.15 KB

    Status: Needs review » Needs work

    The last submitted patch, 237: 1956134-237.patch, failed testing. View results

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    3.16 KB
    22.77 KB

    moved the getOperations check to BlockListBuilder

    joachim’s picture

    Status: Needs review » Needs work
    +++ b/core/modules/block/src/BlockListBuilder.php
    @@ -394,6 +395,48 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
    +  public function buildOperations(EntityInterface $entity) {
    

    Sorry, I've led you down the wrong path again with this! I've had another look at the EntityListBuilder class. There *is* a getOperations method, but neither that nor buildOperations() are the right ones to override.

    There are several methods on EntityListBuilder that work together:

    - buildOperations() makes the render array. To get the list of operations, it calls getOperations()
    - getOperations() collects the operations from the list builder, and hooks, and runs the alter hook on them all
    - getDefaultOperations() defines the basic operations for the entity type in the list builder.

    So it's getDefaultOperations() we should override.

    It needs an @inheritdoc tag rather than repeating docs as in the current patch, and it should start by calling the parent.

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    2.38 KB
    22.14 KB

    Moved to the getDefaultOperations() function.

    joachim’s picture

    Status: Needs review » Needs work
    1. +++ b/core/modules/block/src/BlockListBuilder.php
      @@ -365,6 +366,27 @@ public function getDefaultOperations(EntityInterface $entity) {
      +    if ($entity instanceof BlockOperationsProviderInterface) {
      

      We don't need this check now -- we know we're working with a block.

    2. +++ b/core/modules/block/src/BlockListBuilder.php
      @@ -365,6 +366,27 @@ public function getDefaultOperations(EntityInterface $entity) {
      +      if (!in_array($key, ['edit', 'disable', 'delete'])) {
      

      Would it be simpler to assign the operations from the plugin to a separate variable, loop on THAT instead, and THEN do the $operations += to merge? That way we don't need to check hardcoded array keys.

    3. +++ b/core/modules/block/src/Entity/Block.php
      @@ -354,4 +355,16 @@ public function preSave(EntityStorageInterface $storage) {
      +  public function getOperationLinks() {
      +    $plugin = $this->getPlugin();
      

      Though I'm actually not sure what this method is for -- it just passes on to the plugin.

      Would it be ok for the list builder to do $block->getPlugin()->getOperationLinks() directly?

      I suppose it then means the caller has to faff with checking the plugin interface. If the only caller of this code is likely to be the list builder, then that's ok. But if other code might want to get the links for a block, then yes it makes sense to have this method.

    4. +++ b/core/modules/system/src/BlockOperationsProviderInterface.php
      @@ -0,0 +1,21 @@
      +interface BlockOperationsProviderInterface {
      

      I don't think this interface serves any purpose. We're adding it to the block entity class, so it's for ALL blocks. Why not just add the new method to BlockInterface?

      BC policy allows that.

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    7.19 KB
    20.43 KB

    had to move a few things around.

    smustgrave’s picture

    FileSize
    325 bytes
    20.87 KB

    Moving things around broke the Broke block

    joachim’s picture

    Status: Needs review » Needs work

    This seems to have taken a wrong turning. I think you're mixing up the *entity* class and interface and the *plugin* class and interface maybe?

    In #242 I meant that we don't need to add a new interface for the entities. That's because we want to be able to ask ANY block to give us some links. In an admin list of blocks, we're going to ask ALL of them.

    Meanwhile, it does make sense to have an interface for the *plugins*. Because some plugins provide links, and some don't.

    1. +++ b/core/lib/Drupal/Core/Block/BlockBase.php
      @@ -41,4 +41,16 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
      +    $plugin = $this->getPluginId();
      +    $links = [];
      +    if ($plugin instanceof BlockPluginInterface) {
      

      This looks all wrong.

      BlockBase is the base plugin class! The plugin here is $this! And getPluginId() gets you a string, so it can NEVER be an instance of anything!

    2. +++ b/core/lib/Drupal/Core/Block/BlockPluginInterface.php
      @@ -154,4 +154,15 @@ public function blockSubmit($form, FormStateInterface $form_state);
      +  public function getOperationLinks();
      

      What I meant was put it on the *entity* interface, not the plugin interface!

    smustgrave’s picture

    But moving getOperationLinks to BlockInterface seems to be breaking everything as some blocks don't implement getOperationLinks()

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    6.93 KB
    20.2 KB

    This is only way I could get it to work moving to BlockInterface

    joachim’s picture

    Status: Needs review » Needs work

    > But moving getOperationLinks to BlockInterface seems to be breaking everything as some blocks don't implement getOperationLinks()

    There is only one class which implements BlockInterface -- the Block entity class. See https://api.drupal.org/api/drupal/core%21modules%21block%21src%21BlockIn...

    To recap:

    1. We add getOperationLinks() to the interface for the *entity* class. Because there is only one entity class, and it needs that method.
    2. We add a new interface which *some* plugin classes will implement.

    +++ b/core/modules/block/src/Entity/Block.php
    @@ -354,4 +357,16 @@ public function preSave(EntityStorageInterface $storage) {
    +    if ($plugin instanceof BlockContentBlock || $plugin instanceof SystemMenuBlock || $plugin instanceof ViewsBlockBase) {
    

    Here we should test for the new interface. Also, this code currently won't work for contrib or custom modules ;)

    I *think* that's the only main thing to fix, and also a few test code nitpicks:

    1. +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
      @@ -86,6 +92,19 @@ protected function setUp(): void {
      +    $user = User::create([
      

      If you're importing UserCreationTrait, can't you use the methods from that here?

    2. +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
      @@ -175,6 +194,33 @@ public function testSystemMenuBlockConfigDependencies() {
      +    $block = Block::create([
      

      Shouldn't it be saved?

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    5.9 KB
    21.98 KB

    Added the interface BlockOperationsProviderInterface back and added it to the plugins for BlockContent, SystemMenu, and Views

    1. Updated the test to use the UserCreationTrait.
    2. I don't believe so as the operation links are still correctly returned.

    joachim’s picture

    Status: Needs review » Needs work

    This is definitely getting there! I'd say the structure is right, now. Just some small things to clean up now:

    +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
    @@ -213,4 +214,24 @@ protected function getEntity() {
    +      // Set url options to an empty array.
    

    The comment should say why we need to do this, because I have no idea!

    1. +++ b/core/modules/block/src/BlockInterface.php
      @@ -122,4 +122,15 @@ public function setWeight($weight);
      +   *   An array of operation links. Each operation link will contain a
      +   *     * title
      +   *     * URL route.
      +   *     * weight
      

      The formatting isn't right here, and the docs should explain what each link is. Sorry -- I was too busy focussing on where methods were and didn't read the docs!

      Something like:

      > Each operation link is itself an array with the following keys:
      - title: The title the link should display.
      - url: The \Foo\Thing\Url object for the link.
      - weight: The link weight.

    2. +++ b/core/modules/system/src/BlockOperationsProviderInterface.php
      @@ -0,0 +1,21 @@
      +   * Returns a list of operation links available for this block.
      

      Same here.

    3. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -232,4 +259,23 @@ public function getCacheContexts() {
      +    $menu = Menu::load($menu_name);
      +    $links = [];
      +    // Check the current user has the appropriate permission to edit menus.
      +    if ($this->moduleHandler->moduleExists('menu_ui') && $menu->access('edit')) {
      

      Performance nitpick: check moduleExists() before loading the menu entity.

    4. +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
      @@ -86,12 +90,8 @@ protected function setUp(): void {
      +    $user = $this->createUser(['administer menu'], 'test.user');
      +    \Drupal::service('current_user')->setAccount($user);
      

      Use setupCurrentUser() here?

    5. +++ b/core/modules/views/tests/src/Kernel/Plugin/ViewsBlockTest.php
      @@ -142,4 +147,34 @@ public function testGetPreviewFallbackString() {
      +    // Test when user doesn't have "administer views" permission.
      +    $this->assertEmpty($links);
      

      There's no user set up at this point, is there? I don't know what kernel tests do in this situation -- is it the anon user?

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    4.77 KB
    22.25 KB

    1. Updated comment
    2. Updated description
    3. Same
    4. Changed the code around to check for the module with nested if statement
    5. Changed to currentUser
    6. Not sure on that one but set a currentUser at the beginning of the test function

    joachim’s picture

    Status: Needs review » Needs work
    1. +++ b/core/modules/block/src/BlockInterface.php
      @@ -126,10 +126,10 @@
      -   *   An array of operation links. Each operation link will contain a
      

      We've lost the first sentence. We need to first say it's an array of things, and then what each thing is.

    2. +++ b/core/modules/block/src/BlockInterface.php
      @@ -126,10 +126,10 @@
      +   *     - url: The \Foo\Thing\Url object for the link.
      

      Foo\Thing was a placeholder!!

    3. +++ b/core/modules/system/src/BlockOperationsProviderInterface.php
      @@ -11,10 +11,10 @@
      +   *   Each operation link is itself an array with the following keys:
      

      Same as other method.

    4. +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
      @@ -91,7 +91,7 @@
      +    $this->setCurrentUser($user);
      

      I meant that even more easily, you can use setUpCurrentUser() here can't you?

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    2.22 KB
    22.28 KB

    that was my mistake wasn't paying attention.

    joachim’s picture

    Status: Needs review » Needs work

    Looking great!

    Unfortunately I've spotted a few other small things:

    1. +++ b/core/modules/block/src/BlockListBuilder.php
      @@ -365,6 +365,22 @@ public function getDefaultOperations(EntityInterface $entity) {
      +      $operations[$key] = $operation_extra;
      

      Because of this, the interface's getOperationLinks() should say something about how the keys work in its @return.

      Something like:

      An array of operation links. Keys in this array will overwrite keys of operations defined in \Drupal\block\BlockListBuilder::getDefaultOperations(). Each operation link is itself an array with the following keys:

    2. +++ b/core/modules/system/src/BlockOperationsProviderInterface.php
      @@ -0,0 +1,22 @@
      +namespace Drupal\system;
      

      What's the reason for putting this in system module?

      Block-related things tend to go in the Block namespace, or in the block module.

      Why not put it alongside other block plugin interfaces in Drupal\Core\Block?

      It should get an @ingroup block_api to match other interfaces there.

      And also a @see to \Drupal\block\Entity\Block::getOperationLinks() would be nice.

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    5.38 KB
    22.5 KB

    Attempted to address points in #254

    joachim’s picture

    Status: Needs review » Needs work

    @smustgrave pointed out to me in slack that:

    > it was requested in previous comments that [the interface] be placed in system

    I've gone back and read some of the discussion about this... I'm glad I didn't when I started reviewing patches here a few days ago, as I probably wouldn't have dared :/

    But this issue is nearly TEN years old, it would be nice to get it in as it's a nice UX improvement.

    So, regarding the interface and how generic we make it:

    - I don't think this is the issue to integrate contextual links and entity operation links. For one thing, they work completely differently - contextual links are plugins, but entity operation links are simple arrays. The fact that they are different systems is a DrupalWTF, though, definitely. Needs an issue if there isn't one already.
    - Making it non-specific to block plugins might be a good idea. The 'config entity + plugin' pattern is fairly common. Although, block plugins are a lot more varied than other kinds of plugins -- we get blocks derived from views, from menus, and so on. So it could be that other contrib entity + plugin type systems won't need to add dynamic operation links coming from the plugin. For instance, we don't need this in Flag module. Also, I'd rather not go down more bikeshedding when this patch feels pretty close.

    So I reckon we keep it in the Block plugin namespace, as in the latest patch. It wouldn't be a big deal with later on introduce a generic interface and deprecate the Block-specific one.

    Really close:

    1. +++ b/core/lib/Drupal/Core/Block/BlockOperationsProviderInterface.php
      @@ -0,0 +1,26 @@
      + * @see to \Drupal\block\Entity\Block::getOperationLinks()
      

      Shouldn't have 'to'.

    2. +++ b/core/lib/Drupal/Core/Block/BlockOperationsProviderInterface.php
      @@ -0,0 +1,26 @@
      +   *   An array of operation links. Each operation link is itself an array
      +   *   with the following keys:
      

      We should also warn about the keys here.

    3. +++ b/core/modules/block/src/BlockInterface.php
      @@ -122,4 +122,18 @@ public function setWeight($weight);
      +   *   Each operation link is itself an array with the following key
      

      Should be 'following keys:'.

    srilakshmier’s picture

    Assigned: Unassigned » srilakshmier
    srilakshmier’s picture

    srilakshmier’s picture

    Assigned: srilakshmier » Unassigned
    Status: Needs work » Needs review
    FileSize
    22.49 KB
    1.16 KB

    Modified #255 based on 1 and 3 in #256. Kindly review.

    Status: Needs review » Needs work

    The last submitted patch, 259: 1956134-259.patch, failed testing. View results

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    895 bytes
    22.63 KB

    Addressed the last issue

    joachim’s picture

    Status: Needs review » Needs work
    +++ b/core/modules/block/src/BlockInterface.php
    @@ -122,4 +122,18 @@ public function setWeight($weight);
    +   *   Each operation link is itself an array with the following keys
    

    Nearly there! Missing : here.

    Nitin shrivastava’s picture

    Nitin shrivastava’s picture

    try to address #262

    joachim’s picture

    Status: Needs work » Reviewed & tested by the community

    Thanks! I think this is RTBC!!!

    xjm’s picture

    Status: Reviewed & tested by the community » Needs work
    Issue tags: +Needs issue summary update, +Needs subsystem maintainer review, +Needs change record updates

    Yay!! It's really great to see this VDC usability improvement finally getting close to ready after... wow, a decade.

    #256 is helpful feedback WRT the architecture and should be added to the IS. We should also probably get block subsystem maintainer signoff on that decision and the overall architecture once the following small things are cleaned up:

    1. +++ b/core/lib/Drupal/Core/Block/BlockOperationsProviderInterface.php
      @@ -0,0 +1,28 @@
      +   * @return array
      +   *   An array of operation links. Keys in this array will overwrite keys of
      +   *   operations defined in
      +   *   \Drupal\block\BlockListBuilder::getDefaultOperations().
      +   *   Each operation link is itself an array with the following keys:
      +   *     - title: The title the link should display.
      +   *     - url: The \Drupal\Core\Url object for the link.
      +   *     - weight: The link weight.
      

      It sounds like this can be documented as array[].

    2. +++ b/core/lib/Drupal/Core/Block/BlockOperationsProviderInterface.php
      @@ -0,0 +1,28 @@
      +  public function getOperationLinks();
      

      Since this is a new method, we can typhint to the return value.

    3. +++ b/core/lib/Drupal/Core/Block/BlockOperationsProviderInterface.php
      --- a/core/modules/block/src/BlockInterface.php
      +++ b/core/modules/block/src/BlockInterface.php
      
      +++ b/core/modules/block/src/BlockInterface.php
      @@ -122,4 +122,18 @@ public function setWeight($weight);
      +   * @return array
      +   *   An array of operation links. Keys in this array will overwrite keys of
      +   *   operations defined in
      +   *   \Drupal\block\BlockListBuilder::getDefaultOperations().
      +   *   Each operation link is itself an array with the following keys:
      +   *     - title: The title the link should display.
      +   *     - url: The \Drupal\Core\Url object for the link.
      +   *     - weight: The link weight.
      

      Sounds like this can also be documented as array[].

      Also, why are we adding an identical method to both BlockInterface and a new interface? It seems like either BlockInterface should be implementing the new interface, or the base class should. The current status seems redundant, with no docs as to why.

    4. +++ b/core/modules/block/src/BlockListBuilder.php
      @@ -365,6 +365,22 @@ public function getDefaultOperations(EntityInterface $entity) {
      +    $operation_extras = $entity->getOperationLinks();
      +
      +    foreach ($operation_extras as $key => $operation_extra) {
      +      if ($operation_extra['url']->getOption('query')) {
      +        $operation_extra['url']->mergeOptions([
      +          'query',
      +          ['destination' => 'admin/structure/block'],
      +        ]);
      +      }
      +      else {
      +        $operation_extra['url']->setOption('query', ['destination' => 'admin/structure/block']);
      +      }
      +      $operations[$key] = $operation_extra;
      +    }
      

      An inline comment or two wouldn't hurt.

    5. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +214,24 @@ protected function getEntity() {
      +    // Check the current user has the appropriate permission to edit this
      +    // custom block.
      

      This is missing the word "that" ("Check that the current user...").

    6. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +214,24 @@ protected function getEntity() {
      +      // Set url options to an empty array as the destination will be set later.
      

      "URL" should be capitalized.

      Also, set later where and how? An @see to the code that does this would help too.

      Finally, it might be better to move this comment directly above the 'url' key line for clarity.

    7. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +214,24 @@ protected function getEntity() {
      +        'weight' => 50,
      

      Why this weight? Comment would be good.

    8. +++ b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php
      @@ -0,0 +1,76 @@
      +      'description' => "Provides a block type that increases your site's spiffiness by upto 11%",
      

      "up to" sbould be two words.

    9. +++ b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php
      @@ -0,0 +1,76 @@
      +    // Test when user doesn't have "administer block" permission.
      +    $this->assertEmpty($links);
      

      This is confusing at first glance. I would say:

      At this point, we are logged in as anonymous, so the user doesn't have the "administer block" permission.

    10. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -40,6 +45,20 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
      +  /**
      +   * The module handler used to check whether menu_ui is installed.
      +   *
      +   * @var \Drupal\Core\Extension\ModuleHandlerInterface
      +   */
      +  protected $moduleHandler;
      +
      +  /**
      +   * The current user.
      +   *
      +   * @var \Drupal\Core\Session\AccountInterface
      +   */
      +  protected $user;
      +
      

      Since these are new protected properties, they can be typehinted directly in PHP 8.

      I would also really like to use constructor property promotion here, but right now that's still blocked on coding standards discussions, so I guess we best leave that aside for now. #1956134: Provide helpful editing links on "admin/structure/block" for deriver blocks (menu, views, block content, etc.)

    11. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -53,11 +72,17 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa
      +  public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $menu_active_trail, ModuleHandlerInterface $module_handler, AccountInterface $user) {
      

      For BC, the new constructor parameters should default to NULL and be loaded from the static container with a deprecation warning. I guess that would mean we also need to use a nullable typehint for now, which would be changed in D11. We would need to update the docs accordingly as well.

    12. +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
      @@ -175,6 +174,33 @@ public function testSystemMenuBlockConfigDependencies() {
      +      'id' => 'machinename',
      

      "machine_name" should be two words with an underscore.

    13. +++ b/core/modules/views/tests/src/Kernel/Plugin/ViewsBlockTest.php
      @@ -142,4 +147,37 @@ public function testGetPreviewFallbackString() {
      +    // Test when user doesn't have "administer views" permission.
      ...
      +    // Test when user does have "administer views" permission.
      

      Same feedback as before.

    Finally, the change record is a bit thin; it could use some more explanation of how to use the API (plus mention the deprecation we'll be adding for the constructor).

    Thanks a ton for working on this!

    joachim’s picture

    > Also, why are we adding an identical method to both BlockInterface and a new interface? It seems like either BlockInterface should be implementing the new interface, or the base class should. The current status seems redundant, with no docs as to why.

    The combination of these methods and interfaces has gone through a lot of very different iterations and I took a change of direction when I started reviewing this issue. My thinking is this:

    - code that works with block entities should be able to say 'gimme operation links for this block entity', without needing to know about gory details. Hence the method is on the block entity class, so you can do that.
    - the specifics of whether a block entity has any operation links are up to the block plugin. So each plugin class can implement the interface and the method to provide links.

    So:

    - Block entity class getOperationLinks() -- can be called on any block entity, you'll at least get an empty array
    - Block plugin classes getOperationLinks() -- only on plugin classes which want to provide links

    In other words, entity::getOperationLinks() is a broker which take care of whether plugin::getOperationLinks() can be called.

    Not sure how to document that, any thoughts?

    xjm’s picture

    I asked @tim.plunkett and @larowlan if they could review that architecture choice.

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    9.75 KB
    24.87 KB

    #266
    1. updated to array[] and added typehint
    2. typehint added
    3. updated to array[]
    4. added some comments
    5. add the word "that"
    6. capitalized URL. Moved comment and added a little more
    7. Added comment for why that weight
    8. updated text
    9. updated text
    10. updated
    11. updated and added a 2nd CR https://www.drupal.org/node/3333923
    12. updated
    13. updated text

    Hopefully we are close because will admit losing joy in this one.

    xjm’s picture

    Still need the subsystem maintainer review on the architecture and #267.

    larowlan’s picture

    I'm not a subsystem maintainer for block, but hope Tim doesn't mind me removing the tag

    1. +++ b/core/lib/Drupal/Core/Block/BlockOperationsProviderInterface.php
      @@ -0,0 +1,28 @@
      +interface BlockOperationsProviderInterface {
      ...
      +  public function getOperationLinks(): array;
      
      +++ b/core/modules/block/src/Entity/Block.php
      @@ -354,4 +355,17 @@ public function preSave(EntityStorageInterface $storage) {
      +    if ($plugin instanceof BlockOperationsProviderInterface) {
      

      If we add getOperationsLinks to BlockBase, we can do away with the interface and the instance of check, I think that is OK for BC sake under the 1:1 rule

    2. - ie what @joachim said above

    3. +++ b/core/modules/block/src/BlockListBuilder.php
      @@ -365,6 +365,25 @@ public function getDefaultOperations(EntityInterface $entity) {
      +      if ($operation_extra['url']->getOption('query')) {
      +        $operation_extra['url']->mergeOptions([
      +          'query',
      +          ['destination' => 'admin/structure/block'],
      +        ]);
      +      }
      +      else {
      +        $operation_extra['url']->setOption('query', ['destination' => 'admin/structure/block']);
      +      }
      

      I think we can use \Drupal\Core\Entity\EntityListBuilder::ensureDestination on the urls here instead of this code

    4. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -69,7 +103,9 @@ public static function create(ContainerInterface $container, array $configuratio
      +      $container->get('current_user'),
      

      this doesn't appear to be used anymore?

    joachim’s picture

    > If we add getOperationsLinks to BlockBase, we can do away with the interface and the instance of check

    I'm fine with that architecture too -- I guess it's a case of whether the perception is:

    a) block plugins provide operation links in general. For those plugins that don't, the base class implements the method to return an empty array

    or

    b) providing operation links is something special that only some block plugins do, and so there is an interface for this

    Which is quicker and clearer? I guess if we're happy to add a method to the main plugin interface and base class, then a) is better DX as a developer doesn't need to think about adding an extra interface to their plugin class.

    xjm’s picture

    I agree with #271 FWIW.

    smustgrave’s picture

    Before redoing again

    Removing the interface and the interface check seems to break because now all blocks seem to need a getOperationLinks() function now. Which is why added the interface..

    smustgrave’s picture

    Rinku Jacob 13’s picture

    FileSize
    50.5 KB
    68.01 KB

    I have successfully Reviewed and tested patch #275 for drupal version 10.1.x . I think this patch is very useful to edit the block from the block layout instead of gone through each pages. Adding screenshots for the reference

    joachim’s picture

    Status: Needs review » Needs work
    +   * Returns a list of operation links available for this block.
    

    This method also needs to be on the plugin interface, not just the entity interface!

    joachim’s picture

    @smustgrave I'm on a train and without access to Slack, so in response to your comment there:

    The latest patch is adding a method to block plugins, and calling it in on all block plugins:


    + public function getOperationLinks(): array {
    + $plugin = $this->getPlugin();
    + if (method_exists($plugin, 'getOperationLinks')) {
    + return $plugin->getOperationLinks();
    + }
    + return [];
    + }

    Therefore, BlockPluginInterface must add this method.

    Previous patches defined a new interface for block plugins to implement optionally:

    > If we add getOperationsLinks to BlockBase

    which is fine, but BlockPluginInterface must still add this method because that is part of the API we are expecting block plugins to have.

    There seems to be some confusion on this issue about the entity and the plugin. Both are called 'block' which doesn't help. There are two totally separate class/interface hierarchies in play here:

    - the block entity, which inherits from ConfigEntityBase, implements BlockInterface. This holds the configuration the admin user enters.
    - the block plugin, which inherits from BlockBase, implements BlockPluginInterface. This holds the machinery for outputting the block.

    joachim’s picture

    Oh wait, it's using method_exists($plugin, 'getOperationLinks').

    Let's not do that though -- it's ugly. We should add the method to the block interface.

    smustgrave’s picture

    Then won't I have to update all block plugins now. They all seem to complain about the missing function if I add to BlockPluginInterface

    larowlan’s picture

    No, just add an empty implementation to BlockBase, all blocks are expected to extend from it

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    1.17 KB
    22.86 KB

    Like this?

    smustgrave’s picture

    FileSize
    297 bytes
    23.27 KB

    Had to add a stub to Broke.php.

    smustgrave’s picture

    All green!

    joachim’s picture

    Status: Needs review » Needs work
    1. +++ b/core/lib/Drupal/Core/Block/Plugin/Block/Broken.php
      @@ -93,4 +93,8 @@ protected function brokenMessage() {
      +  public function getOperationLinks(): array {
      +    return [];
      

      This needs an inherit doc. I'm surprised the code checking didn't complain about it!

    2. +++ b/core/modules/block/src/Entity/Block.php
      @@ -354,4 +354,15 @@ public function preSave(EntityStorageInterface $storage) {
      +    if (method_exists($plugin, 'getOperationLinks')) {
      

      We don't need to check the method exists, since it's on the block plugin interface. Every block plugin *must* implement this.

    smustgrave’s picture

    Status: Needs work » Needs review
    Issue tags: -Needs issue summary update, -Needs change record updates
    FileSize
    879 bytes
    23.2 KB

    Fixed points in #285

    Think the issue summary is fine but am working on CR updates

    joachim’s picture

    Status: Needs review » Reviewed & tested by the community

    Yay! I think this is ready!

    I don't think we need this CR:

    > SystemMenuBlock uses ModuleHandlerInterface and AccountInterface

    The BC policy says:

    > Particular plugins, whether class based or yaml based, should not be considered part of the public API. References to plugin IDs and settings in default configuration can be relied upon however.

    quietone’s picture

    Status: Reviewed & tested by the community » Needs work

    Unfortunately, the patch is not passing the checks.

    smustgrave’s picture

    Status: Needs work » Needs review
    FileSize
    309 bytes
    23.2 KB
    larowlan’s picture

    Status: Needs review » Needs work

    First up, I apologize in advance for asking some awkward questions here. But I'm concerned about the implicit dependencies this adds between the system module and the menu UI module, as well as the views module and the views UI module.

    But first some minor comments

    1. +++ b/core/modules/block/src/BlockListBuilder.php
      @@ -365,6 +365,25 @@ public function getDefaultOperations(EntityInterface $entity) {
      +        $operation_extra['url']->setOption('query', ['destination' => 'admin/structure/block']);
      

      Per review above from @andypost and myself, I think this should use the existing ::ensureDestination method on this class

    2. +++ b/core/modules/block_content/src/Plugin/Block/BlockContentBlock.php
      @@ -213,4 +213,26 @@ protected function getEntity() {
      +        // Using this weight so this option appears at the top.
      

      This comment doesn't match the code, 50 would put it at the bottom.

    3. +++ b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php
      @@ -0,0 +1,78 @@
      +    $this->setUpCurrentUser(['uid' => 1], ['edit any spiffy block content']);
      ...
      +    // At this point, we are logged in as an admin, so the user does
      +    // have the "administer block" permission.
      

      I don't think we should test this with user 1. So perhaps create it with a UID > 1

      User 1 typically bypasses access checks

      It will require granting the 'administer block' permission too, but then we're getting closer to a real test

    4. +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php
      @@ -232,4 +251,26 @@ public function getCacheContexts() {
      +      $menu = Menu::load($menu_name);
      +      if ($menu->access('edit')) {
      +        $links['menu-edit'] = [
      +          'title' => $this->t('Edit menu'),
      +          'url' => Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name]),
      +          'weight' => 50,
      

      Ok, brace yourself, this is where I get annoying.

      I'm not convinced system module should know about the menu UI module.

      And perhaps that suggests we're missing an API here.

      For example, let's say module A wants to modify the operation links of module B. e.g. in this case menu_ui would want to edit the operation links of system module.

      But then when you think about it, we already have a hook for adding and altering operation links - that's hook_entity_operation and hook_entity_operation_alter

      So if menu_ui cares about an operation for a block provided by system module, it should handle it itself, not the other way around.

      So I think this change should be reversed, and menu_ui module should implement one of those hooks, probably the first one and add this edit link from there.

    5. +++ b/core/modules/views/src/Plugin/Block/ViewsBlockBase.php
      @@ -233,4 +245,25 @@ public function getViewExecutable() {
      +    if ($this->moduleHandler->moduleExists('views_ui') && $view->storage->access('edit')) {
      +      $links['view-edit'] = [
      +        'title' => $this->t('Edit view'),
      +        'url' => Url::fromRoute('entity.view.edit_display_form', [
      +          'view' => $view->id(),
      +          'display_id' => $display_id,
      +        ]),
      +        'weight' => 50,
      

      And the same comment here re views ui / views module and the existing hook

    So yeah, those last two points are annoying, and sorry they're coming at comment #290. But one good thing is, the test already exists, so the impact shouldn't be as great.

    The added bonus of that is we don't need any API changes for those two block plugins, which are commonly extended (yes they're internal, but in reality they do get extended a lot).

    Thanks again for keeping this moving @smustgrave, and once again sorry for pushing back this late

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

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

    Mutasim Al-Shoura’s picture

    I have updated patch #289 and relocated the edit block link to the top of the list on the block layout page.

    xjm’s picture

    Thanks for your help updating this patch. In the future, when using a patch workflow, provide interdiffs for your patches. That allows reviewers to evaluate your changes.

    smustgrave’s picture

    Pushed up some of the feedback from #290.

    290.3 will probably need all the tests redone especially if we do 290.4

    As far as using the hooks, have to do some trickery to get the name of the menu. Not sure can figure out the view name/display.

    So we sure this is the approach to take?

    larowlan’s picture

    As far as using the hooks, have to do some trickery to get the name of the menu. Not sure can figure out the view name/display.

    We should have the block entity in scope.

    From there we can get the base block plugin ID.

    $plugin = $block->getPlugin();
    $plugin_id = $plugin->getBaseId();
    if ($plugin_id === 'system_menu_block') {
      $menu_id = $block->getDerivativeId();
      $menu = \Drupal\system\Entity\Menu::load($menu_id);
      $menu_name = $menu->label();
    }
    

    If the plugin ID is system_menu_block

    smustgrave’s picture

    Issue summary: View changes
    Status: Needs work » Needs review

    Addressed feedback from #290

    Wim Leers’s picture

    Status: Needs review » Needs work

    Another round of feedback 😊 Looking great in general, just relatively nitpicky things (one pattern of which is an actual bug though), including suggestions on how to harden the test coverage.

    smustgrave’s picture

    Status: Needs work » Needs review

    Addressed feedback.

    larowlan’s picture

    Status: Needs review » Needs work

    Left some comments.
    This is looking really tidy now, much smaller diff, nice and clean

    smustgrave’s picture

    Status: Needs work » Needs review

    Addressed feedback.

    larowlan’s picture

    Status: Needs review » Needs work

    Left another review