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\Plugin\Field\FieldType\AssetItem; use Drupal\Core\Link; use Drupal\Core\Security\TrustedCallbackInterface; use Drupal\Core\Url; use Drupal\media\MediaInterface; /** * Create system specific embed codes. */ 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', ], ]; return $asset_type ? $mapping[$asset_type] : $mapping; } /** * Returns a render array based on the parameters. * * @param string $format * Embed code id for formatting. * @param \Drupal\media\MediaInterface $media * Media instance. * * @return array * Render array. */ public static function renderAsset(string $format, MediaInterface $media): array { /** @var \Drupal\acquia_dam\Plugin\media\Source\Asset $source */ $source = $media->getSource(); $asset_field = $media->get(MediaSourceField::SOURCE_FIELD_NAME)->first(); $external_id = $asset_field->external_id; // If we don't have the external_id saved locally, fetch it from the API. if (!$external_id) { $external_id = $source->getMetadata($media, 'external_id'); } switch ($source->getDerivativeId()) { case 'documents': case 'pdf': $embed = self::renderDocumentsPdfAsset(self::getCdnDomain(), $external_id, $format, $media->getName(), self::encodeFilename($media->getName())); break; case 'video': $embed = self::renderVideoAsset(self::getCdnDomain(), $external_id, $format, $media->getName(), self::encodeFilename($media->getName())); break; case 'spinset': $embed = self::renderSpinsetAsset(self::getCdnDomain(), $external_id, $format, $media->getName(), self::encodeFilename($media->getName())); break; case 'image': assert($asset_field instanceof AssetItem); $image_properties = $source->getMetadata($media, 'image_properties'); $alt_text = $media->get(ImageAltTextField::IMAGE_ALT_TEXT_FIELD_NAME)->value ?? $media->label(); if ($format == 'original') { $embed = [ '#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 = [ '#theme' => 'image_style', '#uri' => "acquia-dam://$asset_field->asset_id/$asset_field->version_id.png", // @todo fetch alt from metadata for a proper value. '#alt' => $alt_text, '#width' => $image_properties['width'], '#style_name' => $format, '#height' => $image_properties['height'], ]; } break; default: $embed = []; } return $embed; } /** * 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']; } /** * Get Acquia CDN domain. */ private static function getCdnDomain() { static $domain; if ($domain === NULL) { $acquia_dam_domain = \Drupal::configFactory()->get('acquia_dam.settings')->get('domain'); $subdomain = explode('.', $acquia_dam_domain)[0]; $domain = "https://{$subdomain}.widen.net"; } return $domain; } /** * 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; } }