improvements-2.x-dev/src/Plugin/Field/FieldFormatter/TextExtendedFormatter.php
src/Plugin/Field/FieldFormatter/TextExtendedFormatter.php
<?php
namespace Drupal\improvements\Plugin\Field\FieldFormatter;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\Attribute\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\TranslatableMarkup;
#[FieldFormatter(
id: 'text_extended',
label: new TranslatableMarkup('Extended text formatter'),
field_types: [
'text',
'text_long',
'text_with_summary',
'string',
],
)]
class TextExtendedFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public static function defaultSettings(): array {
return [
'text_source' => 'value',
'strip_tags' => FALSE,
'replace_tokens' => FALSE,
'trim_length' => 0,
'trim_summary' => FALSE,
'trim_wordsafe' => FALSE,
'trim_ellipsis' => '…',
'link_to_entity' => FALSE,
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state): array {
$field_name = $this->fieldDefinition->getName();
if ($this->fieldDefinition->getType() == 'text_with_summary') {
$elements['text_source'] = [
'#title' => t('Text source'),
'#type' => 'radios',
'#options' => [
'value' => t('Value'),
'text' => t('Formatted text'),
'summary' => t('Formatted summary'),
'summary_or_text' => t('Formatted summary or text'),
],
'#default_value' => $this->getSetting('text_source'),
];
}
$elements['strip_tags'] = [
'#title' => t('Strip tags'),
'#type' => 'checkbox',
'#default_value' => $this->getSetting('strip_tags'),
];
$elements['replace_tokens'] = [
'#title' => t('Replace tokens'),
'#type' => 'checkbox',
'#default_value' => $this->getSetting('replace_tokens'),
];
$elements['truncate'] = [
'#title' => t('Truncate'),
'#type' => 'checkbox',
'#default_value' => ($this->getSetting('trim_length') > 0),
];
$elements['trim_length'] = [
'#title' => t('Trim length'),
'#type' => 'number',
'#default_value' => $this->getSetting('trim_length'),
'#min' => 0,
'#required' => TRUE,
'#states' => [
'visible' => [
':input[name="fields[' . $field_name . '][settings_edit_form][settings][truncate]"]' => [
'checked' => TRUE,
],
],
],
];
if ($this->fieldDefinition->getType() == 'text_with_summary') {
$elements['trim_summary'] = [
'#title' => t('Trim summary'),
'#type' => 'checkbox',
'#default_value' => $this->getSetting('trim_summary'),
'#states' => [
'visible' => [
':input[name="fields[' . $field_name . '][settings_edit_form][settings][truncate]"]' => [
'checked' => TRUE,
],
],
],
];
}
$elements['trim_wordsafe'] = [
'#title' => t('Trim with word safe'),
'#type' => 'checkbox',
'#default_value' => $this->getSetting('trim_wordsafe'),
'#states' => [
'visible' => [
':input[name="fields[' . $field_name . '][settings_edit_form][settings][truncate]"]' => [
'checked' => TRUE,
],
],
],
];
$elements['trim_ellipsis'] = [
'#title' => t('Trim ellipsis'),
'#type' => 'textfield',
'#default_value' => $this->getSetting('trim_ellipsis'),
'#states' => [
'visible' => [
':input[name="fields[' . $field_name . '][settings_edit_form][settings][truncate]"]' => [
'checked' => TRUE,
],
],
],
];
$elements['link_to_entity'] = [
'#title' => t('Link to entity'),
'#type' => 'checkbox',
'#default_value' => $this->getSetting('link_to_entity'),
];
return $elements;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode): array {
$elements = [];
foreach ($items as $delta => $item) {
$elements[$delta] = $this->viewElement($item);
}
return $elements;
}
/**
* Build item render-array.
*/
public function viewElement($item): array {
$settings = $this->getSettings();
$entity = $item->getEntity();
// Text source
if ($settings['text_source'] == 'text') {
$text = check_markup($item->value, $item->format);
}
elseif ($settings['text_source'] == 'summary') {
$text = check_markup($item->summary, $item->format);
}
elseif ($settings['text_source'] == 'summary_or_text') {
$text = check_markup($item->summary ?: $item->value, $item->format);
}
else {
$text = $item->value;
}
// Strip tags
if ($settings['strip_tags']) {
$text = strip_tags($text);
}
// Replace tokens
if ($settings['replace_tokens']) {
$text = \Drupal::token()->replace($text, [$entity->getEntityTypeId() => $entity]);
}
// Trim
if ($settings['trim_length']) {
$text = trim($text);
$text_length = mb_strlen($text);
$text = Unicode::truncate($text, $settings['trim_length'], $settings['trim_wordsafe']);
if ($settings['trim_ellipsis'] && $text_length > mb_strlen($text)) {
$text = rtrim($text, ',.-()\\/*@#');
$text .= $settings['trim_ellipsis'];
}
}
// Link to entity
if ($settings['link_to_entity']) {
$element = [
'#type' => 'link',
'#title' => Markup::create($text),
'#url' => $entity->toUrl(),
];
}
else {
$element = [
'#markup' => $text,
];
}
return $element;
}
}
