public function GeneralLinkFormatter::viewElements in Formatter Suite 8
Builds a renderable array for a field value.
Parameters
\Drupal\Core\Field\FieldItemListInterface $items: The field values to be rendered.
string $langcode: The language that should be used to render the field.
Return value
array A renderable array for $items, as an array of child elements keyed by consecutive numeric indexes starting from 0.
Overrides FormatterInterface::viewElements
File
- src/
Plugin/ Field/ FieldFormatter/ GeneralLinkFormatter.php, line 675
Class
- GeneralLinkFormatter
- Formats a link field as one or more links.
Namespace
Drupal\formatter_suite\Plugin\Field\FieldFormatterCode
public function viewElements(FieldItemListInterface $items, $langcode) {
if ($items
->isEmpty() === TRUE) {
return [];
}
$this
->sanitizeSettings();
$showLink = $this
->getSetting('showLink');
$entity = $items
->getEntity();
// Prepare custom classes, if any.
$classes = $this
->getSetting('classes');
if (empty($classes) === TRUE) {
$classes = [];
}
else {
// Security: Class names are entered by an administrator.
// They may not include anything but CSS-compatible words, and
// certainly no HTML.
//
// Here, the class text is stripped of HTML tags as a start.
// A regex tosses unacceptable characters in a CSS class name.
$classes = strip_tags($classes);
$classes = mb_ereg_replace('[^_a-zA-Z0-9- ]', '', $classes);
if ($classes === FALSE) {
$classes = [];
}
$classes = explode(' ', $classes);
}
$elements = [];
foreach ($items as $delta => $item) {
//
// Get the URL.
// ------------
// Get the URL from the field and get an initial set of options,
// including those that may have been set in the field.
// Build the URL from the field.
$url = $item
->getUrl();
if (empty($url) === TRUE) {
$url = Url::fromRoute('<none>');
}
$urlOptions = $item->options + $url
->getOptions();
$url
->setOptions($urlOptions);
//
// Get the link title.
// -------------------
// Use custom text, text from the link, or the URL. If custom text
// is selected, but there isn't any, fall through to text from the
// link. If there is none of that, fall through to the URL.
switch ($this
->getSetting('titleStyle')) {
case 'text_custom':
// Security: A custom title is entered by an administrator.
// It may legitimately include HTML entities and minor HTML, but
// it should not include dangerous HTML.
//
// Because it may include HTML, we cannot pass it directly as
// the '#title' on a link, which will escape the HTML.
//
// We therefore use an Xss admin filter to remove any egreggious
// HTML (such as scripts and styles), and then FormattableMarkup()
// to mark the resulting text as safe.
$title = Xss::filterAdmin($this
->getSetting('titleCustomText'));
if (empty($title) === FALSE) {
$title = new FormattableMarkup($title, []);
break;
}
// Fall-through and use the field's title as the title text.
default:
case 'text_from_link':
// Security: Link text from the link field is entered by
// a user. It may legitimately include HTML entities and minor
// HTML, but it should not include dangerous HTML.
//
// Because it may include HTML, we cannot pass it directly as the
// '#title' on a link, which will escape the HTML.
//
// We therefore use an Xss strict filter to remove any egreggious
// HTML (such as scripts and styles, broken HTML, etc), and then
// FormattableMarkup() to mark the resulting text as safe.
$title = $item->title;
if (empty($title) === FALSE) {
$title = new FormattableMarkup($title, []);
break;
}
// Fall-through and use the URL as the title text.
case 'text_from_url':
// Use the URL as entered in the field, BEFORE this formatter adds
// additional attributes.
//
// Security: URL text from the link field is entered by a user.
// It should be strictly a valid URL.
//
// Below we pass it as the '#title' on a link, which will escape
// any HTML the URL might contain.
$title = $url
->toString();
break;
}
//
// Build the link.
// ---------------
// If the link is disabled, show the title text within a <span>.
// Otherwise, build a URL and create a link.
if ($showLink === FALSE) {
$elements[$delta] = [
'#type' => 'html_tag',
'#tag' => 'span',
'#value' => $title,
'#attributes' => [
'class' => $classes,
],
'#cache' => [
'tags' => $entity
->getCacheTags(),
],
];
}
else {
$rel = '';
$target = '';
$download = FALSE;
switch ($this
->getSetting('openLinkIn')) {
case '_self':
$target = '_self';
break;
case '_blank':
$target = '_blank';
break;
case 'download':
$download = TRUE;
break;
}
if ($this
->getSetting('noreferrer') === TRUE) {
$rel .= 'noreferrer ';
}
if ($this
->getSetting('noopener') === TRUE) {
$rel .= 'noopener ';
}
if ($this
->getSetting('nofollow') === TRUE) {
$rel .= 'nofollow ';
}
$topic = $this
->getSetting('linkTopic');
if ($topic !== 'any') {
$rel .= $topic;
}
if (empty($rel) === FALSE) {
$urlOptions['attributes']['rel'] = $rel;
}
if (empty($target) === FALSE) {
$urlOptions['attributes']['target'] = $target;
}
if ($download === TRUE) {
$urlOptions['attributes']['download'] = '';
}
$url
->setOptions($urlOptions);
$elements[$delta] = [
'#type' => 'link',
'#title' => $title,
'#options' => $url
->getOptions(),
'#url' => $url,
'#attributes' => [
'class' => $classes,
],
'#cache' => [
'tags' => $entity
->getCacheTags(),
],
];
if (empty($items[$delta]->_attributes) === FALSE) {
// There are item attributes. Add them to the link's options.
$elements[$delta]['#options'] += [
'attributes' => $items[$delta]->_attributes,
];
// And remove them from the item since they are now included
// on the link.
unset($items[$delta]->_attributes);
}
}
}
if (empty($elements) === TRUE) {
return [];
}
//
// Add multi-value field processing.
// ---------------------------------
// If the field has multiple values, redirect to a theme and pass
// the list style and separator.
$isMultiple = $this->fieldDefinition
->getFieldStorageDefinition()
->isMultiple();
if ($isMultiple === TRUE) {
// Replace the 'field' theme with one that supports lists.
$elements['#theme'] = 'formatter_suite_field_list';
// Set the list style.
$elements['#list_style'] = $this
->getSetting('listStyle');
// Set the list separator.
//
// Security: The list separator is entered by an administrator.
// It may legitimately include HTML entities and minor HTML, but
// it should not include dangerous HTML.
//
// Because it may include HTML, we cannot pass it as-is and let a TWIG
// template use {{ }}, which will process the text and corrupt any
// entered HTML or HTML entities.
//
// We therefore use an Xss admin filter to remove any egreggious HTML
// (such as scripts and styles), and then FormattableMarkup() to mark the
// resulting text as safe.
$listSeparator = Xss::filterAdmin($this
->getSetting('listSeparator'));
$elements['#list_separator'] = new FormattableMarkup($listSeparator, []);
}
return $elements;
}