public function TextWithExpandCollapseButtonsFormatter::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/ TextWithExpandCollapseButtonsFormatter.php, line 208
Class
- TextWithExpandCollapseButtonsFormatter
- Formats text with expand/collapse buttons to show more/less.
Namespace
Drupal\formatter_suite\Plugin\Field\FieldFormatterCode
public function viewElements(FieldItemListInterface $items, $langCode) {
//
// The $items array has a list of items to format. We need to return
// an array with identical indexing and corresponding render elements
// for those items.
if ($items
->isEmpty() === TRUE) {
return [];
}
// Get current settings.
$collapsedHeight = $this
->getSetting('collapsedHeight');
$animationDuration = $this
->getSetting('animationDuration');
$collapseButtonLabel = $this
->getSetting('collapseButtonLabel');
$expandButtonLabel = $this
->getSetting('expandButtonLabel');
// Security: The button labels are entered by an administrator.
// They may legitimately include HTML entities and minor HTML, but
// they should not include dangerous HTML. For instance, it is
// legitimate to include <span class="blah"> to style the label,
// or to include <img src="blah"> to add an icon image. However,
// it is not legitimate to add <style> or <script>.
//
// So, Xss::filterAdmin() is used here to get rid of the most
// dangerous HTML, like <style> and <script>.
//
// We'd like the admin-entered text to be translated, if a site
// is using that Drupal feature. However, simply calling t() will
// not quite work. Drupal.org builds translatable text tables by
// scanning the source code for calls to t() with literal strings.
// Since the admin-entered button label text here is not a literal
// string, it will not be found by that scan. This means it will
// not be in automatically-generated translation tables and t()
// will not necessarily do anything.
//
// Calling t() anyway will still do the translation table lookup.
// If a site has MANUALLY entered the text into their own translation
// tables, then translation will take place. Otherwise the text will
// be used as-is.
//
// We'd like to call $this->t() here to do the translation, but the
// various Drupal style checkers complain, even though this is a
// legitimate use. To avoid those complaints, we get the string
// translator from the StringTranslationTrait included in the
// FormatterBase parent class. Calling the translate() method
// directly dodges the style checkers.
$translator = $this
->getStringTranslation();
$collapseButtonLabel = $translator
->translate(Xss::filterAdmin($collapseButtonLabel));
$expandButtonLabel = $translator
->translate(Xss::filterAdmin($expandButtonLabel));
// Security: The animation duration is entered by an administrator.
// It should be a simple integer, with no other characters, HTML, or
// HTML entities.
//
// By parsing it as an integer, we ignore anything else and remove
// any security issues.
$animationDuration = intval($animationDuration);
// Security: The collapse height is entered by an administrator.
// It should be a number followed by CSS units, such as "px", "pt",
// or "em". It should not contain HTML or HTML entities.
//
// If integer parsing of the string yields a zero, then the string
// is assumed to be empty or invalid and collapsing is disabled.
// Otherwise the string is santized using an Html escape filter
// that escapes all HTML and HTML entities. If the admin enters these,
// the resulting string is not likely to work as a collapse height
// and the Javascript will not get a meaningful result, but it will
// still be safe.
$collapsedHeight = Html::escape($collapsedHeight);
$hasCollapsedHeight = TRUE;
if (empty($collapsedHeight) === TRUE || $collapsedHeight === "0" || (int) $collapsedHeight === 0) {
$hasCollapsedHeight = FALSE;
}
// If there is no collapsed height, show text full height.
$build = [];
if ($hasCollapsedHeight === FALSE) {
foreach ($items as $delta => $item) {
$build[$delta] = [
'#type' => 'processed_text',
'#text' => $item->value,
'#format' => $item->format,
'#langcode' => $item
->getLangcode(),
];
}
return $build;
}
// Nest the text, add buttons, and add a behavior script.
foreach ($items as $delta => $item) {
$build[$delta] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'formatter_suite-text-with-expand-collapse-buttons',
],
],
'#attached' => [
'library' => [
'formatter_suite/formatter_suite.usage',
'formatter_suite/formatter_suite.text_with_expand_collapse_buttons',
],
],
'text' => [
'#type' => 'container',
'#attributes' => [
'class' => [
'formatter_suite-text',
],
'data-formatter_suite-collapsed-height' => $collapsedHeight,
'data-formatter_suite-animation-duration' => $animationDuration,
],
'processedtext' => [
'#type' => 'processed_text',
'#text' => $item->value,
'#format' => $item->format,
'#langcode' => $item
->getLangcode(),
],
],
'collapse' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<a href="#">' . $collapseButtonLabel . '</a>',
'#attributes' => [
'class' => [
'formatter_suite-text-collapse-button',
],
'style' => 'display: none',
],
],
'expand' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<a href="#">' . $expandButtonLabel . '</a>',
'#attributes' => [
'class' => [
'formatter_suite-text-expand-button',
],
'style' => 'display: none',
],
],
];
}
return $build;
}