diff --git a/core/lib/Drupal/Core/Link.php b/core/lib/Drupal/Core/Link.php index d53c238c77..e84df99595 100644 --- a/core/lib/Drupal/Core/Link.php +++ b/core/lib/Drupal/Core/Link.php @@ -29,13 +29,6 @@ class Link implements RenderableInterface { */ protected $url; - /** - * The link attributes that are needed for dialog use. - * - * @var array - */ - protected $dialogAttributes; - /** * Constructs a new Link object. * @@ -140,8 +133,6 @@ public function setUrl(Url $url) { * @see \Drupal\Core\Link::toRenderable() */ public function toString() { - $this->setUrlDialogAttributes(); - // @todo How do ensure library is attached for dialogs?s return $this->getLinkGenerator()->generateFromLink($this); } @@ -149,61 +140,23 @@ public function toString() { * {@inheritdoc} */ public function toRenderable() { - $this->setUrlDialogAttributes(); - $renderable = [ + return [ '#type' => 'link', '#url' => $this->url, '#title' => $this->text, ]; - if ($this->dialogAttributes) { - $renderable['#attached'] = [ - 'library' => [ - 'core/drupal.dialog.ajax', - ], - ]; - } - return $renderable; } /** - * Changes the link to open in a dialog. - * - * @param string $type - * The dialog type 'modal' or 'dialog', defaults to 'modal'. - * @param string $renderer - * The dialog renderer. Core provides the 'off_canvas' renderer which uses - * the off-canvas dialog. Other modules can provide dialog renderers by - * defining a service that is tagged with the name - * 'render.main_content_renderer' and tagged with a format in the pattern of - * 'drupal_[dialogType].[dialogRenderer]'. - * @param array $options - * The dialog options. + * Helper function to access \Drupal\Core\Url::openInDialog(). + * + * @see \Drupal\Core\Url::openInDialog() * * @return $this */ public function openInDialog($type = 'modal', $renderer = NULL, array $options = []) { - assert(in_array($type, ['dialog', 'modal']), "Invalid dialog type: '$type'. The dialog type must be either 'dialog' or 'modal'"); - $main_content_renders = \Drupal::getContainer()->getParameter('main_content_renderers'); - $renderer_key = "drupal_$type" . ($renderer ? ".$renderer" : ''); - assert(isset($main_content_renders[$renderer_key]), "The renderer '$renderer_key' is not available."); - $this->dialogAttributes['data-dialog-type'] = $type; - if ($renderer) { - $this->dialogAttributes['data-dialog-renderer'] = $renderer; - } - if ($options) { - $this->dialogAttributes['data-dialog-options'] = json_encode($options); - } + $this->getUrl()->openInDialog($type, $renderer, $options); return $this; } - protected function setUrlDialogAttributes() { - if ($this->dialogAttributes) { - $attributes = $this->url->getOption('attributes'); - if (!$attributes || !isset($attributes['class']) || !in_array('use-ajax', $attributes['class'])) { - $attributes['class'][] = 'use-ajax'; - } - $this->url->setOption('attributes', array_merge($attributes, $this->dialogAttributes)); - } - } - } diff --git a/core/lib/Drupal/Core/Render/Element/Link.php b/core/lib/Drupal/Core/Render/Element/Link.php index 216f068a49..8ab992781e 100644 --- a/core/lib/Drupal/Core/Render/Element/Link.php +++ b/core/lib/Drupal/Core/Render/Element/Link.php @@ -89,6 +89,11 @@ public static function preRenderLink($element) { if (!empty($element['#url']) && $element['#url'] instanceof CoreUrl) { $options = NestedArray::mergeDeep($element['#url']->getOptions(), $element['#options']); + if (!empty($options['attributes']['data-dialog-type'])) { + if (empty($element['#attached']['library']) || !in_array('core/drupal.dialog.ajax', $element['#attached']['library'])) { + $element['#attached']['library'][] = 'core/drupal.dialog.ajax'; + } + } /** @var \Drupal\Core\Utility\LinkGenerator $link_generator */ $link_generator = \Drupal::service('link_generator'); $generated_link = $link_generator->generate($element['#title'], $element['#url']->setOptions($options)); diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php index 76dc46c77b..a0e7810d11 100644 --- a/core/lib/Drupal/Core/Url.php +++ b/core/lib/Drupal/Core/Url.php @@ -92,6 +92,13 @@ class Url { */ protected $internalPath; + /** + * The link attributes that are needed for dialog use. + * + * @var array + */ + protected $dialogAttributes; + /** * Constructs a new Url object. * @@ -655,6 +662,7 @@ public function getOption($name) { */ public function setOptions($options) { $this->options = $options; + $this->setDialogAttributes(); return $this; } @@ -672,6 +680,9 @@ public function setOptions($options) { */ public function setOption($name, $value) { $this->options[$name] = $value; + if ($name == 'attributes') { + $this->setDialogAttributes(); + } return $this; } @@ -887,4 +898,49 @@ public function setUnroutedUrlAssembler(UnroutedUrlAssemblerInterface $url_assem return $this; } + /** + * Changes the link to open in a dialog. + * + * @param string $type + * The dialog type 'modal' or 'dialog', defaults to 'modal'. + * @param string $renderer + * The dialog renderer. Core provides the 'off_canvas' renderer which uses + * the off-canvas dialog. Other modules can provide dialog renderers by + * defining a service that is tagged with the name + * 'render.main_content_renderer' and tagged with a format in the pattern of + * 'drupal_[dialogType].[dialogRenderer]'. + * @param array $options + * The dialog options. + * + * @return $this + */ + public function openInDialog($type = 'modal', $renderer = NULL, array $options = []) { + assert(in_array($type, ['dialog', 'modal']), "Invalid dialog type: '$type'. The dialog type must be either 'dialog' or 'modal'"); + $main_content_renders = \Drupal::getContainer()->getParameter('main_content_renderers'); + $renderer_key = "drupal_$type" . ($renderer ? ".$renderer" : ''); + assert(isset($main_content_renders[$renderer_key]), "The renderer '$renderer_key' is not available."); + $this->dialogAttributes['data-dialog-type'] = $type; + if ($renderer) { + $this->dialogAttributes['data-dialog-renderer'] = $renderer; + } + if ($options) { + $this->dialogAttributes['data-dialog-options'] = json_encode($options); + } + $this->setDialogAttributes(); + return $this; + } + + /** + * Sets the URL attributes to use a dialog if needed. + */ + protected function setDialogAttributes() { + if ($this->dialogAttributes) { + $attributes = $this->getOption('attributes'); + if (!$attributes || !isset($attributes['class']) || !in_array('use-ajax', $attributes['class'])) { + $attributes['class'][] = 'use-ajax'; + } + $this->options['attributes'] = array_merge($attributes, $this->dialogAttributes); + } + } + }