Issue #1174892 by chr.fritsch, travist, Dave Reid, keithm, webchick, phenaproxima, Everett Zufelt, slashrsm, Wim Leers, RobW, seanB, xjm, Gábor Hojtsy, larowlan, ericduran, webflo, Berdir, pschuelke: File field formatters for rich media display with <video> and <audio> HTML5 elements
							parent
							
								
									f7c9dd9352
								
							
						
					
					
						commit
						8f300f534f
					
				| 
						 | 
					@ -70,6 +70,41 @@ field.field_settings.file:
 | 
				
			||||||
      type: boolean
 | 
					      type: boolean
 | 
				
			||||||
      label: 'Enable Description field'
 | 
					      label: 'Enable Description field'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					file.formatter.media:
 | 
				
			||||||
 | 
					  type: mapping
 | 
				
			||||||
 | 
					  label: 'Media display format settings'
 | 
				
			||||||
 | 
					  mapping:
 | 
				
			||||||
 | 
					    controls:
 | 
				
			||||||
 | 
					      type: boolean
 | 
				
			||||||
 | 
					      label: 'Show playback controls'
 | 
				
			||||||
 | 
					    autoplay:
 | 
				
			||||||
 | 
					      type: boolean
 | 
				
			||||||
 | 
					      label: 'Autoplay'
 | 
				
			||||||
 | 
					    loop:
 | 
				
			||||||
 | 
					      type: boolean
 | 
				
			||||||
 | 
					      label: 'Loop'
 | 
				
			||||||
 | 
					    multiple_file_display_type:
 | 
				
			||||||
 | 
					      type: string
 | 
				
			||||||
 | 
					      label: 'Display of multiple files'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					field.formatter.settings.file_audio:
 | 
				
			||||||
 | 
					  type: file.formatter.media
 | 
				
			||||||
 | 
					  label: 'Audio file display format settings'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					field.formatter.settings.file_video:
 | 
				
			||||||
 | 
					  type: file.formatter.media
 | 
				
			||||||
 | 
					  label: 'Video file display format settings'
 | 
				
			||||||
 | 
					  mapping:
 | 
				
			||||||
 | 
					    muted:
 | 
				
			||||||
 | 
					      type: boolean
 | 
				
			||||||
 | 
					      label: 'Muted'
 | 
				
			||||||
 | 
					    width:
 | 
				
			||||||
 | 
					      type: integer
 | 
				
			||||||
 | 
					      label: 'Width'
 | 
				
			||||||
 | 
					    height:
 | 
				
			||||||
 | 
					      type: integer
 | 
				
			||||||
 | 
					      label: 'Height'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
field.formatter.settings.file_default:
 | 
					field.formatter.settings.file_default:
 | 
				
			||||||
  type: mapping
 | 
					  type: mapping
 | 
				
			||||||
  label: 'Generic file format settings'
 | 
					  label: 'Generic file format settings'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -571,6 +571,12 @@ function file_theme() {
 | 
				
			||||||
    'file_managed_file' => [
 | 
					    'file_managed_file' => [
 | 
				
			||||||
      'render element' => 'element',
 | 
					      'render element' => 'element',
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 | 
					    'file_audio' => [
 | 
				
			||||||
 | 
					      'variables' => ['files' => [], 'attributes' => NULL],
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    'file_video' => [
 | 
				
			||||||
 | 
					      'variables' => ['files' => [], 'attributes' => NULL],
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // From file.field.inc.
 | 
					    // From file.field.inc.
 | 
				
			||||||
    'file_widget_multiple' => [
 | 
					    'file_widget_multiple' => [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\file\Plugin\Field\FieldFormatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Plugin implementation of the 'file_audio' formatter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @FieldFormatter(
 | 
				
			||||||
 | 
					 *   id = "file_audio",
 | 
				
			||||||
 | 
					 *   label = @Translation("Audio"),
 | 
				
			||||||
 | 
					 *   description = @Translation("Display the file using an HTML5 audio tag."),
 | 
				
			||||||
 | 
					 *   field_types = {
 | 
				
			||||||
 | 
					 *     "file"
 | 
				
			||||||
 | 
					 *   }
 | 
				
			||||||
 | 
					 * )
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class FileAudioFormatter extends FileMediaFormatterBase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public static function getMediaType() {
 | 
				
			||||||
 | 
					    return 'audio';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,220 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\file\Plugin\Field\FieldFormatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Drupal\Core\Cache\Cache;
 | 
				
			||||||
 | 
					use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
 | 
				
			||||||
 | 
					use Drupal\Core\Field\FieldDefinitionInterface;
 | 
				
			||||||
 | 
					use Drupal\Core\Field\FieldItemListInterface;
 | 
				
			||||||
 | 
					use Drupal\Core\Form\FormStateInterface;
 | 
				
			||||||
 | 
					use Drupal\Core\Template\Attribute;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Base class for media file formatter.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					abstract class FileMediaFormatterBase extends FileFormatterBase implements FileMediaFormatterInterface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Gets the HTML tag for the formatter.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return string
 | 
				
			||||||
 | 
					   *   The HTML tag of this formatter.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function getHtmlTag() {
 | 
				
			||||||
 | 
					    return static::getMediaType();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public static function defaultSettings() {
 | 
				
			||||||
 | 
					    return [
 | 
				
			||||||
 | 
					      'controls' => TRUE,
 | 
				
			||||||
 | 
					      'autoplay' => FALSE,
 | 
				
			||||||
 | 
					      'loop' => FALSE,
 | 
				
			||||||
 | 
					      'multiple_file_display_type' => 'tags',
 | 
				
			||||||
 | 
					    ] + parent::defaultSettings();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function settingsForm(array $form, FormStateInterface $form_state) {
 | 
				
			||||||
 | 
					    return [
 | 
				
			||||||
 | 
					      'controls' => [
 | 
				
			||||||
 | 
					        '#title' => $this->t('Show playback controls'),
 | 
				
			||||||
 | 
					        '#type' => 'checkbox',
 | 
				
			||||||
 | 
					        '#default_value' => $this->getSetting('controls'),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      'autoplay' => [
 | 
				
			||||||
 | 
					        '#title' => $this->t('Autoplay'),
 | 
				
			||||||
 | 
					        '#type' => 'checkbox',
 | 
				
			||||||
 | 
					        '#default_value' => $this->getSetting('autoplay'),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      'loop' => [
 | 
				
			||||||
 | 
					        '#title' => $this->t('Loop'),
 | 
				
			||||||
 | 
					        '#type' => 'checkbox',
 | 
				
			||||||
 | 
					        '#default_value' => $this->getSetting('loop'),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      'multiple_file_display_type' => [
 | 
				
			||||||
 | 
					        '#title' => $this->t('Display of multiple files'),
 | 
				
			||||||
 | 
					        '#type' => 'radios',
 | 
				
			||||||
 | 
					        '#options' => [
 | 
				
			||||||
 | 
					          'tags' => $this->t('Use multiple @tag tags, each with a single source.', ['@tag' => '<' . $this->getHtmlTag() . '>']),
 | 
				
			||||||
 | 
					          'sources' => $this->t('Use multiple sources within a single @tag tag.', ['@tag' => '<' . $this->getHtmlTag() . '>']),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        '#default_value' => $this->getSetting('multiple_file_display_type'),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public static function isApplicable(FieldDefinitionInterface $field_definition) {
 | 
				
			||||||
 | 
					    if (!parent::isApplicable($field_definition)) {
 | 
				
			||||||
 | 
					      return FALSE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    /** @var \Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface $extension_mime_type_guesser */
 | 
				
			||||||
 | 
					    $extension_mime_type_guesser = \Drupal::service('file.mime_type.guesser.extension');
 | 
				
			||||||
 | 
					    $extension_list = array_filter(preg_split('/\s+/', $field_definition->getSetting('file_extensions')));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach ($extension_list as $extension) {
 | 
				
			||||||
 | 
					      $mime_type = $extension_mime_type_guesser->guess('fakedFile.' . $extension);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (static::mimeTypeApplies($mime_type)) {
 | 
				
			||||||
 | 
					        return TRUE;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return FALSE;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function settingsSummary() {
 | 
				
			||||||
 | 
					    $summary = [];
 | 
				
			||||||
 | 
					    $summary[] = $this->t('Playback controls: %controls', ['%controls' => $this->getSetting('controls') ? $this->t('visible') : $this->t('hidden')]);
 | 
				
			||||||
 | 
					    $summary[] = $this->t('Autoplay: %autoplay', ['%autoplay' => $this->getSetting('autoplay') ? $this->t('yes') : $this->t('no')]);
 | 
				
			||||||
 | 
					    $summary[] = $this->t('Loop: %loop', ['%loop' => $this->getSetting('loop') ? $this->t('yes') : $this->t('no')]);
 | 
				
			||||||
 | 
					    switch ($this->getSetting('multiple_file_display_type')) {
 | 
				
			||||||
 | 
					      case 'tags':
 | 
				
			||||||
 | 
					        $summary[] = $this->t('Multiple file display: Multiple HTML tags');
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case 'sources':
 | 
				
			||||||
 | 
					        $summary[] = $this->t('Multiple file display: One HTML tag with multiple sources');
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $summary;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function viewElements(FieldItemListInterface $items, $langcode) {
 | 
				
			||||||
 | 
					    $elements = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $source_files = $this->getSourceFiles($items, $langcode);
 | 
				
			||||||
 | 
					    if (empty($source_files)) {
 | 
				
			||||||
 | 
					      return $elements;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $attributes = $this->prepareAttributes();
 | 
				
			||||||
 | 
					    foreach ($source_files as $delta => $files) {
 | 
				
			||||||
 | 
					      $elements[$delta] = [
 | 
				
			||||||
 | 
					        '#theme' => $this->getPluginId(),
 | 
				
			||||||
 | 
					        '#attributes' => $attributes,
 | 
				
			||||||
 | 
					        '#files' => $files,
 | 
				
			||||||
 | 
					        '#cache' => ['tags' => []],
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $cache_tags = [];
 | 
				
			||||||
 | 
					      foreach ($files as $file) {
 | 
				
			||||||
 | 
					        $cache_tags = Cache::mergeTags($cache_tags, $file['file']->getCacheTags());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      $elements[$delta]['#cache']['tags'] = $cache_tags;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $elements;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Prepare the attributes according to the settings.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param string[] $additional_attributes
 | 
				
			||||||
 | 
					   *   Additional attributes to be applied to the HTML element. Attribute names
 | 
				
			||||||
 | 
					   *   will be used as key and value in the HTML element.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return \Drupal\Core\Template\Attribute
 | 
				
			||||||
 | 
					   *   Container with all the attributes for the HTML tag.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function prepareAttributes(array $additional_attributes = []) {
 | 
				
			||||||
 | 
					    $attributes = new Attribute();
 | 
				
			||||||
 | 
					    foreach (['controls', 'autoplay', 'loop'] + $additional_attributes as $attribute) {
 | 
				
			||||||
 | 
					      if ($this->getSetting($attribute)) {
 | 
				
			||||||
 | 
					        $attributes->setAttribute($attribute, $attribute);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $attributes;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Check if given MIME type applies to the media type of the formatter.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param string $mime_type
 | 
				
			||||||
 | 
					   *   The complete MIME type.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return bool
 | 
				
			||||||
 | 
					   *   TRUE if the MIME type applies, FALSE otherwise.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected static function mimeTypeApplies($mime_type) {
 | 
				
			||||||
 | 
					    list($type) = explode('/', $mime_type, 2);
 | 
				
			||||||
 | 
					    return $type === static::getMediaType();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Gets source files with attributes.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items
 | 
				
			||||||
 | 
					   *   The item list.
 | 
				
			||||||
 | 
					   * @param string $langcode
 | 
				
			||||||
 | 
					   *   The language code of the referenced entities to display.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return array
 | 
				
			||||||
 | 
					   *   Numerically indexed array, which again contains an associative array with
 | 
				
			||||||
 | 
					   *   the following key/values:
 | 
				
			||||||
 | 
					   *     - file => \Drupal\file\Entity\File
 | 
				
			||||||
 | 
					   *     - source_attributes => \Drupal\Core\Template\Attribute
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function getSourceFiles(EntityReferenceFieldItemListInterface $items, $langcode) {
 | 
				
			||||||
 | 
					    $source_files = [];
 | 
				
			||||||
 | 
					    // Because we can have the files grouped in a single media tag, we do a
 | 
				
			||||||
 | 
					    // grouping in case the multiple file behavior is not 'tags'.
 | 
				
			||||||
 | 
					    /** @var \Drupal\file\Entity\File $file */
 | 
				
			||||||
 | 
					    foreach ($this->getEntitiesToView($items, $langcode) as $file) {
 | 
				
			||||||
 | 
					      if (static::mimeTypeApplies($file->getMimeType())) {
 | 
				
			||||||
 | 
					        $source_attributes = new Attribute();
 | 
				
			||||||
 | 
					        $source_attributes
 | 
				
			||||||
 | 
					          ->setAttribute('src', file_url_transform_relative(file_create_url($file->getFileUri())))
 | 
				
			||||||
 | 
					          ->setAttribute('type', $file->getMimeType());
 | 
				
			||||||
 | 
					        if ($this->getSetting('multiple_file_display_type') === 'tags') {
 | 
				
			||||||
 | 
					          $source_files[] = [
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					              'file' => $file,
 | 
				
			||||||
 | 
					              'source_attributes' => $source_attributes,
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					          $source_files[0][] = [
 | 
				
			||||||
 | 
					            'file' => $file,
 | 
				
			||||||
 | 
					            'source_attributes' => $source_attributes,
 | 
				
			||||||
 | 
					          ];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $source_files;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\file\Plugin\Field\FieldFormatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Defines getter methods for FileMediaFormatterBase.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This interface is used on the FileMediaFormatterBase class to ensure that
 | 
				
			||||||
 | 
					 * each file media formatter will be based on a media type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Abstract classes are not able to implement abstract static methods,
 | 
				
			||||||
 | 
					 * this interface will work around that.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @see \Drupal\file\Plugin\Field\FieldFormatter\FileMediaFormatterBase
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					interface FileMediaFormatterInterface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Gets the applicable media type for a formatter.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return string
 | 
				
			||||||
 | 
					   *   The media type of this formatter.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public static function getMediaType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,94 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\file\Plugin\Field\FieldFormatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Drupal\Core\Form\FormStateInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Plugin implementation of the 'file_video' formatter.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @FieldFormatter(
 | 
				
			||||||
 | 
					 *   id = "file_video",
 | 
				
			||||||
 | 
					 *   label = @Translation("Video"),
 | 
				
			||||||
 | 
					 *   description = @Translation("Display the file using an HTML5 video tag."),
 | 
				
			||||||
 | 
					 *   field_types = {
 | 
				
			||||||
 | 
					 *     "file"
 | 
				
			||||||
 | 
					 *   }
 | 
				
			||||||
 | 
					 * )
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class FileVideoFormatter extends FileMediaFormatterBase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public static function getMediaType() {
 | 
				
			||||||
 | 
					    return 'video';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public static function defaultSettings() {
 | 
				
			||||||
 | 
					    return [
 | 
				
			||||||
 | 
					      'muted' => FALSE,
 | 
				
			||||||
 | 
					      'width' => 640,
 | 
				
			||||||
 | 
					      'height' => 480,
 | 
				
			||||||
 | 
					    ] + parent::defaultSettings();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function settingsForm(array $form, FormStateInterface $form_state) {
 | 
				
			||||||
 | 
					    return parent::settingsForm($form, $form_state) + [
 | 
				
			||||||
 | 
					      'muted' => [
 | 
				
			||||||
 | 
					        '#title' => $this->t('Muted'),
 | 
				
			||||||
 | 
					        '#type' => 'checkbox',
 | 
				
			||||||
 | 
					        '#default_value' => $this->getSetting('muted'),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      'width' => [
 | 
				
			||||||
 | 
					        '#type' => 'number',
 | 
				
			||||||
 | 
					        '#title' => $this->t('Width'),
 | 
				
			||||||
 | 
					        '#default_value' => $this->getSetting('width'),
 | 
				
			||||||
 | 
					        '#size' => 5,
 | 
				
			||||||
 | 
					        '#maxlength' => 5,
 | 
				
			||||||
 | 
					        '#field_suffix' => $this->t('pixels'),
 | 
				
			||||||
 | 
					        '#min' => 0,
 | 
				
			||||||
 | 
					        '#required' => TRUE,
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      'height' => [
 | 
				
			||||||
 | 
					        '#type' => 'number',
 | 
				
			||||||
 | 
					        '#title' => $this->t('Height'),
 | 
				
			||||||
 | 
					        '#default_value' => $this->getSetting('height'),
 | 
				
			||||||
 | 
					        '#size' => 5,
 | 
				
			||||||
 | 
					        '#maxlength' => 5,
 | 
				
			||||||
 | 
					        '#field_suffix' => $this->t('pixels'),
 | 
				
			||||||
 | 
					        '#min' => 0,
 | 
				
			||||||
 | 
					        '#required' => TRUE,
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function settingsSummary() {
 | 
				
			||||||
 | 
					    $summary = parent::settingsSummary();
 | 
				
			||||||
 | 
					    $summary[] = $this->t('Muted: %muted', ['%muted' => $this->getSetting('muted') ? $this->t('yes') : $this->t('no')]);
 | 
				
			||||||
 | 
					    $summary[] = $this->t('Size: %width x %height pixels', [
 | 
				
			||||||
 | 
					      '%width' => $this->getSetting('width'),
 | 
				
			||||||
 | 
					      '%height' => $this->getSetting('height'),
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    return $summary;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function prepareAttributes(array $additional_attributes = []) {
 | 
				
			||||||
 | 
					    return parent::prepareAttributes(['muted'])
 | 
				
			||||||
 | 
					      ->setAttribute('width', $this->getSetting('width'))
 | 
				
			||||||
 | 
					      ->setAttribute('height', $this->getSetting('height'));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					{#
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* @file
 | 
				
			||||||
 | 
					* Default theme implementation to display the file entity as an audio tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Available variables:
 | 
				
			||||||
 | 
					* - attributes: An array of HTML attributes, intended to be added to the
 | 
				
			||||||
 | 
					*   audio tag.
 | 
				
			||||||
 | 
					* - files: And array of files to be added as sources for the audio tag. Each
 | 
				
			||||||
 | 
					*   element is an array with the following elements:
 | 
				
			||||||
 | 
					*   - file: The full file object.
 | 
				
			||||||
 | 
					*   - source_attributes: An array of HTML attributes for to be added to the
 | 
				
			||||||
 | 
					*     source tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* @ingroup themeable
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#}
 | 
				
			||||||
 | 
					<audio {{ attributes }}>
 | 
				
			||||||
 | 
					  {% for file in files %}
 | 
				
			||||||
 | 
					    <source {{ file.source_attributes }} />
 | 
				
			||||||
 | 
					  {% endfor %}
 | 
				
			||||||
 | 
					</audio>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					{#
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* @file
 | 
				
			||||||
 | 
					* Default theme implementation to display the file entity as a video tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Available variables:
 | 
				
			||||||
 | 
					* - attributes: An array of HTML attributes, intended to be added to the
 | 
				
			||||||
 | 
					*   video tag.
 | 
				
			||||||
 | 
					* - files: And array of files to be added as sources for the video tag. Each
 | 
				
			||||||
 | 
					*   element is an array with the following elements:
 | 
				
			||||||
 | 
					*   - file: The full file object.
 | 
				
			||||||
 | 
					*   - source_attributes: An array of HTML attributes for to be added to the
 | 
				
			||||||
 | 
					*     source tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* @ingroup themeable
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#}
 | 
				
			||||||
 | 
					<video {{ attributes }}>
 | 
				
			||||||
 | 
					  {% for file in files %}
 | 
				
			||||||
 | 
					    <source {{ file.source_attributes }} />
 | 
				
			||||||
 | 
					  {% endfor %}
 | 
				
			||||||
 | 
					</video>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,58 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\Tests\file\Functional\Formatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Drupal\entity_test\Entity\EntityTest;
 | 
				
			||||||
 | 
					use Drupal\file\Entity\File;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @coversDefaultClass \Drupal\file\Plugin\Field\FieldFormatter\FileAudioFormatter
 | 
				
			||||||
 | 
					 * @group file
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class FileAudioFormatterTest extends FileMediaFormatterTestBase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @covers ::viewElements
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @dataProvider dataProvider
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function testRender($tag_count, $formatter_settings) {
 | 
				
			||||||
 | 
					    $field_config = $this->createMediaField('file_audio', 'mp3', $formatter_settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    file_put_contents('public://file.mp3', str_repeat('t', 10));
 | 
				
			||||||
 | 
					    $file1 = File::create([
 | 
				
			||||||
 | 
					      'uri' => 'public://file.mp3',
 | 
				
			||||||
 | 
					      'filename' => 'file.mp3',
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $file1->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $file2 = File::create([
 | 
				
			||||||
 | 
					      'uri' => 'public://file.mp3',
 | 
				
			||||||
 | 
					      'filename' => 'file.mp3',
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $file2->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $entity = EntityTest::create([
 | 
				
			||||||
 | 
					      $field_config->getName() => [
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          'target_id' => $file1->id(),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          'target_id' => $file2->id(),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $entity->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->drupalGet($entity->toUrl());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $file1_url = file_url_transform_relative(file_create_url($file1->getFileUri()));
 | 
				
			||||||
 | 
					    $file2_url = file_url_transform_relative(file_create_url($file2->getFileUri()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $assert_session = $this->assertSession();
 | 
				
			||||||
 | 
					    $assert_session->elementsCount('css', 'audio[controls="controls"]', $tag_count);
 | 
				
			||||||
 | 
					    $assert_session->elementExists('css', "audio > source[src='$file1_url'][type='audio/mpeg']");
 | 
				
			||||||
 | 
					    $assert_session->elementExists('css', "audio > source[src='$file2_url'][type='audio/mpeg']");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,93 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\Tests\file\Functional\Formatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Drupal\Component\Utility\Unicode;
 | 
				
			||||||
 | 
					use Drupal\Core\Field\FieldStorageDefinitionInterface;
 | 
				
			||||||
 | 
					use Drupal\field\Entity\FieldConfig;
 | 
				
			||||||
 | 
					use Drupal\field\Entity\FieldStorageConfig;
 | 
				
			||||||
 | 
					use Drupal\Tests\BrowserTestBase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Provides methods specifically for testing File module's media formatter's.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					abstract class FileMediaFormatterTestBase extends BrowserTestBase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected static $modules = [
 | 
				
			||||||
 | 
					    'entity_test',
 | 
				
			||||||
 | 
					    'field',
 | 
				
			||||||
 | 
					    'file',
 | 
				
			||||||
 | 
					    'user',
 | 
				
			||||||
 | 
					    'system',
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * {@inheritdoc}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function setUp() {
 | 
				
			||||||
 | 
					    parent::setUp();
 | 
				
			||||||
 | 
					    $this->drupalLogin($this->drupalCreateUser(['view test entity']));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Creates a file field and set's the correct formatter.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param string $formatter
 | 
				
			||||||
 | 
					   *   The formatter ID.
 | 
				
			||||||
 | 
					   * @param string $file_extensions
 | 
				
			||||||
 | 
					   *   The file extensions of the new field.
 | 
				
			||||||
 | 
					   * @param array $formatter_settings
 | 
				
			||||||
 | 
					   *   Settings for the formatter.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return \Drupal\field\Entity\FieldConfig
 | 
				
			||||||
 | 
					   *   Newly created file field.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  protected function createMediaField($formatter, $file_extensions, array $formatter_settings = []) {
 | 
				
			||||||
 | 
					    $entity_type = $bundle = 'entity_test';
 | 
				
			||||||
 | 
					    $field_name = Unicode::strtolower($this->randomMachineName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FieldStorageConfig::create([
 | 
				
			||||||
 | 
					      'entity_type' => $entity_type,
 | 
				
			||||||
 | 
					      'field_name' => $field_name,
 | 
				
			||||||
 | 
					      'type' => 'file',
 | 
				
			||||||
 | 
					      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
 | 
				
			||||||
 | 
					    ])->save();
 | 
				
			||||||
 | 
					    $field_config = FieldConfig::create([
 | 
				
			||||||
 | 
					      'entity_type' => $entity_type,
 | 
				
			||||||
 | 
					      'field_name' => $field_name,
 | 
				
			||||||
 | 
					      'bundle' => $bundle,
 | 
				
			||||||
 | 
					      'settings' => [
 | 
				
			||||||
 | 
					        'file_extensions' => trim($file_extensions),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $field_config->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $display = entity_get_display('entity_test', 'entity_test', 'full');
 | 
				
			||||||
 | 
					    $display->setComponent($field_name, [
 | 
				
			||||||
 | 
					      'type' => $formatter,
 | 
				
			||||||
 | 
					      'settings' => $formatter_settings,
 | 
				
			||||||
 | 
					    ])->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $field_config;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Data provider for testRender.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return array
 | 
				
			||||||
 | 
					   *   An array of data arrays.
 | 
				
			||||||
 | 
					   *   The data array contains:
 | 
				
			||||||
 | 
					   *     - The number of expected HTML tags.
 | 
				
			||||||
 | 
					   *     - An array of settings for the field formatter.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function dataProvider() {
 | 
				
			||||||
 | 
					    return [
 | 
				
			||||||
 | 
					      [2, []],
 | 
				
			||||||
 | 
					      [1, ['multiple_file_display_type' => 'sources']],
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,58 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Drupal\Tests\file\Functional\Formatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Drupal\entity_test\Entity\EntityTest;
 | 
				
			||||||
 | 
					use Drupal\file\Entity\File;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @coversDefaultClass \Drupal\file\Plugin\Field\FieldFormatter\FileVideoFormatter
 | 
				
			||||||
 | 
					 * @group file
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class FileVideoFormatterTest extends FileMediaFormatterTestBase {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @covers ::viewElements
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @dataProvider dataProvider
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  public function testRender($tag_count, $formatter_settings) {
 | 
				
			||||||
 | 
					    $field_config = $this->createMediaField('file_video', 'mp4', $formatter_settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    file_put_contents('public://file.mp4', str_repeat('t', 10));
 | 
				
			||||||
 | 
					    $file1 = File::create([
 | 
				
			||||||
 | 
					      'uri' => 'public://file.mp4',
 | 
				
			||||||
 | 
					      'filename' => 'file.mp4',
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $file1->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $file2 = File::create([
 | 
				
			||||||
 | 
					      'uri' => 'public://file.mp4',
 | 
				
			||||||
 | 
					      'filename' => 'file.mp4',
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $file2->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $entity = EntityTest::create([
 | 
				
			||||||
 | 
					      $field_config->getName() => [
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          'target_id' => $file1->id(),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        [
 | 
				
			||||||
 | 
					          'target_id' => $file2->id(),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $entity->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $this->drupalGet($entity->toUrl());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $file1_url = file_url_transform_relative(file_create_url($file1->getFileUri()));
 | 
				
			||||||
 | 
					    $file2_url = file_url_transform_relative(file_create_url($file2->getFileUri()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $assert_session = $this->assertSession();
 | 
				
			||||||
 | 
					    $assert_session->elementsCount('css', 'video[controls="controls"]', $tag_count);
 | 
				
			||||||
 | 
					    $assert_session->elementExists('css', "video > source[src='$file1_url'][type='video/mp4']");
 | 
				
			||||||
 | 
					    $assert_session->elementExists('css', "video > source[src='$file2_url'][type='video/mp4']");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					{#
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* @file
 | 
				
			||||||
 | 
					* Default theme implementation to display the file entity as an audio tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Available variables:
 | 
				
			||||||
 | 
					* - attributes: An array of HTML attributes, intended to be added to the
 | 
				
			||||||
 | 
					*   audio tag.
 | 
				
			||||||
 | 
					* - files: And array of files to be added as sources for the audio tag. Each
 | 
				
			||||||
 | 
					*   element is an array with the following elements:
 | 
				
			||||||
 | 
					*   - file: The full file object.
 | 
				
			||||||
 | 
					*   - source_attributes: An array of HTML attributes for to be added to the
 | 
				
			||||||
 | 
					*     source tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* @ingroup themeable
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#}
 | 
				
			||||||
 | 
					{{ attach_library('classy/file') }}
 | 
				
			||||||
 | 
					<audio {{ attributes }}>
 | 
				
			||||||
 | 
					  {% for file in files %}
 | 
				
			||||||
 | 
					    <source {{ file.source_attributes }} />
 | 
				
			||||||
 | 
					  {% endfor %}
 | 
				
			||||||
 | 
					</audio>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					{#
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* @file
 | 
				
			||||||
 | 
					* Default theme implementation to display the file entity as a video tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Available variables:
 | 
				
			||||||
 | 
					* - attributes: An array of HTML attributes, intended to be added to the
 | 
				
			||||||
 | 
					*   video tag.
 | 
				
			||||||
 | 
					* - files: And array of files to be added as sources for the video tag. Each
 | 
				
			||||||
 | 
					*   element is an array with the following elements:
 | 
				
			||||||
 | 
					*   - file: The full file object.
 | 
				
			||||||
 | 
					*   - source_attributes: An array of HTML attributes for to be added to the
 | 
				
			||||||
 | 
					*     source tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* @ingroup themeable
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#}
 | 
				
			||||||
 | 
					{{ attach_library('classy/file') }}
 | 
				
			||||||
 | 
					<video {{ attributes }}>
 | 
				
			||||||
 | 
					  {% for file in files %}
 | 
				
			||||||
 | 
					    <source {{ file.source_attributes }} />
 | 
				
			||||||
 | 
					  {% endfor %}
 | 
				
			||||||
 | 
					</video>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					{#
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* @file
 | 
				
			||||||
 | 
					* Default theme implementation to display the file entity as an audio tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Available variables:
 | 
				
			||||||
 | 
					* - attributes: An array of HTML attributes, intended to be added to the
 | 
				
			||||||
 | 
					*   audio tag.
 | 
				
			||||||
 | 
					* - files: And array of files to be added as sources for the audio tag. Each
 | 
				
			||||||
 | 
					*   element is an array with the following elements:
 | 
				
			||||||
 | 
					*   - file: The full file object.
 | 
				
			||||||
 | 
					*   - source_attributes: An array of HTML attributes for to be added to the
 | 
				
			||||||
 | 
					*     source tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* @ingroup themeable
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#}
 | 
				
			||||||
 | 
					<audio {{ attributes }}>
 | 
				
			||||||
 | 
					  {% for file in files %}
 | 
				
			||||||
 | 
					    <source {{ file.source_attributes }} />
 | 
				
			||||||
 | 
					  {% endfor %}
 | 
				
			||||||
 | 
					</audio>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					{#
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* @file
 | 
				
			||||||
 | 
					* Default theme implementation to display the file entity as a video tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* Available variables:
 | 
				
			||||||
 | 
					* - attributes: An array of HTML attributes, intended to be added to the
 | 
				
			||||||
 | 
					*   video tag.
 | 
				
			||||||
 | 
					* - files: And array of files to be added as sources for the video tag. Each
 | 
				
			||||||
 | 
					*   element is an array with the following elements:
 | 
				
			||||||
 | 
					*   - file: The full file object.
 | 
				
			||||||
 | 
					*   - source_attributes: An array of HTML attributes for to be added to the
 | 
				
			||||||
 | 
					*     source tag.
 | 
				
			||||||
 | 
					*
 | 
				
			||||||
 | 
					* @ingroup themeable
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#}
 | 
				
			||||||
 | 
					<video {{ attributes }}>
 | 
				
			||||||
 | 
					  {% for file in files %}
 | 
				
			||||||
 | 
					    <source {{ file.source_attributes }} />
 | 
				
			||||||
 | 
					  {% endfor %}
 | 
				
			||||||
 | 
					</video>
 | 
				
			||||||
		Loading…
	
		Reference in New Issue