From 4ec045d1d59013daa256019743c3fd7a613236ad Mon Sep 17 00:00:00 2001 From: Joshua Sedler <55201-Grevil@users.noreply.drupalcode.org> Date: Fri, 25 Apr 2025 10:46:59 +0000 Subject: [PATCH] Issue #3521021: Add parent calls, adjust templates and fix formatter settings --- .../VidstackPlayerFormatterTrait.php | 70 +++++++++++-------- .../VidstackPlayerRemoteVideoFormatter.php | 50 ++++++++----- .../VidstackPlayerVideoFormatter.php | 64 +++++++---------- .../vidstack-player-remote-video.html.twig | 9 ++- templates/vidstack-player-video.html.twig | 9 ++- 5 files changed, 114 insertions(+), 88 deletions(-) diff --git a/src/Plugin/Field/FieldFormatter/VidstackPlayerFormatterTrait.php b/src/Plugin/Field/FieldFormatter/VidstackPlayerFormatterTrait.php index 2c1dee0..8f2b449 100644 --- a/src/Plugin/Field/FieldFormatter/VidstackPlayerFormatterTrait.php +++ b/src/Plugin/Field/FieldFormatter/VidstackPlayerFormatterTrait.php @@ -6,9 +6,12 @@ use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Shared trait for Vidstack Player video formatters. + * + * NOTE, this trait does not portray ALL shared settings. Notably: + * 'controls', 'autoplay' and 'loop' are shared, but not part of this trait. + * This is because they get partially inherited by some formatters parent class. */ trait VidstackPlayerFormatterTrait { - use StringTranslationTrait; /** @@ -20,60 +23,67 @@ trait VidstackPlayerFormatterTrait { * @return array * The shared settings to reduce duplicate code. */ - public function getSharedSettings(array $form) { - $form['autoplay'] = [ - '#title' => $this->t('Autoplay'), - '#type' => 'checkbox', - '#description' => $this->t('Play the video immediately upon page load. This is generally advised against on UX grounds. It is also disabled by default in some browsers.'), - '#default_value' => $this->getSetting('autoplay'), - ]; - $form['loop'] = [ - '#title' => $this->t('Loop'), - '#type' => 'checkbox', - '#description' => $this->t('Loop the video.'), - '#default_value' => $this->getSetting('loop'), - ]; + protected function getSharedSettings(array $form) { + // @see Trait class docblock. $form['muted'] = [ '#title' => $this->t('Muted'), '#type' => 'checkbox', '#description' => $this->t('Start the video muted.'), '#default_value' => $this->getSetting('muted'), ]; - $form['controls'] = [ - '#title' => $this->t('Default controls'), - '#type' => 'checkbox', - '#description' => $this->t('Show the default controls of the video (e.g. from the browser itself or a provider like YouTube).'), - '#default_value' => $this->getSetting('controls'), - ]; $form['load'] = [ '#title' => $this->t('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'), - 'play' => $this->t('Load after hitting play'), - ], + '#options' => $this->getLoadStrategyOptions(), '#description' => $this->t('The load strategy that will be used to determine when the video content should start loading.'), '#default_value' => $this->getSetting('load'), ]; return $form; } + /** + * Returns the load strategy form options. + * + * @return array + * The load strategy options. + */ + protected function getLoadStrategyOptions() { + return [ + 'eager' => $this->t('Load immediately'), + 'idle' => $this->t('Load after the page is loaded'), + 'visible' => $this->t('Load after becoming visible'), + 'play' => $this->t('Load after hitting play'), + ]; + } + /** * Returns the default settings which are shared between formatters. * * @return array * The shared default settings to reduce duplicate code. */ - public static function getSharedDefaultSettings() { + protected static function getSharedDefaultSettings() { return [ - 'autoplay' => FALSE, - 'loop' => FALSE, 'muted' => FALSE, - 'controls' => FALSE, 'load' => 'visible', ]; } + /** + * Returns the settings summary shared between formatters. + * + * @return array + * The shared settings summary. + */ + protected function getSharedSettingsSummary() { + $summary = []; + $summary[] = $this->t('Muted: %muted', [ + '%muted' => $this->getSetting('muted') ? $this->t('yes') : $this->t('no'), + ]); + $summary[] = $this->t('Load strategy: %load', [ + '%load' => $this->getLoadStrategyOptions()[$this->getSetting('load')], + ]); + return $summary; + } + } diff --git a/src/Plugin/Field/FieldFormatter/VidstackPlayerRemoteVideoFormatter.php b/src/Plugin/Field/FieldFormatter/VidstackPlayerRemoteVideoFormatter.php index 49a7a8a..48173e7 100644 --- a/src/Plugin/Field/FieldFormatter/VidstackPlayerRemoteVideoFormatter.php +++ b/src/Plugin/Field/FieldFormatter/VidstackPlayerRemoteVideoFormatter.php @@ -25,7 +25,6 @@ use Drupal\media\Plugin\media\Source\OEmbedInterface; * ) */ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { - use VidstackPlayerFormatterTrait; /** @@ -80,20 +79,17 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { * {@inheritdoc} */ public function settingsSummary() { - $loadStrategies = [ - 'eager' => $this->t('Load immediately'), - 'idle' => $this->t('Load after page-load'), - 'visible' => $this->t('Load after visible'), - 'play' => $this->t('Load after play'), - ]; - $summary = []; - $summary[] = $this->t('Autoplay: <strong>@autoplay</strong><br>Loop: <strong>@loop</strong><br>Muted: <strong>@muted</strong><br>Default controls: <strong>@controls</strong><br>Load strategy: <strong>@load</strong>', [ - '@autoplay' => $this->getSetting('autoplay') ? $this->t('Yes') : $this->t('No'), - '@loop' => $this->getSetting('loop') ? $this->t('Yes') : $this->t('No'), - '@muted' => $this->getSetting('muted') ? $this->t('Yes') : $this->t('No'), - '@controls' => $this->getSetting('controls') ? $this->t('Yes') : $this->t('No'), - '@load' => $loadStrategies[$this->getSetting('load')], + $summary = parent::settingsSummary(); + $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'), ]); + $summary += $this->getSharedSettingsSummary(); return $summary; } @@ -101,14 +97,36 @@ class VidstackPlayerRemoteVideoFormatter extends FormatterBase { * {@inheritdoc} */ public static function defaultSettings() { - return self::getSharedDefaultSettings(); + $settings = parent::defaultSettings(); + $settings['controls'] = FALSE; + $settings['autoplay'] = FALSE; + $settings['loop'] = FALSE; + $settings += self::getSharedDefaultSettings(); + return $settings; } /** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { - return $this->getSharedSettings($form); + $form = parent::settingsForm($form, $form_state); + $form['controls'] = [ + '#title' => $this->t('Show playback controls'), + '#type' => 'checkbox', + '#default_value' => $this->getSetting('controls'), + ]; + $form['autoplay'] = [ + '#title' => $this->t('Autoplay'), + '#type' => 'checkbox', + '#default_value' => $this->getSetting('autoplay'), + ]; + $form['loop'] = [ + '#title' => $this->t('Loop'), + '#type' => 'checkbox', + '#default_value' => $this->getSetting('loop'), + ]; + $form += $this->getSharedSettings($form); + return $form; } /** diff --git a/src/Plugin/Field/FieldFormatter/VidstackPlayerVideoFormatter.php b/src/Plugin/Field/FieldFormatter/VidstackPlayerVideoFormatter.php index 1bdd04a..5608ac8 100644 --- a/src/Plugin/Field/FieldFormatter/VidstackPlayerVideoFormatter.php +++ b/src/Plugin/Field/FieldFormatter/VidstackPlayerVideoFormatter.php @@ -24,7 +24,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * ) */ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements FileMediaFormatterInterface { - use VidstackPlayerFormatterTrait; /** @@ -86,38 +85,21 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil * {@inheritdoc} */ public function settingsSummary() { - $loadStrategies = [ - 'eager' => $this->t('Load immediately'), - 'idle' => $this->t('Load after page-load'), - 'visible' => $this->t('Load after visible'), - 'play' => $this->t('Load after play'), - ]; - $summary = []; - $posterValue = ''; - switch ($this->getSetting('poster')) { - case 'none': - $posterValue = $this->t('None (Show first frame)'); - break; - - case 'custom': - $posterValue = $this->t('Custom URL'); - break; - - default: - $posterValue = $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')], - ]); - break; - } - $summary[] = $this->t('Autoplay: <strong>@autoplay</strong><br>Loop: <strong>@loop</strong><br>Muted: <strong>@muted</strong><br>Default controls: <strong>@controls</strong><br>Load strategy: <strong>@load</strong><br>Poster image: <strong>@poster</strong><br>Poster load strategy: <strong>@posterLoad</strong>', [ - '@autoplay' => $this->getSetting('autoplay') ? $this->t('Yes') : $this->t('No'), - '@loop' => $this->getSetting('loop') ? $this->t('Yes') : $this->t('No'), - '@muted' => $this->getSetting('muted') ? $this->t('Yes') : $this->t('No'), - '@controls' => $this->getSetting('controls') ? $this->t('Yes') : $this->t('No'), - '@load' => $loadStrategies[$this->getSetting('load')], - '@poster' => $posterValue, - '@posterLoad' => $loadStrategies[$this->getSetting('posterLoad')], + $summary = parent::settingsSummary(); + $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[] = $this->t('Poster image: %poster', [ + '%poster' => $posterValue, + ]); + $summary[] = $this->t('Poster load strategy: %load', [ + '%load' => $this->getLoadStrategyOptions()[$this->getSetting('posterLoad')], ]); return $summary; } @@ -126,19 +108,21 @@ class VidstackPlayerVideoFormatter extends FileMediaFormatterBase implements Fil * {@inheritdoc} */ public static function defaultSettings() { - return self::getSharedDefaultSettings() + [ - 'poster' => 'none', - 'posterUrl' => '', - 'posterLoad' => 'visible', - 'posterStyle' => '', - ]; + $settings = parent::defaultSettings(); + $settings += self::getSharedDefaultSettings(); + $settings['poster'] = 'none'; + $settings['posterUrl'] = ''; + $settings['posterLoad'] = 'visible'; + $settings['posterStyle'] = ''; + return $settings; } /** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { - $form = $this->getSharedSettings($form); + $form = parent::settingsForm($form, $form_state); + $form += $this->getSharedSettings($form); $form['poster'] = [ '#title' => $this->t('Poster image'), diff --git a/templates/vidstack-player-remote-video.html.twig b/templates/vidstack-player-remote-video.html.twig index f621e33..3b66ea3 100644 --- a/templates/vidstack-player-remote-video.html.twig +++ b/templates/vidstack-player-remote-video.html.twig @@ -1 +1,8 @@ -<iframe {{ attributes }} allowfullscreen></iframe> +{# + NOTE: We are using "progressive enhancement" here, as documented: + "The target can be any element but if it’s a <audio>, <video>, or + <iframe> element it will be replaced and enhanced (i.e., progressive + enhancement)." + @see https://vidstack.io/docs/player/getting-started/installation/javascript/?provider=youtube&styling=default-layout&install=cdn +#} +<iframe {{ attributes }}></iframe> diff --git a/templates/vidstack-player-video.html.twig b/templates/vidstack-player-video.html.twig index cecb4c0..d656593 100644 --- a/templates/vidstack-player-video.html.twig +++ b/templates/vidstack-player-video.html.twig @@ -1,4 +1,11 @@ -<video {{ attributes }} playsinline> +{# + NOTE: We are using "progressive enhancement" here, as documented: + "The target can be any element but if it’s a <audio>, <video>, or + <iframe> element it will be replaced and enhanced (i.e., progressive + enhancement)." + @see https://vidstack.io/docs/player/getting-started/installation/javascript/?provider=video&styling=default-layout&install=cdn +#} +<video {{ attributes }}> {% for file in files %} <source {{ file.source_attributes }} /> {% endfor %} -- GitLab