diff --git a/core/modules/outside_in/js/outside_in.js b/core/modules/outside_in/js/outside_in.js index c038cd2..61ad096 100644 --- a/core/modules/outside_in/js/outside_in.js +++ b/core/modules/outside_in/js/outside_in.js @@ -12,6 +12,7 @@ var itemsToToggleSelector = '[data-offcanvas-main-canvas], #toolbar-bar, [data-drupal-outsidein="editable"] a, [data-drupal-outsidein="editable"] button'; var contextualItemsSelector = '[data-contextual-id] a, [data-contextual-id] button'; var quickEditItemSelector = '[data-quickedit-entity-id]'; + var excludedLinksSelector = '[data-outside-in-exclude] [data-outside-in-edit]'; /** * Reacts to contextual links being added. @@ -24,6 +25,9 @@ * @listens event:drupalContextualLinkAdded */ $(document).on('drupalContextualLinkAdded', function (event, data) { + // Remove contextual links that should be excluded. + // @see outside_in_block_view_alter(). + $(excludedLinksSelector).remove(); // Bind Ajax behaviors to all items showing the class. // @todo Fix contextual links to work with use-ajax links in // https://www.drupal.org/node/2764931. diff --git a/core/modules/outside_in/outside_in.module b/core/modules/outside_in/outside_in.module index a7fab7b..28f9107 100644 --- a/core/modules/outside_in/outside_in.module +++ b/core/modules/outside_in/outside_in.module @@ -55,6 +55,14 @@ function outside_in_block_view_alter(array &$build) { $build['#contextual_links']['outside_in'] = [ 'route_parameters' => [], ]; + if (!_outside_in_is_block_editable($build['#plugin_id']) && isset($build['#contextual_links']['block'])) { + // If this block should not be editable set an attribute which will be used + // to remove the link on the client side. + // The individual links are not available here to remove. + // @see outside_in.js + $build['#attributes']['data-outside-in-exclude'] = TRUE; + } + } /** @@ -93,7 +101,9 @@ function outside_in_entity_type_build(array &$entity_types) { function outside_in_preprocess_block(&$variables) { // The main system block does not contain the block contextual links. $variables['#cache']['contexts'][] = 'outside_in_is_applied'; - if ($variables['plugin_id'] !== 'system_main_block' && \Drupal::service('outside_in.manager')->isApplicable()) { + /** @var \Drupal\outside_in\OutsideInManagerInterface $outside_in_manager */ + $outside_in_manager = \Drupal::service('outside_in.manager'); + if (_outside_in_is_block_editable($variables['plugin_id']) && $outside_in_manager->isApplicable()) { // Add class and attributes to all blocks to allow Javascript to target. $variables['attributes']['class'][] = 'outside-in-editable'; $variables['attributes']['data-drupal-outsidein'] = 'editable'; @@ -154,3 +164,18 @@ function outside_in_css_alter(&$css, AttachedAssetsInterface $assets) { $css[$path]['group'] = 200; } } + +/** + * Checks whether a block is editable by this module. + * + * @param string $plugin_id + * The plugin ID for the block to check. + * + * @return bool + * TRUE if the block should have the "Quick Edit" link provided by this + * module. + */ +function _outside_in_is_block_editable($plugin_id) { + $non_editable_blocks = ['page_title_block', 'system_main_block']; + return !in_array($plugin_id, $non_editable_blocks, TRUE); +} diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php index c62436c..13b97a5 100644 --- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php +++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php @@ -364,4 +364,27 @@ protected function pressToolbarEditButton() { $this->assertSession()->assertWaitOnAjaxRequest(); } + /** + * Tests that title block does not have a outside_in contextual link. + */ + public function testBlockExcluded() { + $web_assert = $this->assertSession(); + $block = $this->placeBlock('page_title_block'); + $this->drupalGet('user'); + // Assert that block has been marked as "editable" and contextual that + // should exist does. + $web_assert->elementExists('css', "#block-powered[data-drupal-outsidein=\"editable\"] [data-outside-in-edit]"); + // Check each block that should be excluded. + // We do not need to place the main content block. + // It's ID will just be 'content'. + foreach (["block-{$block->id()}", 'content'] as $excluded_block_id) { + // Assert block itself exists. + $web_assert->elementExists('css', "#$excluded_block_id"); + // Assert that exclude block has not been marked as "editable". + $web_assert->elementNotExists('css', "#{$excluded_block_id}[data-drupal-outsidein=\"editable\"]"); + // Assert that contextual that not should exist does not. + $web_assert->elementNotExists('css', "#$excluded_block_id [data-outside-in-edit]"); + } + } + }