diff --git a/core/modules/outside_in/outside_in.links.contextual.yml b/core/modules/outside_in/outside_in.links.contextual.yml index 99b36ef..62ca999 100644 --- a/core/modules/outside_in/outside_in.links.contextual.yml +++ b/core/modules/outside_in/outside_in.links.contextual.yml @@ -2,3 +2,6 @@ outside_in.block_configure: title: 'Quick edit' route_name: 'entity.block.offcanvas_form' group: 'block' + options: + dialog-type: dialog + dialog-renderer: offcanvas diff --git a/core/modules/outside_in/outside_in.module b/core/modules/outside_in/outside_in.module index a7fab7b..cf2aaf0 100644 --- a/core/modules/outside_in/outside_in.module +++ b/core/modules/outside_in/outside_in.module @@ -5,6 +5,7 @@ * Allows configuring blocks and other configuration from the site front-end. */ +use Drupal\Component\Utility\Html; use Drupal\Core\Asset\AttachedAssetsInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\outside_in\Block\BlockEntityOffCanvasForm; @@ -30,17 +31,28 @@ function outside_in_help($route_name, RouteMatchInterface $route_match) { /** * Implements hook_contextual_links_view_alter(). * - * Change Configure Blocks into offcanvas links. + * @todo Move to \Drupal\contextual\Element\ContextualLinks::preRenderLinks() in ++ * https://www.drupal.org/node/2784443. */ function outside_in_contextual_links_view_alter(&$element, $items) { + $add_library = FALSE; + foreach ($items as $class => $item) { + $class = Html::getClass($class); + if (isset($element['#links'][$class]) && !empty($item['localized_options']['dialog-type'])) { + $add_library = TRUE; + $element['#links'][$class]['attributes']['class'][] = 'use-ajax'; + $element['#links'][$class]['attributes']['data-dialog-type'] = $item['localized_options']['dialog-type']; + if (!empty($item['localized_options']['dialog-renderer'])) { + $element['#links'][$class]['attributes']['data-dialog-renderer'] = $item['localized_options']['dialog-renderer']; + } + } + } + // This section should NOT be moved to + // \Drupal\contextual\Element\ContextualLinks::preRenderLinks(). if (isset($element['#links']['outside-inblock-configure'])) { - $element['#links']['outside-inblock-configure']['attributes'] = [ - 'class' => ['use-ajax'], - 'data-dialog-type' => 'dialog', - 'data-dialog-renderer' => 'offcanvas', - 'data-outside-in-edit' => TRUE, - ]; - + $element['#links']['outside-inblock-configure']['attributes']['data-outside-in-edit'] = TRUE; + } + if ($add_library) { $element['#attached']['library'][] = 'outside_in/drupal.off_canvas'; } } diff --git a/core/modules/outside_in/tests/src/Unit/ContextualLinksViewAlterTest.php b/core/modules/outside_in/tests/src/Unit/ContextualLinksViewAlterTest.php new file mode 100644 index 0000000..17d4403 --- /dev/null +++ b/core/modules/outside_in/tests/src/Unit/ContextualLinksViewAlterTest.php @@ -0,0 +1,143 @@ +root . '/core/modules/outside_in/outside_in.module'; + } + + /** + * @covers ::outside_in_contextual_links_view_alter + */ + public function testValidDialogOptions() { + $elements = [ + '#links' => [ + 'no-options' => [ + 'attributes' => [ + 'class' => [ + 'existing-class', + ], + ], + ], + 'type' => [], + 'type-and-renderer' => [], + 'foo-barbaz-bop' => [], + ], + ]; + $items = [ + 'no_options' => [ + 'route_name' => 'no_options', + 'route_parameters' => [], + ], + 'type' => [ + 'route_name' => 'type', + 'route_parameters' => [], + 'localized_options' => [ + 'dialog-type' => 'modal', + ], + ], + 'type_and_renderer' => [ + 'route_name' => 'type_and_renderer', + 'route_parameters' => [], + 'localized_options' => [ + 'dialog-type' => 'modal', + 'dialog-renderer' => 'offcanvas', + ], + ], + 'foo-bar.baz_bop' => [ + 'route_name' => 'special_characters_in_link_name', + 'route_parameters' => [], + 'localized_options' => [], + ], + ]; + $expected = [ + '#links' => [ + 'no-options' => [ + 'attributes' => [ + 'class' => [ + 'existing-class', + ], + ], + ], + 'type' => [ + 'attributes' => [ + 'class' => [ + 'use-ajax', + ], + 'data-dialog-type' => 'modal', + ], + ], + 'type-and-renderer' => [ + 'attributes' => [ + 'class' => [ + 'use-ajax', + ], + 'data-dialog-type' => 'modal', + 'data-dialog-renderer' => 'offcanvas', + ], + ], + 'foo-barbaz-bop' => [ + ], + ], + '#attached' => ['library' => ['outside_in/drupal.off_canvas']], + ]; + outside_in_contextual_links_view_alter($elements, $items); + $this->assertEquals($expected, $elements); + } + + /** + * @covers ::outside_in_contextual_links_view_alter + */ + public function testNoDialogOptions() { + $elements = [ + '#links' => [ + 'no-options' => [ + 'attributes' => [ + 'class' => [ + 'existing-class', + ], + ], + ], + ], + ]; + $items = [ + 'no_options' => [ + 'route_name' => 'no_options', + 'route_parameters' => [], + ], + ]; + $expected = [ + '#links' => [ + 'no-options' => [ + 'attributes' => [ + 'class' => [ + 'existing-class', + ], + ], + ], + ], + ]; + outside_in_contextual_links_view_alter($elements, $items); + $this->assertEquals($expected, $elements); + } + +}