acquia_dam-1.0.0-rc1/src/EmbedCodeFactory.php

src/EmbedCodeFactory.php
<?php

namespace Drupal\acquia_dam;

use Drupal\acquia_dam\Entity\ImageAltTextField;
use Drupal\acquia_dam\Entity\MediaSourceField;
use Drupal\acquia_dam\Exception\DamServerException;
use Drupal\acquia_dam\Plugin\Field\FieldType\AssetItem;
use Drupal\Core\Link;
use Drupal\Core\Security\TrustedCallbackInterface;
use Drupal\Core\TypedData\Exception\MissingDataException;
use Drupal\Core\Url;
use Drupal\media\MediaInterface;

/**
 * Generates specific embed codes depending on the source plugins of the media item.
 */
final class EmbedCodeFactory implements TrustedCallbackInterface {

  /**
   * Returns array containing select options for select render.
   *
   * @param string|null $asset_type
   *   Asset type.
   *
   * @return string[]
   *   Select options for given type or full mapping if asset type not provided.
   */
  public static function getSelectOptions(string $asset_type = NULL): array {
    // Generated url won't have the download option.
    // https://www.drupal.org/project/drupal/issues/2984272 Core issue where
    // "." in the query parameter gets replaced with "_" so the url with
    // "t.download=true" will be replaced with "t_download=true".
    $image_styles = [];
    /** @var \Drupal\acquia_dam\ImageStyleHelper $image_style_helper */
    $image_style_helper = \Drupal::service('acquia_dam.image_style_support');
    foreach ($image_style_helper->getAllowedImageStyles() as $styles) {
      $image_styles[$styles->id()] = $styles->label();
    }
    $image_styles = ['original' => 'Original'] + $image_styles;
    $mapping = [
      'pdf' => [
        'inline_view_download' => 'Inline viewer with download',
        'inline_view' => 'Inline viewer without download',
        'link_text_download' => 'Text linked to viewer with download',
        'link_text' => 'Text linked to viewer without download',
        'link_thumbnail_download' => 'Thumbnail linked to viewer with download',
        'link_thumbnail' => 'Thumbnail linked to viewer without download',
      ],
      'video' => [
        'inline_view_download' => 'Inline player with download',
        'inline_view' => 'Inline player without download',
        'link_thumbnail_download' => 'Thumbnail linked to player with download',
        'link_thumbnail' => 'Thumbnail linked to player without download',
        'video_stream' => 'Video without player',
      ],
      'spinset' => [
        'inline_view' => 'Inline viewer without download',
        'link_text' => 'Text linked to viewer without download',
      ],
      'image' => $image_styles,
      'documents' => [
        'inline_view_download' => 'Inline viewer with download',
        'link_text_download' => 'Text linked to viewer with download',
        'link_thumbnail_download' => 'Thumbnail linked to viewer with download',
        'link_thumbnail' => 'Thumbnail linked to viewer without download',
      ],
    ];

    // If the universal 'remotely referenced thumbnail image' option is the default embed style of this formatter used
    // for this field type, then add it to all media types as it's independent from them.
    $field_definition = \Drupal::service('plugin.manager.field.field_type')->getDefinition('acquia_dam_asset');

    if (isset($field_definition['default_formatter'])) {
      $default_formatter_settings = \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings('acquia_dam_embed_code');

      if (isset($default_formatter_settings['embed_style'])) {
        $default_embed_style = $default_formatter_settings['embed_style'];
        $remote_thumbnail_embed_style_name = 'remotely_referenced_thumbnail_image';

        if ($default_embed_style === $remote_thumbnail_embed_style_name) {
          $thumbnail_image_option = [$remote_thumbnail_embed_style_name => 'Thumbnail image of the finalized asset version, or the alternate preview if set'];
          if ($asset_type) {
            foreach ($mapping as $key => $value) {
              $mapping[$key] += $thumbnail_image_option;
            }
          }
          else {
            $mapping['Generic'] = $thumbnail_image_option;
          }
        }
      }
    }

    return $asset_type ? $mapping[$asset_type] : $mapping;
  }

  /**
   * Returns a render array based on the parameters.
   *
   * @param string $format
   *   Embed code id for formatting.
   * @param MediaInterface $media
   *   Media instance.
   * @param int|null $thumbnail_width
   *   (optional) Asset thumbnail width to render.
   *
   * @return array
   *   Render array.
   *
   * @throws DamServerException
   * @throws MissingDataException
   */
  public static function renderAsset(string $format, MediaInterface $media, ?int $thumbnail_width = 150): array {
    $embed_code = [];

    /** @var \Drupal\acquia_dam\Plugin\media\Source\Asset $source */
    $source = $media->getSource();
    $asset_field = $media->get(MediaSourceField::SOURCE_FIELD_NAME)->first();
    // @todo fetch alt text from asset metadata for a proper value.
    // $media->getFieldDefinition(ImageAltTextField::IMAGE_ALT_TEXT_FIELD_NAME)
    // $media->get(ImageAltTextField::IMAGE_ALT_TEXT_FIELD_NAME)->first()
    $alt_text = $media->label();

    // Providing the embed code of the thumbnail image is independent from the media type.
    if ($format === 'remotely_referenced_thumbnail_image') {
      $remote_thumbnail_uri = $source->getMetadata($media, 'thumbnail_uri_remote');

      return [
        '#theme' => 'image',
        '#uri' => preg_replace('/\/150(px@2x\/\?q=)/', "/{$thumbnail_width}$1", $remote_thumbnail_uri),
        '#alt' => $alt_text,
        '#attributes' => [
          'width' => $thumbnail_width,
        ],
      ];
    }

    // Get the domain for the embed code.
    $embed_codes = $source->getMetadata($media, 'embeds');
    $original = parse_url($embed_codes['original']['url']);
    $domain = "https://" . $original['host'];
    $external_id = $source->getMetadata($media, 'external_id');

    switch ($source->getDerivativeId()) {
      case 'documents':
      case 'pdf':
        $embed_code = self::renderDocumentsPdfAsset($domain, $external_id, $format, $media->getName(), self::encodeFilename($media->getName()));
        break;

      case 'video':
        $embed_code = self::renderVideoAsset($domain, $external_id, $format, $media->getName(), self::encodeFilename($media->getName()));
        break;

      case 'spinset':
        $embed_code = self::renderSpinsetAsset($domain, $external_id, $format, $media->getName(), self::encodeFilename($media->getName()));
        break;

      case 'image':
        assert($asset_field instanceof AssetItem);
        $image_properties = $source->getMetadata($media, 'image_properties');
        if ($format == 'original') {
          $embed_code = [
            '#theme' => 'image',
            '#uri' => "acquia-dam://$asset_field->asset_id/$asset_field->version_id",
            // @todo fetch alt from metadata for a proper value.
            '#alt' => $alt_text,
            '#width' => $image_properties['width'],
            '#height' => $image_properties['height'],
          ];
        }
        else {
          $embed_code = [
            '#theme' => 'image_style',
            '#uri' => "acquia-dam://$asset_field->asset_id/$asset_field->version_id.png",
            '#style_name' => $format,
            // @todo fetch alt from metadata for a proper value.
            '#alt' => $alt_text,
            '#width' => $image_properties['width'],
            '#height' => $image_properties['height'],
          ];
        }

        break;
    }

    return $embed_code;
  }

  /**
   * Returns a pdf/document asset render array based on the parameters.
   *
   * @param string $domain
   *   Domain.
   * @param string $external_id
   *   Asset external id.
   * @param string $format
   *   Embed code id for formatting.
   * @param string $filename
   *   Media name.
   * @param string $encoded_filename
   *   URL encoded filename.
   *
   * @return array
   *   Render array.
   */
  protected static function renderDocumentsPdfAsset(string $domain, string $external_id, string $format, string $filename, string $encoded_filename) :array {
    switch ($format) {
      case 'original':
        $url = "{$domain}/content/{$external_id}/original/{$encoded_filename}?download=true";
        $embed = self::renderAsLink($url, $filename);
        break;

      case 'inline_view_download':
        $embed = [
          '#type' => 'html_tag',
          '#tag' => 'iframe',
          '#attributes' => [
            'src' => "{$domain}/view/pdf/{$external_id}/{$encoded_filename}?t.download=true",
            'title' => "Document for $filename",
            'webkitallowfullscreen' => '',
            'mozallowfullscreen' => '',
            'allowfullscreen' => '',
          ],
        ];
        break;

      case 'inline_view':
        $embed = [
          '#type' => 'html_tag',
          '#tag' => 'iframe',
          '#attributes' => [
            'src' => "{$domain}/content/{$external_id}/pdf/{$encoded_filename}",
            'title' => "Document for $filename",
            'webkitallowfullscreen' => '',
            'mozallowfullscreen' => '',
            'allowfullscreen' => '',
          ],
        ];
        break;

      case 'link_text_download':
        $url = "{$domain}/view/pdf/{$external_id}/{$encoded_filename}?t.download=true";
        $embed = self::renderAsLink($url, $filename);
        break;

      case 'link_text':
        $url = "{$domain}/content/{$external_id}/pdf/{$encoded_filename}";
        $embed = self::renderAsLink($url, $filename);
        break;

      case 'link_thumbnail_download':
        $filename_without_extension = self::getFilenameWithoutExtension($encoded_filename);

        $asset_url = "{$domain}/view/pdf/{$external_id}/{$encoded_filename}?t.download=true";
        $thumbnail_url = "{$domain}/content/{$external_id}/jpeg/{$filename_without_extension}.jpg";

        $embed = self::renderAsThumbnailLink($asset_url, $thumbnail_url, $filename);
        break;

      case 'link_thumbnail':
        $filename_without_extension = self::getFilenameWithoutExtension($encoded_filename);

        $asset_url = "{$domain}/view/pdf/{$external_id}/{$filename}?t.download=true";
        $thumbnail_url = "{$domain}/content/{$external_id}/jpeg/{$filename_without_extension}.jpg";

        $embed = self::renderAsThumbnailLink($asset_url, $thumbnail_url, $filename);
        break;

      default:
        $embed = [];
    }

    return $embed;
  }

  /**
   * Returns a video asset render array based on the parameters.
   *
   * @param string $domain
   *   Domain.
   * @param string $external_id
   *   Asset external id.
   * @param string $format
   *   Embed code id for formatting.
   * @param string $filename
   *   Filename.
   * @param string $encoded_filename
   *   URL encoded filename.
   *
   * @return array
   *   Render array.
   */
  protected static function renderVideoAsset(string $domain, string $external_id, string $format, string $filename, string $encoded_filename): array {
    switch ($format) {
      case 'original':
        $url = "{$domain}/content/{$external_id}/original/{$encoded_filename}?download=true";
        $embed = self::renderAsLink($url, $filename);
        break;

      case 'inline_view_download':
        $embed = [
          '#theme' => 'acquia_dam_iframe_responsive',
          '#src' => "{$domain}/view/video/{$external_id}/{$encoded_filename}?t.download=true",
        ];
        break;

      case 'inline_view':
        $embed = [
          '#theme' => 'acquia_dam_iframe_responsive',
          '#src' => "{$domain}/view/video/{$external_id}/{$encoded_filename}",
        ];
        break;

      case 'link_thumbnail_download':
        $filename_without_extension = self::getFilenameWithoutExtension($encoded_filename);

        $asset_url = "{$domain}/view/video/{$external_id}/{$encoded_filename}?t.download=true";
        $thumbnail_url = "{$domain}/content/{$external_id}/jpeg/{$filename_without_extension}.jpg";

        $embed = self::renderAsThumbnailLink($asset_url, $thumbnail_url, $filename);
        break;

      case 'link_thumbnail':
        $filename_without_extension = self::getFilenameWithoutExtension($encoded_filename);

        $asset_url = "{$domain}/view/video/{$external_id}/{$encoded_filename}";
        $thumbnail_url = "{$domain}/content/{$external_id}/jpeg/{$filename_without_extension}.jpg";

        $embed = self::renderAsThumbnailLink($asset_url, $thumbnail_url, $filename);
        break;

      case 'video_stream':
        $embed = [
          '#theme' => 'acquia_dam_video_stream',
          '#attributes' => [
            "controls" => "controls",
          ],
          '#source_attributes' => [
            'src' => "{$domain}/content/{$external_id}/mp4/{$encoded_filename}?quality=hd",
            'video' => "video/mp4",
          ],
        ];
        break;

      default:
        $embed = [];
    }

    return $embed;
  }

  /**
   * Returns a spinset asset render array based on the parameters.
   *
   * @param string $domain
   *   Domain.
   * @param string $external_id
   *   Asset external id.
   * @param string $format
   *   Embed code id for formatting.
   * @param string $filename
   *   Filename.
   * @param string $encoded_filename
   *   URL encoded filename.
   *
   * @return array
   *   Render array.
   */
  protected static function renderSpinsetAsset(string $domain, string $external_id, string $format, string $filename, string $encoded_filename): array {
    switch ($format) {
      case 'original':
        $embed = [
          '#type' => 'markup',
          '#markup' => "{$domain}/content/{$external_id}/original/{$encoded_filename}?download=true",
        ];
        break;

      case 'inline_view':
        $embed = [
          '#theme' => 'acquia_dam_iframe_responsive',
          '#src' => "{$domain}/view/spinset/{$external_id}/{$encoded_filename}",
        ];
        break;

      case 'link_text':
        $url = "{$domain}/view/spinset/{$external_id}/{$encoded_filename}";
        $embed = self::renderAsLink($url, $filename);
        break;

      default:
        $embed = [];
    }

    return $embed;
  }

  /**
   * Returns link pointing to the given asset embed.
   *
   * @param string $url
   *   Link url.
   * @param string $asset_name
   *   Asset name as link name.
   *
   * @return array
   *   Render array.
   */
  protected static function renderAsLink(string $url, string $asset_name): array {
    $link = Link::fromTextAndUrl($asset_name, Url::fromUri($url, ['attributes' => ['target' => '_blank']]));
    $render_array = $link->toRenderable();
    $render_array['#post_render'] = [[static::class, 'postRenderDamLink']];
    return $render_array;
  }

  /**
   * Returns thumbnail as a link.
   *
   * @param string $url
   *   Asset url.
   * @param string $thumbnail_url
   *   Thumbnail url.
   * @param string $name
   *   File name.
   *
   * @return array
   *   Render array.
   */
  protected static function renderAsThumbnailLink(string $url, string $thumbnail_url, string $name): array {
    $link_title = [
      '#theme' => 'image',
      '#width' => 300,
      '#height' => 300,
      '#uri' => $thumbnail_url,
      '#alt' => sprintf('%s preview', $name),
    ];

    return [
      '#type' => 'container',
      '#theme_wrappers' => ['container__acquia_dam_asset'],
      'embed' => [
        '#type' => 'link',
        '#title' => $link_title,
        '#url' => Url::fromUri($url, ['attributes' => ['target' => '_blank']]),
        '#post_render' => [[static::class, 'postRenderDamLink']],
      ],
    ];
  }

  /**
   * Replace t_download within the markup with the correct key.
   *
   * @param string $markup
   *   Link markup generated for embed code.
   *
   * @return string
   *   Markup.
   */
  public static function postRenderDamLink(string $markup) {
    if (!str_contains($markup, 't_download')) {
      return $markup;
    }

    return str_replace('t_download', 't.download', $markup);
  }

  /**
   * {@inheritdoc}
   */
  public static function trustedCallbacks() {
    return ['postRenderDamLink'];
  }

  /**
   * Replaces certain characters in the filename so it matches the DAM ones.
   *
   * @param string $filename
   *   Media name.
   *
   * @return string
   *   Returns filename.
   */
  private static function encodeFilename(string $filename) {
    return str_replace(
      [' ', "'", '"'],
      ['-', '', ''],
      $filename
    );
  }

  /**
   * Gets a filename without the extension.
   *
   * @param string $filename
   *   Media name.
   *
   * @return string
   *   Returns filename without the extension.
   */
  private static function getFilenameWithoutExtension(string $filename) {
    $filename_without_extension = pathinfo($filename, PATHINFO_FILENAME);
    $filename_without_extension = urlencode($filename_without_extension);

    return $filename_without_extension;
  }

}

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

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