improvements-2.x-dev/src/Plugin/Field/FieldFormatter/ImageWithMobileAlternativeOneFieldFormatter.php
src/Plugin/Field/FieldFormatter/ImageWithMobileAlternativeOneFieldFormatter.php
<?php
namespace Drupal\improvements\Plugin\Field\FieldFormatter;
use Drupal\breakpoint\BreakpointInterface;
use Drupal\breakpoint\BreakpointManagerInterface;
use Drupal\Core\Field\Attribute\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\file\FileInterface;
use Drupal\image\Entity\ImageStyle;
use Drupal\image\ImageStyleInterface;
use Drupal\image\Plugin\Field\FieldType\ImageItem;
#[FieldFormatter(
id: 'image_with_mobile_alternative_one_field',
label: new TranslatableMarkup('Image with mobile alternative (one field)'),
field_types: ['image'],
)]
class ImageWithMobileAlternativeOneFieldFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public static function defaultSettings(): array {
return [
'image_style' => '',
'breakpoint_group' => '',
'mobile_breakpoint' => '',
'mobile_image_style' => '',
] + parent::defaultSettings();
}
/**
* {@inheritDoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state): array {
$image_styles_options = image_style_options(FALSE);
$breakpoint_manager = \Drupal::service('breakpoint.manager'); /** @var BreakpointManagerInterface $breakpoint_manager */
$breakpoint_group = $this->getSetting('breakpoint_group');
// Image style
$elements['image_style'] = [
'#type' => 'select',
'#title' => t('Default image style'),
'#options' => $image_styles_options,
'#empty_option' => t('None (original image)'),
'#default_value' => $this->getSetting('image_style'),
];
// Breakpoint group
$elements['breakpoint_group'] = [
'#type' => 'select',
'#title' => t('Breakpoint group'),
'#options' => $breakpoint_manager->getGroups(),
'#default_value' => $breakpoint_group,
];
// @TODO Add update form on ajax
if ($breakpoint_group) {
// Mobile breakpoint
$elements['mobile_breakpoint'] = [
'#type' => 'select',
'#title' => t('Mobile breakpoint'),
'#options' => $this->getMobileBreakpointOptions($breakpoint_group),
'#default_value' => $this->getSetting('mobile_breakpoint'),
];
// Mobile image style
$elements['mobile_image_style'] = [
'#type' => 'select',
'#title' => t('Mobile image style'),
'#options' => $image_styles_options,
'#empty_option' => t('None (original image)'),
'#default_value' => $this->getSetting('mobile_image_style'),
];
}
return $elements;
}
/**
* {@inheritDoc}
*/
public function settingsSummary(): array {
$summary = [];
if ($image_style = $this->getSetting('image_style')) {
$summary[] = t('Default image style') . ': ' . $this->getSetting('image_style');
}
if ($breakpoint_group = $this->getSetting('breakpoint_group')) {
$summary[] = t('Breakpoint group') . ': ' . $breakpoint_group;
}
if ($mobile_breakpoint = $this->getSetting('mobile_breakpoint')) {
$summary[] = t('Mobile breakpoint') . ': ' . $mobile_breakpoint;
}
if ($mobile_image_style = $this->getSetting('mobile_image_style')) {
$summary[] = t('Mobile image style') . ': ' . $mobile_image_style;
}
return $summary;
}
/**
* {@inheritDoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode): array {
$elements = [];
if ($items->isEmpty()) {
return $elements;
}
$formatter_settigns = $this->getSettings();
$breakpoint_manager = \Drupal::service('breakpoint.manager'); /** @var BreakpointManagerInterface $breakpoint_manager */
$mobile_breakpoint = $breakpoint_manager->getBreakpointsByGroup($formatter_settigns['breakpoint_group'])[$formatter_settigns['mobile_breakpoint']];
/** @var ImageStyleInterface $default_image_style */
$default_image_style = $formatter_settigns['image_style'] ? ImageStyle::load($formatter_settigns['image_style']) : NULL;
$default_image_item = $items->get(0); /** @var ImageItem $default_image_item */
$mobile_image_item = $items->get(1); /** @var ImageItem $mobile_image_item */
$default_image_entity = $default_image_item->entity; /** @var FileInterface $default_image_entity */
$mobile_image_entity = $mobile_image_item ? $mobile_image_item->entity : NULL; /** @var FileInterface $mobile_image_entity */
$default_image_url = $this->getImageStyleUrl($default_image_entity->getFileUri(), $formatter_settigns['image_style']);
$default_image_dimensions = ['width' => $default_image_item->width, 'height' => $default_image_item->height];
if ($default_image_style) {
$default_image_style->transformDimensions($default_image_dimensions, $default_image_entity->getFileUri());
}
$elements[0] = [
'#theme' => 'picture',
// Default image
'#img' => [
'src' => $default_image_url,
'alt' => '',
] + $default_image_dimensions,
];
if ($mobile_image_entity) {
$mobile_image_url = $this->getImageStyleUrl($mobile_image_entity->getFileUri(), $formatter_settigns['mobile_image_style']);
// Mobile image
$elements[0]['#source'] = [
'mobile' => [
'srcset' => $mobile_image_url,
'type' => $mobile_image_entity->getMimeType(),
'media' => $mobile_breakpoint->getMediaQuery(),
],
];
}
$elements['#all_in_one'] = TRUE;
return $elements;
}
/**
* {@inheritDoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition): bool {
return $field_definition->getFieldStorageDefinition()->isMultiple();
}
/**
* Return options for "mobile breakpoint" setting.
*/
protected function getMobileBreakpointOptions(string $breakpoint_group): array {
$breakpoint_manager = \Drupal::service('breakpoint.manager'); /** @var BreakpointManagerInterface $breakpoint_manager */
$breakpoints = $breakpoint_manager->getBreakpointsByGroup($breakpoint_group);
return array_map(function ($breakpoint) {
/** @var BreakpointInterface $breakpoint */
return $breakpoint->getLabel();
}, $breakpoints);
}
/**
* Return url for image with image style.
*/
protected function getImageStyleUrl(string $path, string $style_name): string {
$file_url_generator = \Drupal::service('file_url_generator');
if ($style_name && ($image_style = ImageStyle::load($style_name))) {
return $file_url_generator->transformRelative($image_style->buildUrl($path));
}
return $file_url_generator->generateString($path);
}
}
