media_helper-2.0.0/src/Service/TwigExtension.php

src/Service/TwigExtension.php
<?php

namespace Drupal\media_helper\Service;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\Core\Render\Element;
use Drupal\media\MediaInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
use function is_array;
use function is_int;
use function is_string;

/**
 * Twig extension that provides Media Helper's functions and filters.
 */
class TwigExtension extends AbstractExtension {

  /**
   * Instantiates the TwigExtension service.
   */
  public function __construct(
    protected EntityTypeManagerInterface $entityTypeManager,
    protected MediaHelper $mediaHelper,
  ) {
  }

  /**
   * {@inheritdoc}
   */
  public function getFilters() {
    $filters = [
      new TwigFilter('media_first_nonempty', [$this, 'mediaFirstNonempty']),
      new TwigFilter('media_image', [$this, 'mediaImage']),
      new TwigFilter('media_image_url', [$this, 'mediaImageUrl']),
      new TwigFilter('media_video', [$this, 'mediaVideo']),
    ];

    return $filters;
  }

  /**
   * {@inheritdoc}
   */
  public function getFunctions() {
    $filters = [
      new TwigFunction('media_bundle', [$this, 'mediaBundle']),
      new TwigFunction('media_source', [$this, 'mediaSource']),
    ];

    return $filters;
  }

  /**
   * Get the type for the given media entity(s).
   *
   * Examples:
   * {{ media_bundle(node.field_media_image) }}
   * {{ media_bundle(content.field_media_image) }}
   * {{ media_bundle(6) }}
   * {{ media_bundle(media_entity_object) }}
   *
   * @param mixed $input
   *   The input from Twig.
   *
   * @return string|null
   *   The bundle ID of the passed media.
   *   If there is no identifiable media entity, NULL will be returned.
   *   If there are multiple entities all of the same bundle, that bundle ID will be returned.
   *   If there are multiple entities of different bundles, the string "mixed" will be returned.
   */
  public function mediaBundle($input): ?string {
    $medias = $this->getMedias($input);

    if ($medias) {
      return $this->mediaHelper->mediaBundle($medias);
    }

    return NULL;
  }

  /**
   * Get the source ID for the given media entity(s).
   *
   * Examples:
   * {{ media_source(node.field_media_image) }}
   * {{ media_source(content.field_media_image) }}
   * {{ media_source(6) }}
   * {{ media_source(media_entity_object) }}
   *
   * @param mixed $input
   *   The input from Twig.
   *
   * @return string|null
   *   The ID of the source of the passed media.
   *   If an empty array is passed, NULL will be returned.
   *   If there are multiple entities all having the same media source, that source ID will be returned.
   *   If there are multiple entities of different sources, the string "mixed" will be returned.
   */
  public function mediaSource($input): ?string {
    $medias = $this->getMedias($input);

    if ($medias) {
      return $this->mediaHelper->mediaSource($medias);
    }

    return NULL;
  }

  /**
   * Get the first non-empty value in an array of values.
   *
   * Example:
   * {{ [node.field_media_image, fallback_image]|media_first_nonempty }}
   *
   * @param mixed $input
   *   Input from Twig. Expected to be iterable.
   *
   * @return mixed
   *   The first nonempty value, or NULL if there is no meaningful input.
   */
  public function mediaFirstNonempty($input) {
    if (!$input) {
      return NULL;
    }

    if (!is_iterable($input)) {
      trigger_error('|media_first_nonempty Twig filter expects an iterable such as an array', E_USER_WARNING);
      return NULL;
    }

    foreach ($input as $possible_value) {
      $medias = $this->getMedias($possible_value);
      if ($medias) {
        return $possible_value;
      }
      elseif ($medias === NULL) {
        return $possible_value;
      }
    }

    return NULL;
  }

  /**
   * Render a media image.
   *
   * Examples:
   * {{ node.field_media_image|media_image('500x500') }}
   * {{ content.field_media_image|media_image }}
   * {{ 6|media_image }}
   * {{ media_entity_object|media_image }}
   *
   * All arguments are optional. In addition to an image style, class(es) to add to the image tag may also be specified.
   * Examples:
   * {{ node.field_media_image|media_image('500x500', 'my-class') }}
   * {{ node.field_media_image|media_image('style', ['hi', 'there']) }}
   *
   * @param mixed $input
   *   The input from Twig.
   * @param string $style
   *   (optional) The machine name of the image style to use. If not specified, the image style used on the media's
   *   default display mode will be used instead - or if that cannot be discovered, the original image.
   *   Also supports Responsive Image module transparently. Specify the machine name of a responsive image style to use
   *   it. (Identical machine names in the two modules will resolve to the basic, non-responsive style.)
   * @param string|string[] $classes
   *   (optional) Class(es) to add to the element, as a string or array of strings.
   * @param array $attributes
   *   (optional) Attributes to add to the element, name => value.
   *
   * @return array|null
   *   A render array, or NULL if there is no meaningful input or output.
   */
  public function mediaImage($input, string $style = '', $classes = '', array $attributes = []): ?array {
    $medias = $this->getMedias($input);
    if ($medias) {
      return $this->mediaHelper->mediaImage($medias, $style, $classes, $attributes);
    }
    elseif ($medias === NULL) {
      return $input;
    }
    return NULL;
  }

  /**
   * Render a media image URL.
   *
   * Examples:
   * {{ node.field_media_image|media_image('500x500') }}
   * {{ content.field_media_image|media_image }}
   * {{ 6|media_image }}
   * {{ media_entity_object|media_image }}
   *
   * All arguments are optional.
   *
   * @param mixed $input
   *   The input from Twig.
   * @param string $style
   *   (optional) The machine name of the image style to use.
   *
   * @return array|null
   *   A render array, or NULL if there is no meaningful input or output.
   *   (A render array must be used for cache metadata bubbling.)
   */
  public function mediaImageUrl($input, string $style = ''): ?array {
    $medias = $this->getMedias($input);
    if ($medias) {
      return $this->mediaHelper->mediaImageUrl($medias, $style);
    }
    elseif ($medias === NULL) {
      return $input;
    }
    return NULL;
  }

  /**
   * Render a media uploaded video.
   *
   * Examples:
   * {{ node.field_media_video|media_video('custom-class') }}
   * {{ content.field_media_video|media_video }}
   * {{ 6|media_video }}
   * {{ media_entity_object|media_video }}
   *
   * All arguments are optional. CSS class(es), Drupal video widget settings, and/or <video> tag attributes may also be
   * specified. Examples:
   * {{ node.field_media_video|media_video('my-custom-class') }}
   * {{ node.field_media_video|media_video('', { width: 200, height: 300 }) }}
   * {{ node.field_media_video|media_video(
   *   '',
   *   {},
   *   { 'data-custom-attr': 'my_value' }
   * )}}
   *
   * @param mixed $input
   *   The input from Twig.
   * @param string|array $classes
   *   (optional) Class(es) to add to the <video> element, as a string or array
   *   of strings.
   * @param array $settings
   *   (optional) Settings overrides for the Drupal file_video display widget.
   *   These defaults are used:
   *     'autoplay' => TRUE
   *     'controls' => FALSE
   *     'loop' => TRUE
   *     'muted' => TRUE
   *     'multiple_file_display_type' => 'sources'
   *     'width' => NULL
   *     'height' => NULL
   *   and can be overridden by setting the value in this argument.
   * @param array $attributes
   *   (optional) Attributes to add to the <video> element, name => value.
   *   If the autoplay setting is on (which it is by default), the attributes 'disablePictureInPicture' and
   *   'playsinline' are added if not already set.
   *
   * @return array|null
   *   A render array, or NULL if there is no meaningful input or output.
   */
  public function mediaVideo($input, $classes = '', array $settings = [], array $attributes = []): ?array {
    $medias = $this->getMedias($input);
    if ($medias) {
      return $this->mediaHelper->mediaVideo($medias, $classes, $settings, $attributes);
    }
    elseif ($medias === NULL) {
      return $input;
    }
    else {
      return NULL;
    }
  }

  /**
   * Returns media object(s) given Twig input.
   *
   * @param mixed $input
   *   The input from Twig. Multiple input types are accepted:
   *   - A media reference field (e.g. node.field_id).
   *   - The render array from a media reference field. ("Rendered entity" format supported. Other formats may not be.)
   *   - One media entity object.
   *   - One media entity ID.
   *
   * @return \Drupal\media\MediaInterface[]|null
   *   A (possibly empty) array of media objects, or NULL if this looks like an empty render array that should be
   *   output unmodified.
   */
  protected function getMedias($input): ?array {
    if (!$input) {
      return [];
    }

    // Handle direct input of media entity.
    if ($input instanceof MediaInterface) {
      return [$input];
    }

    // Handle reference field.
    if ($input instanceof EntityReferenceFieldItemListInterface) {
      return $input->referencedEntities();
    }

    // Handle media entity ID.
    if (
      (is_int($input) && $input > 0)
      || (is_string($input) && ctype_digit($input))
    ) {
      return $this->entityTypeManager->getStorage('media')->loadMultiple([$input]);
    }

    // Handle reference field render array.
    if (is_array($input) && isset($input['#field_type']) && $input['#field_type'] === 'entity_reference') {
      $medias = [];
      foreach (Element::getVisibleChildren($input) as $key) {
        if (isset($input[$key]['#media']) && $input[$key]['#media'] instanceof MediaInterface) {
          $medias[] = $input[$key]['#media'];
        }
      }
      return $medias;
    }

    // Sometimes a render array might be completely empty if the field is empty or if no entities pass access control.
    // In those cases, return the render array as-is to make sure the cache data bubbles.
    if (is_array($input) && !isset($input['#field_type']) && isset($input['#cache'])) {
      return NULL;
    }

    return [];
  }

}

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

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