improvements-2.x-dev/src/Plugin/Field/FieldFormatter/ImageWithMobileAlternativeFormatter.php

src/Plugin/Field/FieldFormatter/ImageWithMobileAlternativeFormatter.php
<?php

namespace Drupal\improvements\Plugin\Field\FieldFormatter;

use Drupal\breakpoint\BreakpointInterface;
use Drupal\breakpoint\BreakpointManagerInterface;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field\Entity\FieldConfig;
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",
 *   label = @Translation("Image with mobile alternative (separate fields)"),
 *   field_types = {
 *     "image",
 *   }
 * )
 */
class ImageWithMobileAlternativeFormatter extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings(): array {
    return [
      'image_style' => '',
      'breakpoint_group' => '',
      'mobile_breakpoint' => '',
      'mobile_field' => '',
      '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 field
      $elements['mobile_field'] = [
        '#type' => 'select',
        '#title' => t('Mobile field'),
        '#options' => $this->getMobileFieldOptions(),
        '#default_value' => $this->getSetting('mobile_field'),
      ];

      // 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_field = $this->getSetting('mobile_field')) {
      $summary[] = t('Mobile field') . ': ' . $mobile_field;
    }
    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 = [];
    $formatter_settigns = $this->getSettings();
    $host_entity = $items->getEntity();
    $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;

    /** @var ImageItem[] $items */
    foreach ($items as $delta => $item) {
      $default_image_entity = $item->entity; /** @var FileInterface $default_image_entity */
      $mobile_image_entity = $host_entity->get($formatter_settigns['mobile_field'])->get($delta)->entity; /** @var FileInterface $mobile_image_entity */
      $default_image_url = $this->getUrlForImageWithStyle($default_image_entity->getFileUri(), $formatter_settigns['image_style']);

      $default_image_dimensions = ['width' => $item->width, 'height' => $item->height];
      if ($default_image_style) {
        $default_image_style->transformDimensions($default_image_dimensions, $default_image_entity->getFileUri());
      }

      $elements[$delta] = [
        '#theme' => 'picture',
        // Default image
        '#img' => [
          'src' => $default_image_url,
          'alt' => '',
        ] + $default_image_dimensions,
      ];

      if ($mobile_image_entity) {
        $mobile_image_url = $this->getUrlForImageWithStyle($mobile_image_entity->getFileUri(), $formatter_settigns['mobile_image_style']);

        // Mobile image
        $elements[$delta]['#source'] = [
          'mobile' => [
            'srcset' => $mobile_image_url,
            'type' => $mobile_image_entity->getMimeType(),
            'media' => $mobile_breakpoint->getMediaQuery(),
          ],
        ];
      }
    }

    return $elements;
  }

  /**
   * Return options for "mobile breakpoint" setting.
   */
  private 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 options for "mobile field" setting.
   */
  private function getMobileFieldOptions(): array {
    $this_field = $this->fieldDefinition; /** @var FieldConfig $this_field */
    $this_field_name = $this_field->getName();
    $entity_field_manager = \Drupal::service('entity_field.manager'); /** @var EntityFieldManager $entity_field_manager */
    $bundle_fields = $entity_field_manager->getFieldDefinitions($this_field->getTargetEntityTypeId(), $this_field->getTargetBundle());

    $options = [];
    foreach ($bundle_fields as $field_name => $field) {
      if ($field->getType() == 'image' && $field->getName() != $this_field_name) {
        $options[$field_name] = $field->getLabel();
      }
    }

    return $options;
  }

  /**
   * Return url for image with image style.
   */
  private function getUrlForImageWithStyle(string $path, string $style_name): string {
    $file_url_generator = \Drupal::service('file_url_generator');

    if ($style_name && ($image_style = ImageStyle::load($style_name))) {
      $url = $image_style->buildUrl($path);
    }
    else {
      $url = $file_url_generator->generateAbsoluteString($path);
    }

    return $file_url_generator->transformRelative($url);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc