Browse Source

Merge branch '3359393-drupal-image-alt-parameter' into '3.x'

Issue #3359393: drupal_image() should provide the required #alt parameter

See merge request project/twig_tweak!30
merge-requests/30/merge
Julian Pustkuchen 2 years ago
parent
commit
f3aa6e31c7
  1. 7
      docs/cheat-sheet.md
  2. 4
      src/TwigTweakExtension.php
  3. 8
      src/View/ImageViewBuilder.php
  4. 90
      tests/src/Kernel/ImageViewBuilderTest.php

7
docs/cheat-sheet.md

@ -118,8 +118,11 @@ Note that drupal_field() does not work for view modes powered by Layout Builder.
{# Render image specified by file URI. #}
{{ drupal_image('public://ocean.jpg') }}
{# Render image using 'thumbnail' image style and custom attributes. #}
{{ drupal_image('public://ocean.jpg', 'thumbnail', {alt: 'The alternative text'|t, title: 'The title text'|t}) }}
{# Render image specified by file URI with alt text #}
{{ drupal_image('public://ocean.jpg', alt='The alternative text'|t) }}
{# Render image using 'thumbnail' image style, alt text and custom attributes. #}
{{ drupal_image('public://ocean.jpg', 'thumbnail', {title: 'The title text'|t}, alt='The alternative text'|t) }}
{# Render image using 'thumbnail' image style with lazy/eager loading (by attribute). #}
{{ drupal_image('public://ocean.jpg', 'thumbnail', {loading: 'lazy'}) }}

4
src/TwigTweakExtension.php

@ -232,7 +232,7 @@ class TwigTweakExtension extends AbstractExtension {
/**
* Builds an image.
*/
public static function drupalImage(string $selector, string $style = NULL, array $attributes = [], bool $responsive = FALSE, bool $check_access = TRUE): array {
public static function drupalImage(string $selector, string $style = NULL, array $attributes = [], bool $responsive = FALSE, bool $check_access = TRUE, string $alt = ''): array {
// Determine selector type by its value.
if (preg_match('/^\d+$/', $selector)) {
@ -257,7 +257,7 @@ class TwigTweakExtension extends AbstractExtension {
ksort($files);
$file = reset($files);
return \Drupal::service('twig_tweak.image_view_builder')->build($file, $style, $attributes, $responsive, $check_access);
return \Drupal::service('twig_tweak.image_view_builder')->build($file, $style, $attributes, $responsive, $check_access, $alt);
}
/**

8
src/View/ImageViewBuilder.php

@ -24,11 +24,13 @@ class ImageViewBuilder {
* (optional) Indicates that the provided image style is responsive.
* @param bool $check_access
* (optional) Indicates that access check is required.
* @param bool $alt
* (optional) The image "alt" text.
*
* @return array
* A renderable array to represent the image.
*/
public function build(FileInterface $file, string $style = NULL, array $attributes = [], bool $responsive = FALSE, bool $check_access = TRUE): array {
public function build(FileInterface $file, string $style = NULL, array $attributes = [], bool $responsive = FALSE, bool $check_access = TRUE, string $alt = ''): array {
$access = $check_access ? $file->access('view', NULL, TRUE) : AccessResult::allowed();
@ -40,14 +42,18 @@ class ImageViewBuilder {
if ($responsive) {
$build['#type'] = 'responsive_image';
$build['#responsive_image_style_id'] = $style;
// This is currently inconsistent: https://www.drupal.org/project/drupal/issues/3359410
$build['#attributes']['alt'] = $alt;
}
else {
$build['#theme'] = 'image_style';
$build['#style_name'] = $style;
$build['#alt'] = $alt;
}
}
else {
$build['#theme'] = 'image';
$build['#alt'] = $alt;
}
}

90
tests/src/Kernel/ImageViewBuilderTest.php

@ -78,6 +78,7 @@ final class ImageViewBuilderTest extends AbstractTestCase {
'#uri' => 'public://ocean.jpg',
'#attributes' => [],
'#theme' => 'image',
'#alt' => '',
'#cache' => [
'contexts' => [
'user',
@ -93,13 +94,36 @@ final class ImageViewBuilderTest extends AbstractTestCase {
self::assertRenderArray($expected_build, $build);
self::assertSame('<img src="/files/ocean.jpg" alt="" />', $this->renderPlain($build));
// -- Without style, with alt.
$build = $view_builder->build($public_image, NULL, [], FALSE, TRUE, 'The attribute');
$expected_build = [
'#uri' => 'public://ocean.jpg',
'#attributes' => [],
'#theme' => 'image',
'#alt' => 'The attribute',
'#cache' => [
'contexts' => [
'user',
'user.permissions',
],
'tags' => [
'file:1',
'tag_for_public://ocean.jpg',
],
'max-age' => 70,
],
];
self::assertRenderArray($expected_build, $build);
self::assertSame('<img src="/files/ocean.jpg" alt="The attribute" />', $this->renderPlain($build));
// -- With style.
$build = $view_builder->build($public_image, 'large', ['alt' => 'Ocean']);
$build = $view_builder->build($public_image, 'large', ['title' => 'The title']);
$expected_build = [
'#uri' => 'public://ocean.jpg',
'#attributes' => ['alt' => 'Ocean'],
'#attributes' => ['title' => 'The title'],
'#theme' => 'image_style',
'#style_name' => 'large',
'#alt' => '',
'#cache' => [
'contexts' => [
'user',
@ -113,13 +137,66 @@ final class ImageViewBuilderTest extends AbstractTestCase {
],
];
self::assertRenderArray($expected_build, $build);
self::assertSame('<img alt="Ocean" src="/files/styles/large/public/ocean.jpg?itok=abc" />', $this->renderPlain($build));
self::assertSame('<img title="The title" src="/files/styles/large/public/ocean.jpg?itok=abc" alt="" />', $this->renderPlain($build));
// -- With responsive style.
$build = $view_builder->build($public_image, 'wide', ['alt' => 'Ocean'], TRUE);
$build = $view_builder->build($public_image, 'wide', ['title' => 'The title'], TRUE);
$expected_build = [
'#uri' => 'public://ocean.jpg',
'#attributes' => ['alt' => 'Ocean'],
'#attributes' => [
'title' => 'The title',
'alt' => '',
],
'#type' => 'responsive_image',
'#responsive_image_style_id' => 'wide',
'#cache' => [
'contexts' => [
'user',
'user.permissions',
],
'tags' => [
'file:1',
'tag_for_public://ocean.jpg',
],
'max-age' => 70,
],
];
self::assertRenderArray($expected_build, $build);
self::assertSame('<picture><img src="/files/ocean.jpg" alt="" title="The title" /></picture>', $this->renderPlain($build));
// -- With style and alt
$build = $view_builder->build($public_image, 'large', ['title' => 'The title'], FALSE, TRUE, 'The attribute');
$expected_build = [
'#uri' => 'public://ocean.jpg',
'#attributes' => [
'title' => 'The title',
],
'#theme' => 'image_style',
'#style_name' => 'large',
'#alt' => 'The attribute',
'#cache' => [
'contexts' => [
'user',
'user.permissions',
],
'tags' => [
'file:1',
'tag_for_public://ocean.jpg',
],
'max-age' => 70,
],
];
self::assertRenderArray($expected_build, $build);
self::assertSame('<img title="The title" src="/files/styles/large/public/ocean.jpg?itok=abc" alt="The attribute" />', $this->renderPlain($build));
// -- With responsive style and alt.
$build = $view_builder->build($public_image, 'wide', ['title' => 'The title'], TRUE, TRUE, 'The attribute');
$expected_build = [
'#uri' => 'public://ocean.jpg',
'#attributes' => [
'title' => 'The title',
'alt' => 'The attribute',
],
'#type' => 'responsive_image',
'#responsive_image_style_id' => 'wide',
'#cache' => [
@ -135,7 +212,7 @@ final class ImageViewBuilderTest extends AbstractTestCase {
],
];
self::assertRenderArray($expected_build, $build);
self::assertSame('<picture><img src="/files/ocean.jpg" alt="Ocean" /></picture>', $this->renderPlain($build));
self::assertSame('<picture><img src="/files/ocean.jpg" alt="The attribute" title="The title" /></picture>', $this->renderPlain($build));
// -- Private image with access check.
$build = $view_builder->build($private_image);
@ -158,6 +235,7 @@ final class ImageViewBuilderTest extends AbstractTestCase {
'#uri' => 'private://sea.jpg',
'#attributes' => [],
'#theme' => 'image',
'#alt' => '',
'#cache' => [
'contexts' => [],
'tags' => ['file:2'],

Loading…
Cancel
Save