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\FieldItemListInterface; use Drupal\Core\Form\FormStateInterface; 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 = @Translation("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; } }