Skip to content

Commit

Permalink
EWPP-3296: Theme the Media paragraph.
Browse files Browse the repository at this point in the history
  • Loading branch information
22Alexandra committed May 15, 2023
1 parent a426fec commit 23ece95
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 1 deletion.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"openeuropa/oe_corporate_countries": "^2.0.0-alpha6",
"openeuropa/oe_media": "^1.22",
"openeuropa/oe_multilingual": "dev-master",
"openeuropa/oe_paragraphs": "^1.17",
"openeuropa/oe_paragraphs": "dev-EWPP-3295",
"openeuropa/oe_search": "^1.9",
"openeuropa/oe_webtools": "^1.21",
"openeuropa/rdf_skos": "^1.0.0-alpha9",
Expand Down
85 changes: 85 additions & 0 deletions oe_theme.theme
Original file line number Diff line number Diff line change
Expand Up @@ -2204,3 +2204,88 @@ function oe_theme_preprocess_oe_theme_helper_in_page_navigation__node__oe_person
}
}
}

/**
* Implements hook_preprocess_paragraph() for paragraph--oe-av-media.html.twig.
*/
function oe_theme_preprocess_paragraph__oe_av_media(array &$variables): void {
/** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */
$paragraph = $variables['paragraph'];

// Bail out if there is no media present.
if ($paragraph->get('field_oe_media')->isEmpty()) {
return;
}

$cacheability = CacheableMetadata::createFromRenderArray($variables);

/** @var \Drupal\media\Entity\Media $media */
$media = $paragraph->get('field_oe_media')->entity;
if (!$media instanceof MediaInterface) {
// The media entity is not available anymore, bail out.
return;
}

// Retrieve the correct media translation.
$media = \Drupal::service('entity.repository')->getTranslationFromContext($media, $paragraph->language()->getId());

// Caches are handled by the formatter usually. Since we are not rendering
// the original render arrays, we need to propagate our caches to the
// paragraph template.
$cacheability->addCacheableDependency($media);

// Run access checks on the media entity.
$access = $media->access('view', $variables['user'], TRUE);
$cacheability->addCacheableDependency($access);
$cacheability->applyTo($variables);
if (!$access->isAllowed()) {
$cacheability->applyTo($variables);
return;
}

// Get the media source.
$source = $media->getSource();

if ($source instanceof MediaAvPortalVideoSource || $source instanceof OEmbed || $source instanceof Iframe) {
if ($source instanceof MediaAvPortalVideoSource) {
// Default video aspect ratio is set to 16:9 for AV Portal Video.
$variables['ratio'] = '16:9';
}

// Load information about the media and the display.
$media_type = \Drupal::entityTypeManager()->getStorage('media_type')->load($media->bundle());
$cacheability->addCacheableDependency($media_type);
$source_field = $source->getSourceFieldDefinition($media_type);
$display = EntityViewDisplay::collectRenderDisplay($media, 'oe_theme_main_content');
$cacheability->addCacheableDependency($display);
$display_options = $display->getComponent($source_field->getName());

// If it is an OEmbed resource, render it and pass it as embeddable data
// only if it is of type video or html.
if ($source instanceof OEmbed) {
$oembed_type = $source->getMetadata($media, 'type');
if (in_array($oembed_type, ['video', 'html'])) {
$variables['video'] = $media->{$source_field->getName()}->view($display_options);
$cacheability->applyTo($variables);
return;
}
}

// If it's an AV Portal video or a Video iframe, render it.
$variables['video'] = $media->{$source_field->getName()}->view($display_options);
$cacheability->applyTo($variables);

// When dealing with iframe videos, also respect its given aspect ratio.
if ($media->bundle() === 'video_iframe') {
$ratio = $media->get('oe_media_iframe_ratio')->value;
$variables['ratio'] = str_replace('_', '-', $ratio);
}
return;
}

// If it's an image media, render it and assign it to the image variable.
if ($source instanceof MediaAvPortalPhotoSource || $source instanceof Image) {
$thumbnail = $media->get('thumbnail')->first();
$variables['image'] = ImageValueObject::fromStyledImageItem($thumbnail, 'oe_theme_medium_no_crop');
}
}
22 changes: 22 additions & 0 deletions templates/paragraphs/paragraph--oe-av-media.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{#
/**
* @file
* Theme override to display the 'Media' type paragraph.
*
* @see ./modules/contrib/paragraphs/templates/paragraph.html.twig
*/
#}
{% if image %}
{% set media_container = {
'image': image.src,
'alt': image.alt,
} %}
{% elseif video %}
{% set media_container = {
'embedded_media': video,
'ratio': ratio,
} %}
{% endif %}
{% if media_container %}
{% include '@ecl/media-container/media-container.html.twig' with media_container only %}
{% endif %}
166 changes: 166 additions & 0 deletions tests/src/Kernel/Paragraphs/MediaParagraphsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class MediaParagraphsTest extends ParagraphsTestBase {
'file_link',
'oe_paragraphs_carousel',
'composite_reference',
'oe_paragraphs_av_media',
];

/**
Expand All @@ -61,6 +62,7 @@ protected function setUp(): void {
'options',
'oe_media_iframe',
'oe_paragraphs_carousel',
'oe_paragraphs_av_media',
]);
// Call the install hook of the Media module.
module_load_include('install', 'media');
Expand Down Expand Up @@ -1089,4 +1091,168 @@ public function testCarousel(): void {
$assert->assertPattern($expected_values, $html);
}

/**
* Test Media paragraph rendering.
*/
public function testMediaParagraph(): void {
// Set image media translatable.
$this->container->get('content_translation.manager')->setEnabled('media', 'image', TRUE);
// Make the image field translatable.
$field_config = $this->container->get('entity_type.manager')->getStorage('field_config')->load('media.image.oe_media_image');
$field_config->set('translatable', TRUE)->save();
$this->container->get('router.builder')->rebuild();

// Create English file.
$en_file = file_save_data(file_get_contents(drupal_get_path('theme', 'oe_theme') . '/tests/fixtures/example_1.jpeg'), 'public://example_1_en.jpeg');
$en_file->setPermanent();
$en_file->save();

// Create Bulgarian file.
$bg_file = file_save_data(file_get_contents(drupal_get_path('theme', 'oe_theme') . '/tests/fixtures/example_1.jpeg'), 'public://example_1_bg.jpeg');
$bg_file->setPermanent();
$bg_file->save();

// Create a media.
$media_storage = $this->container->get('entity_type.manager')->getStorage('media');
$media = $media_storage->create([
'bundle' => 'image',
'name' => 'test image en',
'oe_media_image' => [
'target_id' => $en_file->id(),
'alt' => 'Alt en',
],
]);
$media->save();
// Translate the media to Bulgarian.
$media_bg = $media->addTranslation('bg', [
'name' => 'test image bg',
'oe_media_image' => [
'target_id' => $bg_file->id(),
'alt' => 'Alt bg',
],
]);
$media_bg->save();

// Create a Media paragraph.
$paragraph = $this->container
->get('entity_type.manager')
->getStorage('paragraph')->create([
'type' => 'oe_av_media',
'field_oe_media' => [
'target_id' => $media->id(),
],
]);
$paragraph->save();

// Add Bulgarian translation.
$paragraph->addTranslation('bg', $paragraph->toArray())->save();

// Test the translated media is rendered with the translated paragraph.
$html = $this->renderParagraph($paragraph);
$crawler = new Crawler($html);

$this->assertCount(1, $crawler->filter('figure.ecl-media-container img.ecl-media-container__media'));
$image_element = $crawler->filter('figure.ecl-media-container img.ecl-media-container__media');
$this->assertStringContainsString('example_1_en.jpeg', $image_element->attr('src'));

// Assert bulgarian rendering.
$html = $this->renderParagraph($paragraph, 'bg');
$crawler = new Crawler($html);
$this->assertCount(1, $crawler->filter('figure.ecl-media-container img.ecl-media-container__media'));
$image_element = $crawler->filter('figure.ecl-media-container img.ecl-media-container__media');
$this->assertStringContainsString('example_1_bg.jpeg', $image_element->attr('src'));

// Unpublish the media and assert it is not rendered anymore.
$media->set('status', 0);
$media->save();

// Since static cache is not cleared due to lack of requests in the test we
// need to reset manually.
$this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache();

$html = $this->renderParagraph($paragraph);
$crawler = new Crawler($html);
$this->assertCount(0, $crawler->filter('figure.ecl-media-container'));

// Create a remote video and add it to the paragraph.
$media = $media_storage->create([
'bundle' => 'remote_video',
'oe_media_oembed_video' => [
'value' => 'https://www.youtube.com/watch?v=1-g73ty9v04',
],
]);
$media->save();
$paragraph->set('field_oe_media', ['target_id' => $media->id()]);
$paragraph->save();

$html = $this->renderParagraph($paragraph);
$crawler = new Crawler($html);
// Assert remote video is rendered properly.
$this->assertCount(1, $crawler->filter('figure.ecl-media-container div.ecl-media-container__media'));
$media_container = $crawler->filter('div.ecl-media-container__media');
$existing_classes = $media_container->attr('class');
$existing_classes = explode(' ', $existing_classes);
$this->assertNotContains('ecl-media-container__media--ratio-16-9', $existing_classes);
$video_iframe = $media_container->filter('iframe');
$partial_iframe_url = Url::fromRoute('media.oembed_iframe', [], [
'query' => [
'url' => 'https://www.youtube.com/watch?v=1-g73ty9v04',
],
])->toString();
$this->assertStringContainsString($partial_iframe_url, $video_iframe->attr('src'));
$this->assertStringContainsString('459', $video_iframe->attr('width'));
$this->assertStringContainsString('344', $video_iframe->attr('height'));

// Create an avportal video and add it to the paragraph.
$media = $media_storage->create([
'bundle' => 'av_portal_video',
'oe_media_avportal_video' => 'I-163162',
]);
$media->save();
$paragraph->set('field_oe_media', ['target_id' => $media->id()]);
$paragraph->save();

// Assert AV Portal video is rendered properly.
$html = $this->renderParagraph($paragraph);
$crawler = new Crawler($html);
$this->assertCount(1, $crawler->filter('figure.ecl-media-container div.ecl-media-container__media'));
$media_container = $crawler->filter('div.ecl-media-container__media');
$this->assertEquals('<iframe id="videoplayerI-163162" src="//ec.europa.eu/avservices/play.cfm?ref=I-163162&amp;lg=EN&amp;sublg=none&amp;autoplay=true&amp;tin=10&amp;tout=59" frameborder="0" allowtransparency allowfullscreen webkitallowfullscreen mozallowfullscreen width="576" height="324" class="media-avportal-content"></iframe>', $media_container->html());

// Create Video iframe with ratio 16:9 and add it to the paragraph.
$media = $media_storage->create([
'bundle' => 'video_iframe',
'oe_media_iframe' => '<iframe src="http://example.com"></iframe>',
'oe_media_iframe_ratio' => '16_9',
]);
$media->save();
$paragraph->set('field_oe_media', ['target_id' => $media->id()]);
$paragraph->save();

$html = $this->renderParagraph($paragraph);
$crawler = new Crawler($html);
$this->assertCount(1, $crawler->filter('figure.ecl-media-container div.ecl-media-container__media'));
$media_container = $crawler->filter('div.ecl-media-container__media');
$this->assertEquals('<iframe src="http://example.com"></iframe>', $media_container->html());

// Create iframe video with aspect ratio 1:1 and add it to the paragraph.
$media = $media_storage->create([
'bundle' => 'video_iframe',
'oe_media_iframe' => '<iframe src="http://example.com"></iframe>',
'oe_media_iframe_ratio' => '1_1',
]);
$media->save();
$paragraph->set('field_oe_media', ['target_id' => $media->id()]);
$paragraph->save();

$html = $this->renderParagraph($paragraph);
$crawler = new Crawler($html);
$this->assertCount(1, $crawler->filter('figure.ecl-media-container div.ecl-media-container__media'));
$media_container = $crawler->filter('div.ecl-media-container__media');
$this->assertEquals('<iframe src="http://example.com"></iframe>', $media_container->html());
$existing_classes = $media_container->attr('class');
$existing_classes = explode(' ', $existing_classes);
$this->assertTrue(in_array('ecl-media-container__media--ratio-1-1', $existing_classes));
}

}

0 comments on commit 23ece95

Please sign in to comment.