toolshed-8.x-1.x-dev/modules/toolshed_media/src/Plugin/Field/FieldFormatter/ImageStyleTrait.php

modules/toolshed_media/src/Plugin/Field/FieldFormatter/ImageStyleTrait.php
<?php

namespace Drupal\toolshed_media\Plugin\Field\FieldFormatter;

use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides the formatter settings, summary, and building for image field.
 *
 * Common methods for supporting either rendering options for responsive image
 * styles or image styles with fields that work images or media.
 */
trait ImageStyleTrait {

  /**
   * Service which retrieves and maintains Drupal system configurations.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected ConfigFactoryInterface $configFactory;

  /**
   * Service which manages various entity types and their handlers.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * Get the default field formatter options for the image styler.
   *
   * This method should be compatible with field formatter defaultSettings()
   * method.
   *
   * @return array
   *   Default options for an image style formatter using these trait options.
   */
  public static function defaultSettings(): array {
    return [
      'image_style' => '',
      'link_to' => NULL,
      'decorative' => FALSE,
      'image_loading' => 'lazy',
    ] + parent::defaultSettings();
  }

  /**
   * Get the current options for linking the image to.
   *
   * @return array<string, string|\Stringable>
   *   An array of 'link to' options with the labels as the value.
   */
  abstract public function getLinkOptions(): array;

  /**
   * Create a renderable array to support field image rendering.
   *
   * The renderable uses the field formatter settings, and the display style
   * settings to build a base renderable with the styles applied. Calling
   * methods are expected to set the "#item" value to provide the image file
   * to render.
   *
   * @param \Drupal\Core\Field\FieldItemListInterface $items
   *   The field items being rendered.
   *
   * @return array
   *   A renderable array to ath be used to generate an formatted image item
   *   element.
   */
  protected function getDisplayRenderable(FieldItemListInterface $items): array {
    $settings = $this->getSettings();
    $style = $settings['image_style'] ?? 'none';
    $styleStorage = $this->entityTypeManager->getStorage('image_style');

    $display = [];
    $display['#theme'] = 'image_formatter';
    $display['#item_attributes'] = ($settings['decorative'] ?? FALSE) ? [
      'role' => 'presentation',
      'alt' => '',
    ] : [];

    // If image loading is an array or null, use "lazy" as the default.
    $display['#item_attributes']['loading'] = $settings['image_loading']['attribute'] ?? 'lazy';

    // Theme with responsive or image preset styles based on user selection.
    if (str_starts_with($style, 'responsive:')) {
      [, $style] = explode(':', $style, 2);

      try {
        /** @var \Drupal\responsive_image\ResponsiveImageStyleInterface $rStyle */
        $rStyle = $this->entityTypeManager
          ->getStorage('responsive_image_style')
          ->load($style);

        if ($rStyle) {
          $cacheTags = $rStyle->getCacheTags();
          foreach ($styleStorage->loadMultiple($rStyle->getImageStyleIds()) as $imgStyle) {
            $cacheTags = Cache::mergeTags($cacheTags, $imgStyle->getCacheTags());
          }

          $display['#theme'] = 'responsive_image_formatter';
          $display['#responsive_image_style_id'] = $style;
          $display['#cache']['tags'] = $cacheTags;
        }
      }
      catch (PluginNotFoundException $e) {
        // Responsive image module is missing, fallback to an image formatter.
      }
    }
    elseif ('none' !== $style && $imageStyle = $styleStorage->load($style)) {
      $display['#image_style'] = $style;
      $display['#cache'] = [
        'tags' => $imageStyle->getCacheTags(),
      ];
    }

    $display['#url'] = @('entity' === $settings['link_to'])
      ? $items->getEntity()->toUrl()
      : NULL;

    return $display;
  }

  /**
   * Generates a field formatter summary.
   *
   * The summary should be compatible with the field formatter
   * ::settingsSummary() method.
   *
   * @return array
   *   The field formatter settings summary.
   *
   * @see \Drupal\Core\Field\FormatterInterface::settingsSummary()
   */
  public function settingsSummary(): array {
    if ($styleId = $this->getSetting('image_style')) {
      if (str_starts_with($styleId, 'responsive:')) {
        try {
          [, $rStyleId] = explode(':', $styleId, 2);
          $styler = $this->entityTypeManager
            ->getStorage('responsive_image_style')
            ->load($rStyleId);
        }
        catch (PluginNotFoundException $e) {
          // Responsive image style module is missing, skip.
        }
      }
      else {
        $styler = $this->entityTypeManager
          ->getStorage('image_style')
          ->load($styleId);
      }
    }

    $styleParams = [
      '@label' => isset($styler) ? $styler->label() : $this->t('Original'),
    ];

    $summary = [];
    $summary[] = $this->getSetting('decorative')
      ? $this->t('Image style (decorative): @label', $styleParams)
      : $this->t('Image style: @label', $styleParams);

    $summary[] = $this->t('Image loading: :loading', [
      ':loading' => $this->getSetting('image_loading')['attribute'] ?? 'lazy',
    ]);

    $linkTo = $this->getSetting('link_to');
    $linkOpts = $this->getLinkOptions();
    if (!empty($linkTo) && !empty($linkOpts[$linkTo])) {
      $summary[] = $this->t('Link to: @target', [
        '@target' => $linkOpts[$linkTo],
      ]);
    }

    // Fallback is only needed for media types when no thumbnail available.
    if ('image' !== $this->fieldDefinition->getType()) {
      $summary[] = $this->t('Fallback display: %fallback_display', [
        '%fallback_display' => $this->getSetting('fallback_display'),
      ]);
    }

    return $summary;
  }

  /**
   * Generates a config form for the image styler formatter settings.
   *
   * @return array
   *   Image style settings form for the media styler formatters.
   *
   * @see \Drupal\Core\Field\FormatterInterface::settingsForm()
   */
  public function settingsForm(array $form, FormStateInterface $form_state): array {
    $form = parent::settingsForm($form, $form_state);
    $styleStorage = $this->entityTypeManager->getStorage('image_style');

    $styleOpts = ['none' => $this->t('Original')];
    foreach ($styleStorage->loadMultiple() as $styleId => $style) {
      $styleOpts[$styleId] = $style->label();
    }

    // Add responsive image styles if any are available.
    try {
      $responsiveOpts = [];
      $responsiveStorage = $this->entityTypeManager->getStorage('responsive_image_style');

      /** @var \Drupal\responsive_image\ResponsiveImageStyleInterface $responsive */
      foreach ($responsiveStorage->loadMultiple() as $responsiveId => $responsive) {
        if ($responsive->hasImageStyleMappings()) {
          $responsiveOpts["responsive:{$responsiveId}"] = $responsive->label();
        }
      }
    }
    catch (PluginNotFoundException $e) {
      // Responsive image styles is not installed, we can safely skip.
    }

    // If being used with embed styles, filter the allowed embed styles to
    // only the allowed styles. This prevents the usage of image presets
    // that don't make sense here or, could be dangerous in an embed situation.
    if ($this->viewMode === '_entity_embed') {
      $embedStyles = $this->configFactory->get('toolshed.media.embed_styles');
      $filterStyles = $embedStyles->get('styles');
      $filterResponsive = $embedStyles->get('responsiveStyles');

      if (!empty($filterStyles)) {
        $styleOpts = $embedStyles->get('filter_method') === 'only_listed'
          ? array_intersect_key($styleOpts, $filterStyles)
          : array_diff_key($styleOpts, $filterStyles);
      }
      if ($responsiveOpts && $filterResponsive) {
        $styleOpts = $embedStyles->get('filter_method') === 'only_listed'
          ? array_intersect_key($responsiveOpts, $filterResponsive)
          : array_diff_key($responsiveOpts, $filterResponsive);
      }
    }

    $form['image_style'] = [
      '#type' => 'select',
      '#title' => $this->t('Image style'),
      // Make responsive options available if any of them are available.
      '#options' => $responsiveOpts ? [
        (string) $this->t('Image styles') => $styleOpts,
        (string) $this->t('Responsive styles') => $responsiveOpts,
      ] : $styleOpts,
      '#default_value' => $this->getSetting('image_style'),
    ];
    $form['decorative'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Is image decorative?'),
      '#default_value' => $this->getSetting('decorative'),
    ];
    $form['image_loading'] = [
      '#type' => 'details',
      '#title' => $this->t("Image loading"),
      '#tree' => TRUE,

      'attribute' => [
        '#type' => 'select',
        '#options' => [
          'lazy' => $this->t('Lazy (load when in viewport)'),
          'eager' => $this->t('Eager (load immediately)'),
        ],
        '#default_value' => $this->getSetting('image_loading')['attribute'] ?? 'lazy',
        '#description' => $this->t('<p>Select how to render and load images using the loading attribute (<em>loading=lazy</em>). This improves performance by allowing browsers to lazily load images.</p><p><a href=":link">Learn more about the loading attribute for images.</a></p>', [
          ':link' => 'https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-loading-attributes',
        ]),
      ],
    ];
    $form['link_to'] = [
      '#type' => 'select',
      '#title' => $this->t('Link to:'),
      '#options' => [
        '' => $this->t('No link'),
      ] + $this->getLinkOptions(),
      '#default_value' => $this->getSetting('link_to'),
    ];

    return $form;
  }

}

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

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