diff --git a/core/modules/block_content/block_content.module b/core/modules/block_content/block_content.module index 137455fc0cbfbf7c90fc1ccae208631fb6ea6260..00fc5a5320d811dc80996b5e097d47fb5d9631d5 100644 --- a/core/modules/block_content/block_content.module +++ b/core/modules/block_content/block_content.module @@ -5,7 +5,9 @@ * Allows the creation of content blocks through the user interface. */ +use Drupal\block\BlockInterface; use Drupal\block_content\BlockContentInterface; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Url; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\field\Entity\FieldConfig; @@ -214,3 +216,28 @@ function block_content_theme_suggestions_block_alter(array &$suggestions, array return $suggestions; } + +/** + * Implements hook_entity_operation(). + */ +function block_content_entity_operation(EntityInterface $entity): array { + $operations = []; + if ($entity instanceof BlockInterface) { + $plugin = $entity->getPlugin(); + if ($plugin->getBaseId() === 'block_content') { + $custom_block = \Drupal::entityTypeManager()->getStorage('block_content')->loadByProperties([ + 'uuid' => $plugin->getDerivativeId(), + ]); + $custom_block = reset($custom_block); + if ($custom_block && $custom_block->access('update')) { + $operations['block-edit'] = [ + 'title' => t('Edit block'), + 'url' => $custom_block->toUrl('edit-form')->setOptions([]), + 'weight' => 50, + ]; + } + } + } + + return $operations; +} diff --git a/core/modules/block_content/tests/src/Kernel/BlockContentTest.php b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8cc3f2b679fc24f4d58d71ceed866b3ea1570d6e --- /dev/null +++ b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php @@ -0,0 +1,77 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\block_content\Kernel; + +use Drupal\block\Entity\Block; +use Drupal\block_content\Entity\BlockContent; +use Drupal\block_content\Entity\BlockContentType; +use Drupal\Component\Plugin\PluginBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\user\Traits\UserCreationTrait; + +/** + * Tests the block content. + * + * @group block_content + */ +class BlockContentTest extends KernelTestBase { + + use UserCreationTrait; + use StringTranslationTrait; + + /** + * {@inheritdoc} + */ + protected static $modules = ['block', 'block_content', 'system', 'user']; + + /** + * {@inheritdoc} + */ + public function setUp(): void { + parent::setUp(); + $this->installEntitySchema('user'); + $this->installEntitySchema('block_content'); + } + + /** + * Tests the editing links for BlockContentBlock. + */ + public function testOperationLinks(): void { + // Create a block content type. + BlockContentType::create([ + 'id' => 'spiffy', + 'label' => 'Mucho spiffy', + 'description' => "Provides a block type that increases your site's spiffiness by up to 11%", + ])->save(); + // And a block content entity. + $block_content = BlockContent::create([ + 'info' => 'Spiffy prototype', + 'type' => 'spiffy', + ]); + $block_content->save(); + $block = Block::create([ + 'plugin' => 'block_content' . PluginBase::DERIVATIVE_SEPARATOR . $block_content->uuid(), + 'region' => 'content', + 'id' => 'machine_name', + 'theme' => 'stark', + ]); + + // The anonymous user doesn't have the "administer block" permission. + $this->assertEmpty(block_content_entity_operation($block)); + + $this->setUpCurrentUser(['uid' => 1], ['edit any spiffy block content', 'administer blocks']); + + // The admin user does have the "administer block" permission. + $this->assertEquals([ + 'block-edit' => [ + 'title' => $this->t('Edit block'), + 'url' => $block_content->toUrl('edit-form')->setOptions([]), + 'weight' => 50, + ], + ], block_content_entity_operation($block)); + } + +} diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module index 11b1f993e31a4a113331390922bfdfaa6c86eec6..40e9bc92e94041d917c452144b02d2e38c7248b9 100644 --- a/core/modules/menu_ui/menu_ui.module +++ b/core/modules/menu_ui/menu_ui.module @@ -8,6 +8,8 @@ * used for navigation. */ +use Drupal\block\BlockInterface; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Url; use Drupal\Core\Breadcrumb\Breadcrumb; use Drupal\Core\Cache\CacheableMetadata; @@ -466,3 +468,25 @@ function menu_ui_theme(): array { ], ]; } + +/** + * Implements hook_entity_operation(). + */ +function menu_ui_entity_operation(EntityInterface $entity): array { + $operations = []; + if ($entity instanceof BlockInterface) { + $plugin = $entity->getPlugin(); + if ($plugin->getBaseId() === 'system_menu_block') { + $menu = Menu::load($plugin->getDerivativeId()); + if ($menu && $menu->access('edit')) { + $operations['menu-edit'] = [ + 'title' => t('Edit menu'), + 'url' => $menu->toUrl('edit-form'), + 'weight' => 50, + ]; + } + } + } + + return $operations; +} diff --git a/core/modules/menu_ui/tests/src/Kernel/MenuBlockTest.php b/core/modules/menu_ui/tests/src/Kernel/MenuBlockTest.php new file mode 100644 index 0000000000000000000000000000000000000000..555e946d495ada0f7592cb82b3bc55ec2d016594 --- /dev/null +++ b/core/modules/menu_ui/tests/src/Kernel/MenuBlockTest.php @@ -0,0 +1,88 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\menu_ui\Kernel; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\system\Entity\Menu; +use Drupal\block\Entity\Block; +use Drupal\system\MenuInterface; +use Drupal\Tests\user\Traits\UserCreationTrait; + +/** + * Tests SystemMenuBlock. + * + * @group menu_ui + */ +class MenuBlockTest extends KernelTestBase { + + use UserCreationTrait; + + /** + * Modules to enable. + * + * @var array + */ + protected static $modules = [ + 'system', + 'block', + 'menu_ui', + 'user', + ]; + + /** + * The menu for testing. + * + * @var \Drupal\system\MenuInterface + */ + protected MenuInterface $menu; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + $this->installEntitySchema('user'); + + $this->setUpCurrentUser([], ['administer menu']); + + // Add a new custom menu. + $menu_name = 'mock'; + $label = $this->randomMachineName(16); + + $this->menu = Menu::create([ + 'id' => $menu_name, + 'label' => $label, + 'description' => 'Description text', + ]); + $this->menu->save(); + + } + + /** + * Tests the editing links for SystemMenuBlock. + */ + public function testOperationLinks(): void { + $block = Block::create([ + 'plugin' => 'system_menu_block:' . $this->menu->id(), + 'region' => 'footer', + 'id' => 'machine_name', + 'theme' => 'stark', + ]); + + // Test when user does have "administer menu" permission. + $this->assertEquals([ + 'menu-edit' => [ + 'title' => 'Edit menu', + 'url' => $this->menu->toUrl('edit-form'), + 'weight' => 50, + ], + ], menu_ui_entity_operation($block)); + + $this->setUpCurrentUser(); + // Test when user doesn't have "administer menu" permission. + $this->assertEmpty(menu_ui_entity_operation($block)); + } + +} diff --git a/core/modules/views_ui/tests/src/Kernel/ViewsBlockTest.php b/core/modules/views_ui/tests/src/Kernel/ViewsBlockTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7551b83ee3661023b497a1e351b2fa198d10b7ad --- /dev/null +++ b/core/modules/views_ui/tests/src/Kernel/ViewsBlockTest.php @@ -0,0 +1,82 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\views_ui\Kernel; + +use Drupal\Core\Url; +use Drupal\block\Entity\Block; +use Drupal\Tests\user\Traits\UserCreationTrait; +use Drupal\Tests\views\Kernel\ViewsKernelTestBase; +use Drupal\views\Tests\ViewTestData; + +/** + * Tests ViewsBlock. + * + * @group views_ui + */ +class ViewsBlockTest extends ViewsKernelTestBase { + + use UserCreationTrait; + + /** + * Modules to enable. + * + * @var array + */ + protected static $modules = [ + 'system', + 'block', + 'block_test_views', + 'views_ui', + 'user', + ]; + + /** + * Views used by this test. + * + * @var array + */ + public static $testViews = ['test_view_block']; + + /** + * {@inheritdoc} + */ + protected function setUp($import_test_views = TRUE): void { + parent::setUp(); + + ViewTestData::createTestViews(static::class, ['block_test_views']); + } + + /** + * Tests the editing links for ViewsBlockBase. + */ + public function testOperationLinks(): void { + $this->setUpCurrentUser(['uid' => 0]); + + $block = Block::create([ + 'plugin' => 'views_block:test_view_block-block_1', + 'region' => 'content', + 'id' => 'machine_name', + 'theme' => 'stark', + ]); + + // The anonymous user doesn't have the "administer block" permission. + $this->assertEmpty(views_ui_entity_operation($block)); + + $this->setUpCurrentUser(['uid' => 1], ['administer views']); + + // The admin user does have the "administer block" permission. + $this->assertEquals([ + 'view-edit' => [ + 'title' => 'Edit view', + 'url' => Url::fromRoute('entity.view.edit_display_form', [ + 'view' => 'test_view_block', + 'display_id' => 'block_1', + ]), + 'weight' => 50, + ], + ], views_ui_entity_operation($block)); + } + +} diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module index 213d8e7b825f16913deb835df2c8db2f839e374f..ff90c1639a8c2ffc76fa873958a9bb311d4e843c 100644 --- a/core/modules/views_ui/views_ui.module +++ b/core/modules/views_ui/views_ui.module @@ -5,9 +5,12 @@ * Provide structure for the administrative interface to Views. */ +use Drupal\block\BlockInterface; use Drupal\Component\Utility\Xss; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; +use Drupal\views\Entity\View; use Drupal\views\ViewExecutable; use Drupal\views\Analyzer; @@ -334,3 +337,31 @@ function views_ui_views_analyze(ViewExecutable $view) { return $ret; } + +/** + * Implements hook_entity_operation(). + */ +function views_ui_entity_operation(EntityInterface $entity): array { + $operations = []; + if ($entity instanceof BlockInterface) { + $plugin = $entity->getPlugin(); + if ($plugin->getBaseId() === 'views_block') { + $view_id_parts = explode('-', $plugin->getDerivativeId()); + $view_id = $view_id_parts[0] ?? ''; + $display_id = $view_id_parts[1] ?? ''; + $view = View::load($view_id); + if ($view && $view->access('edit')) { + $operations['view-edit'] = [ + 'title' => t('Edit view'), + 'url' => Url::fromRoute('entity.view.edit_display_form', [ + 'view' => $view_id, + 'display_id' => $display_id, + ]), + 'weight' => 50, + ]; + } + } + } + + return $operations; +}