improvements-2.x-dev/src/Plugin/Field/FieldFormatter/ExtendedImageFormatter.php
src/Plugin/Field/FieldFormatter/ExtendedImageFormatter.php
<?php
namespace Drupal\improvements\Plugin\Field\FieldFormatter;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Field\Attribute\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\druhels\EntityHelper;
use Drupal\image\Entity\ImageStyle;
use Drupal\image\ImageStyleInterface;
use Drupal\image\Plugin\Field\FieldFormatter\ImageFormatterBase;
#[FieldFormatter(
id: 'extended_image_formatter',
label: new TranslatableMarkup('Extended image formatter'),
field_types: ['image'],
)]
class ExtendedImageFormatter extends ImageFormatterBase {
/**
* {@inheritdoc}
*/
public static function defaultSettings(): array {
return [
'image_style' => '',
'first_image_style' => '',
'image_link' => '',
'image_link_source_field' => '',
'image_link_style' => '',
'items_limit' => 0,
'default_image_type' => 'default',
'default_image_custom' => '',
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state): array {
$form = parent::settingsForm($form, $form_state);
$field_name = $this->fieldDefinition->getName();
$image_styles_options = image_style_options(FALSE);
$form['image_style'] = [
'#type' => 'select',
'#title' => t('Image style'),
'#options' => $image_styles_options,
'#empty_option' => t('None (original image)'),
'#default_value' => $this->getSetting('image_style'),
];
$form['first_image_style'] = [
'#type' => 'select',
'#title' => t('First image style'),
'#options' => $image_styles_options,
'#empty_option' => t('None (original image)'),
'#default_value' => $this->getSetting('first_image_style'),
];
$form['image_link'] = [
'#type' => 'select',
'#title' => t('Link image to'),
'#empty_option' => t('Nothing'),
'#options' => [
'content' => t('Content'),
'file' => t('File'),
'url_from_field' => t('Url from field'),
],
'#default_value' => $this->getSetting('image_link'),
];
$link_fields_definitions = EntityHelper::getBundleFieldDefinitionsByType($this->fieldDefinition->getTargetEntityTypeId(), $this->fieldDefinition->getTargetBundle(), 'link');
$image_link_source_field_options = array_map(fn($field_definition) => $field_definition->getLabel(), $link_fields_definitions);
$form['image_link_source_field'] = [
'#type' => 'select',
'#title' => t('Image link source field'),
'#options' => $image_link_source_field_options,
'#default_value' => $this->getSetting('image_link_source_field'),
'#states' => [
'visible' => [
'select[name="fields[' . $field_name . '][settings_edit_form][settings][image_link]"]' => [
'value' => 'url_from_field',
],
],
],
];
$form['image_link_style'] = [
'#type' => 'select',
'#title' => t('Image link style'),
'#options' => $image_styles_options,
'#empty_option' => t('None (original image)'),
'#default_value' => $this->getSetting('image_link_style'),
'#states' => [
'visible' => [
'select[name="fields[' . $field_name . '][settings_edit_form][settings][image_link]"]' => [
'value' => 'file',
],
],
],
];
$form['default_image_type'] = [
'#type' => 'select',
'#title' => t('Default image'),
'#options' => [
'default' => t('Default'),
'custom' => t('Custom'),
],
'#default_value' => $this->getSetting('default_image_type'),
];
$form['default_image_custom'] = [
'#type' => 'textfield',
'#title' => t('Custom default image'),
'#default_value' => $this->getSetting('default_image_custom'),
'#states' => [
'visible' => [
'select[name="fields[' . $field_name . '][settings_edit_form][settings][default_image_type]"]' => [
'value' => 'custom',
],
],
],
];
$form['items_limit'] = [
'#type' => 'number',
'#title' => t('Items limit'),
'#min' => 0,
'#default_value' => $this->getSetting('items_limit'),
];
return $form;
}
/**
* {@inheritDoc}
*/
public function settingsSummary(): array {
$summary[] = t('Image style') . ': ' . ($this->getSetting('image_style') ?: '~');
$summary[] = t('First image style') . ': ' . ($this->getSetting('first_image_style') ?: '~');
$summary[] = t('Link image to') . ': ' . ($this->getSetting('image_link') ?: '~');
$summary[] = t('Image link style') . ': ' . ($this->getSetting('image_link_style') ?: '~');
$summary[] = t('Default image type') . ': ' . $this->getSetting('default_image_type');
$summary[] = t('Items limit') . ': ' . $this->getSetting('items_limit');
return $summary;
}
/**
* {@inheritdoc}
*
* @see \Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter::viewElements()
*/
public function viewElements(FieldItemListInterface $items, $langcode): array {
$formatter_settings = $this->getSettings();
$elements = [];
// Custom default image
if ($items->isEmpty() && $formatter_settings['default_image_type'] == 'custom') {
$elements[0] = [
'#markup' => $formatter_settings['default_image_custom'],
];
return $elements;
}
$files = $this->getEntitiesToView($items, $langcode);
if (!$files) {
return $elements;
}
$image_style_name = $formatter_settings['image_style'];
$first_image_style_name = $formatter_settings['first_image_style'];
$image_link_source = $formatter_settings['image_link'];
$image_link_source_field = $formatter_settings['image_link_source_field'];
$image_link_style_name = $formatter_settings['image_link_style'];
$image_link_style = $image_link_style_name ? ImageStyle::load($image_link_style_name) : NULL; /** @var ImageStyleInterface $image_link_style */
$items_limit = $formatter_settings['items_limit'];
// Items limit
if ($items_limit && count($files) > $items_limit) {
$files = array_slice($files, 0, $items_limit);
}
// Get image link url
$image_link_url = NULL;
if ($image_link_source == 'content') {
$entity = $items->getEntity();
if (!$entity->isNew()) {
$image_link_url = $entity->toUrl();
}
}
elseif ($image_link_source == 'url_from_field') {
$entity = $items->getEntity();
if (
!$entity->isNew() &&
$image_link_source_field &&
$entity->hasField($image_link_source_field) &&
!($image_link_source_field_items = $entity->get($image_link_source_field))->isEmpty()
) {
$image_link_url = $image_link_source_field_items[0]->getUrl();
}
}
// Collect cache tags to be added for each item in the field
$cache_tags = $this->getImageStylesCacheTags($image_style_name, $first_image_style_name);
foreach ($files as $delta => $file) {
// Extract field item attributes for the theme function, and unset them
// from the $item so that the field template does not re-render them.
$item = $file->_referringItem;
$item_attributes = $item->_attributes;
unset($item->_attributes);
$elements[$delta] = [
'#theme' => 'image_formatter',
'#item' => $item,
'#item_attributes' => $item_attributes,
'#image_style' => ($first_image_style_name && $delta == 0) ? $first_image_style_name : $image_style_name,
'#url' => $image_link_url,
'#cache' => [
'tags' => Cache::mergeTags($cache_tags, $file->getCacheTags()),
],
];
}
return $elements;
}
/**
* Return image styles cache tags.
*/
protected function getImageStylesCacheTags(...$image_style_names): array {
$cache_tags = [];
foreach ($image_style_names as $image_style_name) {
if (
$image_style_name &&
($image_style_cache_tags = ImageStyle::load($image_style_name)?->getCacheTags())
) {
$cache_tags = Cache::mergeTags($cache_tags, $image_style_cache_tags);
}
}
return $cache_tags;
}
}
