PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php

http://github.com/drupal/drupal
PHP | 260 lines | 158 code | 27 blank | 75 comment | 21 complexity | 16b25ba25a65a66bee74c807199a43b8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. namespace Drupal\link\Plugin\Field\FieldFormatter;
  3. use Drupal\Component\Utility\Unicode;
  4. use Drupal\Core\Field\FieldDefinitionInterface;
  5. use Drupal\Core\Field\FieldItemListInterface;
  6. use Drupal\Core\Field\FormatterBase;
  7. use Drupal\Core\Form\FormStateInterface;
  8. use Drupal\Core\Path\PathValidatorInterface;
  9. use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
  10. use Drupal\Core\Url;
  11. use Drupal\link\LinkItemInterface;
  12. use Symfony\Component\DependencyInjection\ContainerInterface;
  13. /**
  14. * Plugin implementation of the 'link' formatter.
  15. *
  16. * @FieldFormatter(
  17. * id = "link",
  18. * label = @Translation("Link"),
  19. * field_types = {
  20. * "link"
  21. * }
  22. * )
  23. */
  24. class LinkFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
  25. /**
  26. * The path validator service.
  27. *
  28. * @var \Drupal\Core\Path\PathValidatorInterface
  29. */
  30. protected $pathValidator;
  31. /**
  32. * {@inheritdoc}
  33. */
  34. public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  35. return new static(
  36. $plugin_id,
  37. $plugin_definition,
  38. $configuration['field_definition'],
  39. $configuration['settings'],
  40. $configuration['label'],
  41. $configuration['view_mode'],
  42. $configuration['third_party_settings'],
  43. $container->get('path.validator')
  44. );
  45. }
  46. /**
  47. * Constructs a new LinkFormatter.
  48. *
  49. * @param string $plugin_id
  50. * The plugin_id for the formatter.
  51. * @param mixed $plugin_definition
  52. * The plugin implementation definition.
  53. * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
  54. * The definition of the field to which the formatter is associated.
  55. * @param array $settings
  56. * The formatter settings.
  57. * @param string $label
  58. * The formatter label display setting.
  59. * @param string $view_mode
  60. * The view mode.
  61. * @param array $third_party_settings
  62. * Third party settings.
  63. * @param \Drupal\Core\Path\PathValidatorInterface $path_validator
  64. * The path validator service.
  65. */
  66. public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, PathValidatorInterface $path_validator) {
  67. parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
  68. $this->pathValidator = $path_validator;
  69. }
  70. /**
  71. * {@inheritdoc}
  72. */
  73. public static function defaultSettings() {
  74. return [
  75. 'trim_length' => '80',
  76. 'url_only' => '',
  77. 'url_plain' => '',
  78. 'rel' => '',
  79. 'target' => '',
  80. ] + parent::defaultSettings();
  81. }
  82. /**
  83. * {@inheritdoc}
  84. */
  85. public function settingsForm(array $form, FormStateInterface $form_state) {
  86. $elements = parent::settingsForm($form, $form_state);
  87. $elements['trim_length'] = [
  88. '#type' => 'number',
  89. '#title' => t('Trim link text length'),
  90. '#field_suffix' => t('characters'),
  91. '#default_value' => $this->getSetting('trim_length'),
  92. '#min' => 1,
  93. '#description' => t('Leave blank to allow unlimited link text lengths.'),
  94. ];
  95. $elements['url_only'] = [
  96. '#type' => 'checkbox',
  97. '#title' => t('URL only'),
  98. '#default_value' => $this->getSetting('url_only'),
  99. '#access' => $this->getPluginId() == 'link',
  100. ];
  101. $elements['url_plain'] = [
  102. '#type' => 'checkbox',
  103. '#title' => t('Show URL as plain text'),
  104. '#default_value' => $this->getSetting('url_plain'),
  105. '#access' => $this->getPluginId() == 'link',
  106. '#states' => [
  107. 'visible' => [
  108. ':input[name*="url_only"]' => ['checked' => TRUE],
  109. ],
  110. ],
  111. ];
  112. $elements['rel'] = [
  113. '#type' => 'checkbox',
  114. '#title' => t('Add rel="nofollow" to links'),
  115. '#return_value' => 'nofollow',
  116. '#default_value' => $this->getSetting('rel'),
  117. ];
  118. $elements['target'] = [
  119. '#type' => 'checkbox',
  120. '#title' => t('Open link in new window'),
  121. '#return_value' => '_blank',
  122. '#default_value' => $this->getSetting('target'),
  123. ];
  124. return $elements;
  125. }
  126. /**
  127. * {@inheritdoc}
  128. */
  129. public function settingsSummary() {
  130. $summary = [];
  131. $settings = $this->getSettings();
  132. if (!empty($settings['trim_length'])) {
  133. $summary[] = t('Link text trimmed to @limit characters', ['@limit' => $settings['trim_length']]);
  134. }
  135. else {
  136. $summary[] = t('Link text not trimmed');
  137. }
  138. if ($this->getPluginId() == 'link' && !empty($settings['url_only'])) {
  139. if (!empty($settings['url_plain'])) {
  140. $summary[] = t('Show URL only as plain-text');
  141. }
  142. else {
  143. $summary[] = t('Show URL only');
  144. }
  145. }
  146. if (!empty($settings['rel'])) {
  147. $summary[] = t('Add rel="@rel"', ['@rel' => $settings['rel']]);
  148. }
  149. if (!empty($settings['target'])) {
  150. $summary[] = t('Open link in new window');
  151. }
  152. return $summary;
  153. }
  154. /**
  155. * {@inheritdoc}
  156. */
  157. public function viewElements(FieldItemListInterface $items, $langcode) {
  158. $element = [];
  159. $entity = $items->getEntity();
  160. $settings = $this->getSettings();
  161. foreach ($items as $delta => $item) {
  162. // By default use the full URL as the link text.
  163. $url = $this->buildUrl($item);
  164. $link_title = $url->toString();
  165. // If the title field value is available, use it for the link text.
  166. if (empty($settings['url_only']) && !empty($item->title)) {
  167. // Unsanitized token replacement here because the entire link title
  168. // gets auto-escaped during link generation in
  169. // \Drupal\Core\Utility\LinkGenerator::generate().
  170. $link_title = \Drupal::token()->replace($item->title, [$entity->getEntityTypeId() => $entity], ['clear' => TRUE]);
  171. }
  172. // Trim the link text to the desired length.
  173. if (!empty($settings['trim_length'])) {
  174. $link_title = Unicode::truncate($link_title, $settings['trim_length'], FALSE, TRUE);
  175. }
  176. if (!empty($settings['url_only']) && !empty($settings['url_plain'])) {
  177. $element[$delta] = [
  178. '#plain_text' => $link_title,
  179. ];
  180. if (!empty($item->_attributes)) {
  181. // Piggyback on the metadata attributes, which will be placed in the
  182. // field template wrapper, and set the URL value in a content
  183. // attribute.
  184. // @todo Does RDF need a URL rather than an internal URI here?
  185. // @see \Drupal\Tests\rdf\Kernel\Field\LinkFieldRdfaTest.
  186. $content = str_replace('internal:/', '', $item->uri);
  187. $item->_attributes += ['content' => $content];
  188. }
  189. }
  190. else {
  191. $element[$delta] = [
  192. '#type' => 'link',
  193. '#title' => $link_title,
  194. '#options' => $url->getOptions(),
  195. ];
  196. $element[$delta]['#url'] = $url;
  197. if (!empty($item->_attributes)) {
  198. $element[$delta]['#options'] += ['attributes' => []];
  199. $element[$delta]['#options']['attributes'] += $item->_attributes;
  200. // Unset field item attributes since they have been included in the
  201. // formatter output and should not be rendered in the field template.
  202. unset($item->_attributes);
  203. }
  204. }
  205. }
  206. return $element;
  207. }
  208. /**
  209. * Builds the \Drupal\Core\Url object for a link field item.
  210. *
  211. * @param \Drupal\link\LinkItemInterface $item
  212. * The link field item being rendered.
  213. *
  214. * @return \Drupal\Core\Url
  215. * A Url object.
  216. */
  217. protected function buildUrl(LinkItemInterface $item) {
  218. $url = $item->getUrl() ?: Url::fromRoute('<none>');
  219. $settings = $this->getSettings();
  220. $options = $item->options;
  221. $options += $url->getOptions();
  222. // Add optional 'rel' attribute to link options.
  223. if (!empty($settings['rel'])) {
  224. $options['attributes']['rel'] = $settings['rel'];
  225. }
  226. // Add optional 'target' attribute to link options.
  227. if (!empty($settings['target'])) {
  228. $options['attributes']['target'] = $settings['target'];
  229. }
  230. $url->setOptions($options);
  231. return $url;
  232. }
  233. }