25edc42c9810e4e5d285c8ac56f1d3b62c172c28
[yaffs-website] / web / core / lib / Drupal / Core / Render / Element / Link.php
1 <?php
2
3 namespace Drupal\Core\Render\Element;
4
5 use Drupal\Component\Utility\NestedArray;
6 use Drupal\Component\Utility\Html as HtmlUtility;
7 use Drupal\Core\Render\BubbleableMetadata;
8 use Drupal\Core\Url as CoreUrl;
9
10 /**
11  * Provides a link render element.
12  *
13  * Properties:
14  * - #title: The link text.
15  * - #url: \Drupal\Core\Url object containing URL information pointing to a
16  *   internal or external link. See \Drupal\Core\Utility\LinkGeneratorInterface.
17  *
18  * Usage example:
19  * @code
20  * $build['examples_link'] = [
21  *   '#title' => $this->t('Examples'),
22  *   '#type' => 'link',
23  *   '#url' => \Drupal\Core\Url::fromRoute('examples.description')
24  * ];
25  * @endcode
26  *
27  * @RenderElement("link")
28  */
29 class Link extends RenderElement {
30
31   /**
32    * {@inheritdoc}
33    */
34   public function getInfo() {
35     $class = get_class($this);
36     return [
37       '#pre_render' => [
38         [$class, 'preRenderLink'],
39       ],
40     ];
41   }
42
43   /**
44    * Pre-render callback: Renders a link into #markup.
45    *
46    * Doing so during pre_render gives modules a chance to alter the link parts.
47    *
48    * @param array $element
49    *   A structured array whose keys form the arguments to
50    *   \Drupal\Core\Utility\LinkGeneratorInterface::generate():
51    *   - #title: The link text.
52    *   - #url: The URL info either pointing to a route or a non routed path.
53    *   - #options: (optional) An array of options to pass to the link generator.
54    *
55    * @return array
56    *   The passed-in element containing a rendered link in '#markup'.
57    */
58   public static function preRenderLink($element) {
59     // By default, link options to pass to the link generator are normally set
60     // in #options.
61     $element += ['#options' => []];
62     // However, within the scope of renderable elements, #attributes is a valid
63     // way to specify attributes, too. Take them into account, but do not override
64     // attributes from #options.
65     if (isset($element['#attributes'])) {
66       $element['#options'] += ['attributes' => []];
67       $element['#options']['attributes'] += $element['#attributes'];
68     }
69
70     // This #pre_render callback can be invoked from inside or outside of a Form
71     // API context, and depending on that, a HTML ID may be already set in
72     // different locations. #options should have precedence over Form API's #id.
73     // #attributes have been taken over into #options above already.
74     if (isset($element['#options']['attributes']['id'])) {
75       $element['#id'] = $element['#options']['attributes']['id'];
76     }
77     elseif (isset($element['#id'])) {
78       $element['#options']['attributes']['id'] = $element['#id'];
79     }
80
81     // Conditionally invoke self::preRenderAjaxForm(), if #ajax is set.
82     if (isset($element['#ajax']) && !isset($element['#ajax_processed'])) {
83       // If no HTML ID was found above, automatically create one.
84       if (!isset($element['#id'])) {
85         $element['#id'] = $element['#options']['attributes']['id'] = HtmlUtility::getUniqueId('ajax-link');
86       }
87       $element = static::preRenderAjaxForm($element);
88     }
89
90     if (!empty($element['#url']) && $element['#url'] instanceof CoreUrl) {
91       $options = NestedArray::mergeDeep($element['#url']->getOptions(), $element['#options']);
92       /** @var \Drupal\Core\Utility\LinkGenerator $link_generator */
93       $link_generator = \Drupal::service('link_generator');
94       $generated_link = $link_generator->generate($element['#title'], $element['#url']->setOptions($options));
95       $element['#markup'] = $generated_link;
96       $generated_link->merge(BubbleableMetadata::createFromRenderArray($element))
97         ->applyTo($element);
98     }
99     return $element;
100   }
101
102 }