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

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

namespace Drupal\toolshed_media\Plugin\Field\FieldFormatter;

use Drupal\Component\Utility\Html;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\Attribute\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * A Field formatter for displaying media with more options.
 *
 * The formatter used to be applied to media and image fields but it added
 * unnecessary overhead that can be removed by separating the formatters. The
 * formatter is already in use with this plugin ID and needs to be kept until
 * a migration can be provided.
 *
 * @FieldFormatter(
 *   id = "toolshed_image_style",
 *   label = @Translation("Toolshed: Media image styler"),
 *   field_types = {
 *     "entity_reference",
 *     "entity_reference_revision",
 *   }
 * );
 */
#[FieldFormatter(
  id: 'toolshed_image_style',
  label: new TranslatableMarkup('Toolshed: Media image styler'),
  field_types: [
    'entity_reference',
    'entity_reference_revision',
  ],
)]
class MediaStyleFormatter extends EntityReferenceFormatterBase implements ContainerFactoryPluginInterface {

  use ImageStyleTrait {
    settingsForm as stylerSettingsForm;
  }

  /**
   * Service for managing the various entity view modes.
   *
   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
   */
  protected EntityDisplayRepositoryInterface $entityDisplayRepo;

  /**
   * Media image style formatter object.
   *
   * @param array $configuration
   *   Array of plugin configuration options which includes the field formatter
   *   definition information:
   *     - $field_definition
   *     - $settings
   *     - $label
   *     - $view_mode
   *     - $third_party_settings
   *   These are the usual values for constructing a standard field formatter.
   * @param string $plugin_id
   *   The plugin_id for the formatter.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   Service for retrieving and maintain Drupal system configurations.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity manager service, for getting entity definitions and handlers.
   * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
   *   Manage entity view mode configurations and displays.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, EntityDisplayRepositoryInterface $entity_display_repository) {
    parent::__construct(
      $plugin_id,
      $plugin_definition,
      $configuration['field_definition'],
      $configuration['settings'],
      $configuration['label'],
      $configuration['view_mode'],
      $configuration['third_party_settings']
    );

    $this->configFactory = $config_factory;
    $this->entityTypeManager = $entity_type_manager;
    $this->entityDisplayRepo = $entity_display_repository;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('config.factory'),
      $container->get('entity_type.manager'),
      $container->get('entity_display.repository')
    );
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings(): array {
    return [
      'image_style' => '',
      'link_to' => NULL,
      'decorative' => FALSE,
      'image_loading' => 'lazy',
      'fallback_display' => 'default',
    ] + parent::defaultSettings();
  }

  /**
   * Is the media reference have types that are compatible with an images.
   *
   * @param string[] $bundles
   *   The allowed bundles for the media type.
   *
   * @return bool
   *   Are the bundles a image or video compatible type?
   */
  protected static function hasAllowedMediaBundles(array $bundles = []): bool {
    static $imageBundles = NULL;

    if (empty($bundles)) {
      return TRUE;
    }

    if (!isset($imageBundles)) {
      try {
        $sources = ['image', 'video'];
        $imageBundles = \Drupal::entityTypeManager()
          ->getStorage('media_type')
          ->getQuery()
          ->accessCheck(FALSE)
          ->condition('source', $sources, 'IN')
          ->execute();
      }
      catch (\throwable) {
        $imageBundles = [];
      }
    }

    return (bool) array_intersect($imageBundles, $bundles);
  }

  /**
   * {@inheritdoc}
   */
  public static function isApplicable(FieldDefinitionInterface $fieldDef): bool {
    $fieldStorageDef = $fieldDef->getFieldStorageDefinition();
    $settings = $fieldDef->getSetting('handler_settings');

    return 'media' === $fieldStorageDef->getSettings()['target_type']
      && static::hasAllowedMediaBundles($settings['target_bundles'] ?? []);
  }

  /**
   * 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.
   */
  public function getLinkOptions(): array {
    return [
      'entity' => $this->t('Content entity'),
      'media' => $this->t('Media'),
    ];
  }

  /**
   * {@inheritdoc}
   *
   * @param \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items
   *   The field entity reference items.
   * @param string $langcode
   *   The language that should be used to render the field.
   */
  public function viewElements(FieldItemListInterface $items, $langcode): array {
    $elements = [];
    if ('media' !== $this->fieldDefinition->getSetting('target_type')) {
      return $elements;
    }

    $display = $this->getDisplayRenderable($items);
    $linkToMedia = 'media' === $this->getSetting('link_to');

    /** @var \Drupal\media\MediaInterface $media */
    foreach ($this->getEntitiesToView($items, $langcode) as $delta => $media) {
      // Should only be applied to media entity types, which have a base field
      // of "thumbnail" so field should always exist, but it can still be empty
      // if the source plugin does not produce a thumbnail image file.
      /** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $imageItem */
      $imageItem = $media->get('thumbnail')->first();

      if ($imageItem && $imageItem->entity) {
        $elements[$delta] = $display;
        $elements[$delta]['#item'] = $imageItem;

        if ($linkToMedia) {
          $elements[$delta]['#url'] = $media->toUrl();
        }

        // Ensure that the item cache includes the media entity that owns it.
        CacheableMetadata::createFromRenderArray($display)
          ->addCacheableDependency($media)
          ->applyTo($elements[$delta]);
      }
      else {
        // Fallback, to use the media view builder. Used if media entity is not
        // targeting an image or if we are unable to load the needed file info.
        $elements[$delta] = $this->entityTypeManager
          ->getViewBuilder('media')
          ->view($media, $this->getSetting('fallback_display'));
      }
    }

    return $elements;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state): array {
    $form = $this->stylerSettingsForm($form, $form_state);

    // Provide media entity display mode as a fallback when no media thumbnail.
    $fieldStorageDef = $this->fieldDefinition->getFieldStorageDefinition();
    $targetType = $fieldStorageDef->getSettings()['target_type'];

    $viewModes = ['default' => $this->t('Default')];
    foreach ($this->entityDisplayRepo->getViewModes($targetType) as $viewModeId => $viewMode) {
      $viewModes[$viewModeId] = Html::escape((string) $viewMode['label']);
    }

    $form['fallback_display'] = [
      '#type' => 'select',
      '#title' => $this->t('Fallback display mode'),
      '#options' => $viewModes,
      '#default_value' => $this->getSetting('fallback_display'),
      '#description' => $this->t('If the the media entity is not an image, image styles cannot be applied and will use this view mode to render as a fallback.'),
    ];

    return $form;
  }

}

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

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