rocketship_core-8.x-2.0-alpha11/src/Plugin/Field/FieldFormatter/ClassyLinkFormatter.php
src/Plugin/Field/FieldFormatter/ClassyLinkFormatter.php
<?php
namespace Drupal\rocketship_core\Plugin\Field\FieldFormatter;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Path\PathValidatorInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Url;
use Drupal\link\LinkItemInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin implementation of the 'classy_link_formatter' formatter.
*
* @FieldFormatter(
* id = "classy_link_formatter",
* label = @Translation("Classy link formatter"),
* field_types = {
* "link"
* }
* )
*/
class ClassyLinkFormatter extends FormatterBase implements ContainerFactoryPluginInterface {
/**
* The path validator service.
*
* @var \Drupal\Core\Path\PathValidatorInterface
*/
protected $pathValidator;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['label'],
$configuration['view_mode'],
$configuration['third_party_settings'],
$container->get('path.validator')
);
}
/**
* Constructs a new LinkFormatter.
*
* @param string $plugin_id
* The plugin_id for the formatter.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field to which the formatter is associated.
* @param array $settings
* The formatter settings.
* @param string $label
* The formatter label display setting.
* @param string $view_mode
* The view mode.
* @param array $third_party_settings
* Third party settings.
* @param \Drupal\Core\Path\PathValidatorInterface $path_validator
* The path validator service.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, PathValidatorInterface $path_validator) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->pathValidator = $path_validator;
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'trim_length' => '80',
'url_only' => '',
'url_plain' => '',
'rel' => '',
'target' => '',
'classes' => '',
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$elements = parent::settingsForm($form, $form_state);
$elements['trim_length'] = [
'#type' => 'number',
'#title' => t('Trim link text length'),
'#field_suffix' => t('characters'),
'#default_value' => $this->getSetting('trim_length'),
'#min' => 1,
'#description' => t('Leave blank to allow unlimited link text lengths.'),
];
$elements['url_only'] = [
'#type' => 'checkbox',
'#title' => t('URL only'),
'#default_value' => $this->getSetting('url_only'),
'#access' => $this->getPluginId() == 'link',
];
$elements['url_plain'] = [
'#type' => 'checkbox',
'#title' => t('Show URL as plain text'),
'#default_value' => $this->getSetting('url_plain'),
'#access' => $this->getPluginId() == 'link',
'#states' => [
'visible' => [
':input[name*="url_only"]' => ['checked' => TRUE],
],
],
];
$elements['rel'] = [
'#type' => 'checkbox',
'#title' => t('Add rel="nofollow" to links'),
'#return_value' => 'nofollow',
'#default_value' => $this->getSetting('rel'),
];
$elements['target'] = [
'#type' => 'checkbox',
'#title' => t('Open link in new window'),
'#return_value' => '_blank',
'#default_value' => $this->getSetting('target'),
];
$elements['classes'] = [
'#type' => 'textfield',
'#title' => t('Extra classes. Separate multiple classes with space'),
'#default_value' => $this->getSetting('classes'),
];
return $elements;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];
$settings = $this->getSettings();
if (!empty($settings['trim_length'])) {
$summary[] = t('Link text trimmed to @limit characters', ['@limit' => $settings['trim_length']]);
}
else {
$summary[] = t('Link text not trimmed');
}
if ($this->getPluginId() == 'link' && !empty($settings['url_only'])) {
if (!empty($settings['url_plain'])) {
$summary[] = t('Show URL only as plain-text');
}
else {
$summary[] = t('Show URL only');
}
}
if (!empty($settings['rel'])) {
$summary[] = t('Add rel="@rel"', ['@rel' => $settings['rel']]);
}
if (!empty($settings['target'])) {
$summary[] = t('Open link in new window');
}
if (!empty($settings['classes'])) {
$summary[] = t('Extra classes:') . ' ' . $settings['classes'];
}
return $summary;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$element = [];
$entity = $items->getEntity();
$settings = $this->getSettings();
$classes = $this->getSetting('classes');
foreach ($items as $delta => $item) {
// By default use the full URL as the link text.
$url = $this->buildUrl($item);
$link_title = $url->toString();
// If the title field value is available, use it for the link text.
if (empty($settings['url_only']) && !empty($item->title)) {
// Unsanitized token replacement here because the entire link title
// gets auto-escaped during link generation in
// \Drupal\Core\Utility\LinkGenerator::generate().
$link_title = \Drupal::token()
->replace($item->title, [$entity->getEntityTypeId() => $entity], ['clear' => TRUE]);
}
// Trim the link text to the desired length.
if (!empty($settings['trim_length'])) {
$link_title = Unicode::truncate($link_title, $settings['trim_length'], FALSE, TRUE);
}
if (!empty($settings['url_only']) && !empty($settings['url_plain'])) {
$element[$delta] = [
'#plain_text' => $link_title,
];
if (!empty($item->_attributes)) {
// Piggyback on the metadata attributes, which will be placed in the
// field template wrapper, and set the URL value in a content
// attribute.
// @todo Does RDF need a URL rather than an internal URI here?
// @see \Drupal\Tests\rdf\Kernel\Field\LinkFieldRdfaTest.
$content = str_replace('internal:/', '', $item->uri);
$item->_attributes += ['content' => $content];
}
}
else {
$element[$delta] = [
'#type' => 'link',
'#title' => $link_title,
'#options' => $url->getOptions(),
];
$element[$delta]['#url'] = $url;
if (!empty($classes)) {
$element[$delta]['#options'] += ['attributes' => []];
$element[$delta]['#options']['attributes']['class'][] = $classes;
}
if (!empty($item->_attributes)) {
$element[$delta]['#options'] += ['attributes' => []];
$element[$delta]['#options']['attributes'] += $item->_attributes;
// Unset field item attributes since they have been included in the
// formatter output and should not be rendered in the field template.
unset($item->_attributes);
}
}
}
return $element;
}
/**
* Builds the \Drupal\Core\Url object for a link field item.
*
* @param \Drupal\link\LinkItemInterface $item
* The link field item being rendered.
*
* @return \Drupal\Core\Url
* A Url object.
*/
protected function buildUrl(LinkItemInterface $item) {
$url = $item->getUrl() ?: Url::fromRoute('<none>');
$settings = $this->getSettings();
$options = $item->options;
$options += $url->getOptions();
// Add optional 'rel' attribute to link options.
if (!empty($settings['rel'])) {
$options['attributes']['rel'] = $settings['rel'];
}
// Add optional 'target' attribute to link options.
if (!empty($settings['target'])) {
$options['attributes']['target'] = $settings['target'];
}
$url->setOptions($options);
return $url;
}
}
