Skip to content
Snippets Groups Projects
Commit 384b872c authored by Joshua Sedler's avatar Joshua Sedler :cartwheel_tone2:
Browse files

Merge branch '3521463-poster-image-settings' into '1.x'

Issue #3521463: Poster image settings missing from remote video formatter

See merge request !5
parents 517cd36a a6e7da77
No related branches found
No related tags found
No related merge requests found
Pipeline #484863 passed with warnings
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
namespace Drupal\vidstack_player\Plugin\Field\FieldFormatter; namespace Drupal\vidstack_player\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\file\Entity\File;
use Drupal\image\Entity\ImageStyle;
/** /**
* Shared trait for Vidstack Player video formatters. * Shared trait for Vidstack Player video formatters.
...@@ -38,6 +42,47 @@ trait VidstackPlayerFormatterTrait { ...@@ -38,6 +42,47 @@ trait VidstackPlayerFormatterTrait {
'#description' => $this->t('The load strategy that will be used to determine when the video content should start loading.'), '#description' => $this->t('The load strategy that will be used to determine when the video content should start loading.'),
'#default_value' => $this->getSetting('load'), '#default_value' => $this->getSetting('load'),
]; ];
$form['poster'] = [
'#title' => $this->t('Poster image'),
'#type' => 'select',
'#options' => [
'none' => $this->t('None (Show first frame)'),
'custom' => $this->t('Custom URL'),
$this->t('Image fields from this entity:')->render() => $this->getEntityImageFields(),
],
'#description' => $this->t('The image that will be displayed as a poster/thumbnail.'),
'#default_value' => $this->getSetting('poster'),
];
$form['posterUrl'] = [
'#title' => $this->t('Custom poster image URL'),
'#type' => 'textfield',
'#description' => $this->t('The custom URL for the poster/thumbnail image.'),
'#default_value' => $this->getSetting('posterUrl'),
'#states' => [
'visible' => [
':input[name*="[settings][poster]"]' => ['value' => 'custom'],
],
],
];
$form['posterStyle'] = [
'#title' => $this->t('Poster image style'),
'#type' => 'select',
'#options' => image_style_options(FALSE),
'#empty_option' => $this->t('None (original image)'),
'#description' => $this->t('The image style to use for the poster image.'),
'#default_value' => $this->getSetting('posterStyle'),
];
$form['posterLoad'] = [
'#title' => $this->t('Poster load strategy'),
'#type' => 'select',
'#options' => [
'eager' => $this->t('Load immediately'),
'idle' => $this->t('Load after the page is loaded'),
'visible' => $this->t('Load after becoming visible'),
],
'#description' => $this->t('The load strategy that will be used to determine when the poster/thumbnail should start loading.'),
'#default_value' => $this->getSetting('posterLoad'),
];
return $form; return $form;
} }
...@@ -66,6 +111,10 @@ trait VidstackPlayerFormatterTrait { ...@@ -66,6 +111,10 @@ trait VidstackPlayerFormatterTrait {
return [ return [
'muted' => FALSE, 'muted' => FALSE,
'load' => 'visible', 'load' => 'visible',
'poster' => 'none',
'posterUrl' => '',
'posterLoad' => 'visible',
'posterStyle' => '',
]; ];
} }
...@@ -83,7 +132,106 @@ trait VidstackPlayerFormatterTrait { ...@@ -83,7 +132,106 @@ trait VidstackPlayerFormatterTrait {
$summary['load'] = $this->t('Load strategy: %load', [ $summary['load'] = $this->t('Load strategy: %load', [
'%load' => $this->getLoadStrategyOptions()[$this->getSetting('load')], '%load' => $this->getLoadStrategyOptions()[$this->getSetting('load')],
]); ]);
$posterValue = match($this->getSetting('poster')) {
'none' => $this->t('None (Show first frame)'),
'custom' => $this->t('Custom URL'),
default => $this->t('Field "%name" (%style)', [
'%name' => $this->getSetting('poster'),
'%style' => $this->getSetting('posterStyle') === '' ? $this->t('None (original image)') : image_style_options(TRUE)[$this->getSetting('posterStyle')],
]),
};
$summary['poster'] = $this->t('Poster image: %poster', [
'%poster' => $posterValue,
]);
$summary['poster_load'] = $this->t('Poster load strategy: %load', [
'%load' => $this->getLoadStrategyOptions()[$this->getSetting('posterLoad')],
]);
return $summary; return $summary;
} }
/**
* Get the poster url.
*/
protected function getPosterUrl(FieldItemListInterface $items) {
$settings = $this->getSettings();
$posterUrl = '';
switch ($settings['poster']) {
case 'none':
break;
case 'custom':
$posterUrl = $settings['posterUrl'];
break;
default:
// Check if the poster is set to an image field on the entity, if not
// break:
if (!in_array($settings['poster'], array_keys($this->getEntityImageFields()), TRUE)) {
break;
}
// Check if the poster field is empty (no referenced file). If not
// break:
$referenecedPosterFileId = $items->getEntity()->get($settings['poster'])->target_id;
if ($referenecedPosterFileId === NULL) {
break;
}
// We have a proper file id now, load the file and generate the file
// uri based on the "posterStyle" setting:
$posterFile = File::load($referenecedPosterFileId);
if ($settings['posterStyle'] === '') {
$posterUrl = $posterFile->createFileUrl(FALSE);
}
else {
$posterFileUri = $posterFile->getFileUri();
$posterUrl = ImageStyle::load($settings['posterStyle'])->buildUrl($posterFileUri);
}
break;
}
return $posterUrl;
}
/**
* Returns a single element to be rendered by the viewElements function.
*
* @return array
* The render array for the view element.
*/
protected function getViewElement(string $theme, array $settings, FieldItemListInterface $items) {
$posterUrl = $this->getPosterUrl($items);
return [
'#theme' => $theme,
'#attributes' => [
'class' => ['vidstack-player'],
'data-autoplay' => (bool) $settings['autoplay'],
'data-loop' => (bool) $settings['loop'],
'data-muted' => (bool) $settings['muted'],
'data-controls' => (bool) $settings['controls'],
'data-load' => $settings['load'],
'data-poster' => $posterUrl,
'data-poster-load' => $settings['posterLoad'],
],
];
}
/**
* Helper function that gathers all image fields attached to the media entity.
*
* @return array
* The image fields of the media entity.
*/
public function getEntityImageFields(): array {
$imageFieldsArray = [];
$imageFields = array_filter($this->entityFieldManager->getFieldDefinitions($this->fieldDefinition->getTargetEntityTypeId(), $this->fieldDefinition->getTargetBundle()),
function (FieldDefinitionInterface $field) {
return $field->getType() === 'image';
});
foreach ($imageFields as $imageField) {
$imageFieldsArray[$imageField->getName()] = $imageField->getLabel() . ' (' . $imageField->getName() . ')';
}
return $imageFieldsArray;
}
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Drupal\vidstack_player\Plugin\Field\FieldFormatter; namespace Drupal\vidstack_player\Plugin\Field\FieldFormatter;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase; use Drupal\Core\Field\FormatterBase;
...@@ -34,6 +35,13 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { ...@@ -34,6 +35,13 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase {
*/ */
protected $urlResolver; protected $urlResolver;
/**
* The entity field manager service.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/** /**
* Constructs an VidstackPlayerRemoteVideoFormatter instance. * Constructs an VidstackPlayerRemoteVideoFormatter instance.
* *
...@@ -51,12 +59,15 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { ...@@ -51,12 +59,15 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase {
* The view mode. * The view mode.
* @param array $third_party_settings * @param array $third_party_settings
* Any third party settings. * Any third party settings.
* @param \Drupal\media\OEmbed\UrlResolverInterface $url_resolver * @param \Drupal\media\OEmbed\UrlResolverInterface $urlResolver
* The oEmbed url resolver service. * The oEmbed url resolver service.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager
* The entity field manager service.
*/ */
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, UrlResolverInterface $url_resolver) { public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, UrlResolverInterface $urlResolver, EntityFieldManagerInterface $entityFieldManager) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->urlResolver = $url_resolver; $this->urlResolver = $urlResolver;
$this->entityFieldManager = $entityFieldManager;
} }
/** /**
...@@ -71,7 +82,8 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { ...@@ -71,7 +82,8 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase {
$configuration['label'], $configuration['label'],
$configuration['view_mode'], $configuration['view_mode'],
$configuration['third_party_settings'], $configuration['third_party_settings'],
$container->get('media.oembed.url_resolver') $container->get('media.oembed.url_resolver'),
$container->get('entity_field.manager'),
); );
} }
...@@ -153,8 +165,10 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { ...@@ -153,8 +165,10 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function viewElements(FieldItemListInterface $items, $langcode) { public function viewElements(FieldItemListInterface $items, $langcode) {
$settings = $this->getSettings();
$elements = []; $elements = [];
$settings = $this->getSettings();
$viewElement = $this->getViewElement('vidstack_player_remote_video', $settings, $items);
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
// Get the main property value (an url) and check if it uses a valid // Get the main property value (an url) and check if it uses a valid
// provider: // provider:
...@@ -164,18 +178,8 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { ...@@ -164,18 +178,8 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase {
continue; continue;
} }
if ($this->usesValidProvider($value)) { if ($this->usesValidProvider($value)) {
$elements[$delta] = [ $elements[$delta] = $viewElement;
'#theme' => 'vidstack_player_remote_video', $elements[$delta]['#attributes']['src'] = $value;
'#attributes' => [
'class' => ['vidstack-player'],
'src' => $value,
'data-autoplay' => (bool) $settings['autoplay'],
'data-loop' => (bool) $settings['loop'],
'data-muted' => (bool) $settings['muted'],
'data-controls' => (bool) $settings['controls'],
'data-load' => $settings['load'],
],
];
} }
else { else {
$elements[$delta] = [ $elements[$delta] = [
......
...@@ -8,8 +8,6 @@ use Drupal\Core\Field\FieldItemListInterface; ...@@ -8,8 +8,6 @@ use Drupal\Core\Field\FieldItemListInterface;
use Drupal\file\Plugin\Field\FieldFormatter\FileMediaFormatterBase; use Drupal\file\Plugin\Field\FieldFormatter\FileMediaFormatterBase;
use Drupal\file\Plugin\Field\FieldFormatter\FileMediaFormatterInterface; use Drupal\file\Plugin\Field\FieldFormatter\FileMediaFormatterInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;
use Drupal\image\Entity\ImageStyle;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
...@@ -31,7 +29,7 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil ...@@ -31,7 +29,7 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil
* *
* @var \Drupal\Core\Entity\EntityFieldManagerInterface * @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/ */
private $entityFieldManager; protected $entityFieldManager;
/** /**
* Constructs an VidstackPlayerRemoteVideoFormatter instance. * Constructs an VidstackPlayerRemoteVideoFormatter instance.
...@@ -87,20 +85,7 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil ...@@ -87,20 +85,7 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil
public function settingsSummary() { public function settingsSummary() {
$summary = parent::settingsSummary(); $summary = parent::settingsSummary();
$summary += $this->getSharedSettingsSummary(); $summary += $this->getSharedSettingsSummary();
$posterValue = match($this->getSetting('poster')) {
'none' => $this->t('None (Show first frame)'),
'custom' => $this->t('Custom URL'),
default => $this->t('Field "%name" (%style)', [
'%name' => $this->getSetting('poster'),
'%style' => $this->getSetting('posterStyle') === '' ? $this->t('None (original image)') : image_style_options(TRUE)[$this->getSetting('posterStyle')],
]),
};
$summary['poster'] = $this->t('Poster image: %poster', [
'%poster' => $posterValue,
]);
$summary['poster_load'] = $this->t('Poster load strategy: %load', [
'%load' => $this->getLoadStrategyOptions()[$this->getSetting('posterLoad')],
]);
return $summary; return $summary;
} }
...@@ -110,10 +95,6 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil ...@@ -110,10 +95,6 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil
public static function defaultSettings() { public static function defaultSettings() {
$settings = parent::defaultSettings(); $settings = parent::defaultSettings();
$settings += self::getSharedDefaultSettings(); $settings += self::getSharedDefaultSettings();
$settings['poster'] = 'none';
$settings['posterUrl'] = '';
$settings['posterLoad'] = 'visible';
$settings['posterStyle'] = '';
return $settings; return $settings;
} }
...@@ -123,49 +104,6 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil ...@@ -123,49 +104,6 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil
public function settingsForm(array $form, FormStateInterface $form_state) { public function settingsForm(array $form, FormStateInterface $form_state) {
$form = parent::settingsForm($form, $form_state); $form = parent::settingsForm($form, $form_state);
$form += $this->getSharedSettings($form); $form += $this->getSharedSettings($form);
$form['poster'] = [
'#title' => $this->t('Poster image'),
'#type' => 'select',
'#options' => [
'none' => $this->t('None (Show first frame)'),
'custom' => $this->t('Custom URL'),
$this->t('Image fields from this entity:')->render() => $this->getEntityImageFields(),
],
'#description' => $this->t('The image that will be displayed as a poster/thumbnail.'),
'#default_value' => $this->getSetting('poster'),
];
$form['posterUrl'] = [
'#title' => $this->t('Custom poster image URL'),
'#type' => 'textfield',
'#description' => $this->t('The custom URL for the poster/thumbnail image.'),
'#default_value' => $this->getSetting('posterUrl'),
'#states' => [
'visible' => [
':input[name="fields[field_media_video_file][settings_edit_form][settings][poster]"]' => ['value' => 'custom'],
],
],
];
$form['posterStyle'] = [
'#title' => $this->t('Poster image style'),
'#type' => 'select',
'#options' => image_style_options(FALSE),
'#empty_option' => $this->t('None (original image)'),
'#description' => $this->t('The image style to use for the poster image.'),
'#default_value' => $this->getSetting('posterStyle'),
];
$form['posterLoad'] = [
'#title' => $this->t('Poster load strategy'),
'#type' => 'select',
'#options' => [
'eager' => $this->t('Load immediately'),
'idle' => $this->t('Load after the page is loaded'),
'visible' => $this->t('Load after becoming visible'),
],
'#description' => $this->t('The load strategy that will be used to determine when the poster/thumbnail should start loading.'),
'#default_value' => $this->getSetting('posterLoad'),
];
return $form; return $form;
} }
...@@ -175,75 +113,14 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil ...@@ -175,75 +113,14 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil
public function viewElements(FieldItemListInterface $items, $langcode) { public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = parent::viewElements($items, $langcode); $elements = parent::viewElements($items, $langcode);
$settings = $this->getSettings(); $settings = $this->getSettings();
$viewElement = $this->getViewElement('vidstack_player_video', $settings, $items);
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
$elements[$delta][] = [ // We want to keep the parent element, so we merge the arrays instead:
'#theme' => 'vidstack_player_video', $elements[$delta] = array_merge_recursive($elements[$delta], $viewElement);
];
$posterUrl = '';
switch ($settings['poster']) {
case 'none':
break;
case 'custom':
$posterUrl = $settings['posterUrl'];
break;
default:
// Check if the poster is set to an image field on the entity, if not
// break:
if (!in_array($settings['poster'], array_keys($this->getEntityImageFields()), TRUE)) {
break;
}
// Check if the poster field is empty (no referenced file). If not
// break:
$referenecedPosterFileId = $items->getEntity()->get($settings['poster'])->target_id;
if ($referenecedPosterFileId === NULL) {
break;
}
// We have a proper file id now, load the file and generate the file
// uri based on the "posterStyle" setting:
$posterFile = File::load($referenecedPosterFileId);
if ($settings['posterStyle'] === '') {
$posterUrl = $posterFile->createFileUrl(FALSE);
}
else {
$posterFileUri = $posterFile->getFileUri();
$posterUrl = ImageStyle::load($settings['posterStyle'])->buildUrl($posterFileUri);
}
break;
}
$elements[$delta]['#attributes']->addClass('vidstack-player')
->setAttribute('data-autoplay', (bool) $settings['autoplay'])
->setAttribute('data-loop', (bool) $settings['loop'])
->setAttribute('data-muted', (bool) $settings['muted'])
->setAttribute('data-controls', (bool) $settings['controls'])
->setAttribute('data-load', $settings['load'])
->setAttribute('data-poster', $posterUrl)
->setAttribute('data-poster-load', $settings['posterLoad']);
}
$elements['#attached']['library'][] = 'vidstack_player/init'; $elements['#attached']['library'][] = 'vidstack_player/init';
return $elements; return $elements;
} }
/**
* Helper function that gathers all image fields attached to the media entity.
*
* @return array
* The image fields of the media entity.
*/
public function getEntityImageFields(): array {
$imageFieldsArray = [];
$imageFields = array_filter($this->entityFieldManager->getFieldDefinitions($this->fieldDefinition->getTargetEntityTypeId(), $this->fieldDefinition->getTargetBundle()),
function (FieldDefinitionInterface $field) {
return $field->getType() === 'image';
});
foreach ($imageFields as $imageField) {
$imageFieldsArray[$imageField->getName()] = $imageField->getLabel() . ' (' . $imageField->getName() . ')';
}
return $imageFieldsArray;
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment