diff --git a/core/includes/theme.inc b/core/includes/theme.inc index d7387a21f628c68ce89b5c8a204724b727d0e59a..7a45d10791bc4fc73f7a6d1cd40e14d7e259f61c 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1073,11 +1073,31 @@ function template_preprocess_links(&$variables) { * - title: The title text is displayed when the image is hovered in some * popular browsers. * - attributes: Associative array of attributes to be placed in the img tag. + * - srcset: Array of multiple URIs and sizes/multipliers. * - sizes: The sizes attribute for viewport-based selection of images. * - http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content.html#introduction-3:viewport-based-selection-2 */ function template_preprocess_image(&$variables) { - $variables['attributes']['src'] = file_create_url($variables['uri']); + if (!empty($variables['uri'])) { + $variables['attributes']['src'] = file_create_url($variables['uri']); + } + // Generate a srcset attribute conforming to the spec at + // http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#attr-img-srcset + if (!empty($variables['srcset'])) { + $srcset = array(); + foreach ($variables['srcset'] as $src) { + // URI is mandatory. + $source = file_create_url($src['uri']); + if (isset($src['width']) && !empty($src['width'])) { + $source .= ' ' . $src['width']; + } + elseif (isset($src['multiplier']) && !empty($src['multiplier'])) { + $source .= ' ' . $src['multiplier']; + } + $srcset[] = $source; + } + $variables['attributes']['srcset'] = implode(', ', $srcset); + } foreach (array('width', 'height', 'alt', 'title', 'sizes') as $key) { if (isset($variables[$key])) { @@ -2268,7 +2288,7 @@ function drupal_common_theme() { // - http://dev.w3.org/html5/spec/Overview.html#alt // The title attribute is optional in all cases, so it is omitted by // default. - 'variables' => array('uri' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'sizes' => NULL), + 'variables' => array('uri' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'sizes' => NULL, 'srcset' => array()), 'template' => 'image', ), 'breadcrumb' => array( diff --git a/core/modules/system/src/Tests/Theme/ImageTest.php b/core/modules/system/src/Tests/Theme/ImageTest.php index f28e1f7cfa9885253ea9e7b8100128cdd27b666d..f22ef2e8cb38fca17b9e51d440f0bb6874819122 100644 --- a/core/modules/system/src/Tests/Theme/ImageTest.php +++ b/core/modules/system/src/Tests/Theme/ImageTest.php @@ -23,6 +23,21 @@ class ImageTest extends KernelTestBase { */ public static $modules = array('system'); + /* + * The images to test with. + * + * @var array + */ + protected $testImages; + + protected function setUp() { + parent::setUp(); + $this->testImages = array( + '/core/misc/druplicon.png', + '/core/misc/loading.gif', + ); + } + /** * Tests that an image with the sizes attribute is output correctly. */ @@ -32,7 +47,7 @@ function testThemeImageWithSizes() { $image = array( '#theme' => 'image', '#sizes' => $sizes, - '#uri' => '/core/misc/druplicon.png', + '#uri' => reset($this->testImages), '#width' => rand(0, 1000) . 'px', '#height' => rand(0, 500) . 'px', '#alt' => $this->randomMachineName(), @@ -44,4 +59,83 @@ function testThemeImageWithSizes() { $this->assertRaw($sizes, 'Sizes is set correctly.'); } + /** + * Tests that an image with the src attribute is output correctly. + */ + function testThemeImageWithSrc() { + + $image = array( + '#theme' => 'image', + '#uri' => reset($this->testImages), + '#width' => rand(0, 1000) . 'px', + '#height' => rand(0, 500) . 'px', + '#alt' => $this->randomMachineName(), + '#title' => $this->randomMachineName(), + ); + $this->render($image); + + // Make sure the src attribute has the correct value. + $this->assertRaw(file_create_url($image['#uri']), 'Correct output for an image with the src attribute.'); + } + + /** + * Tests that an image with the srcset and multipliers is output correctly. + */ + function testThemeImageWithSrcsetMultiplier() { + // Test with multipliers. + $image = array( + '#theme' => 'image', + '#srcset' => array( + array( + 'uri' => $this->testImages[0], + 'multiplier' => '1x', + ), + array( + 'uri' => $this->testImages[1], + 'multiplier' => '2x', + ), + ), + '#width' => rand(0, 1000) . 'px', + '#height' => rand(0, 500) . 'px', + '#alt' => $this->randomMachineName(), + '#title' => $this->randomMachineName(), + ); + $this->render($image); + + // Make sure the srcset attribute has the correct value. + $this->assertRaw(file_create_url($this->testImages[0]) . ' 1x, ' . file_create_url($this->testImages[1]) . ' 2x', 'Correct output for image with srcset attribute and multipliers.'); + } + + /** + * Tests that an image with the srcset and widths is output correctly. + */ + function testThemeImageWithSrcsetWidth() { + // Test with multipliers. + $widths = array( + rand(0, 500) . 'w', + rand(500, 1000) . 'w', + ); + $image = array( + '#theme' => 'image', + '#srcset' => array( + array( + 'uri' => $this->testImages[0], + 'width' => $widths[0], + ), + array( + 'uri' => $this->testImages[1], + 'width' => $widths[1], + ), + ), + '#width' => rand(0, 1000) . 'px', + '#height' => rand(0, 500) . 'px', + '#alt' => $this->randomMachineName(), + '#title' => $this->randomMachineName(), + ); + $this->render($image); + + // Make sure the srcset attribute has the correct value. + $this->assertRaw(file_create_url($this->testImages[0]) . ' ' . $widths[0] . ', ' . file_create_url($this->testImages[1]) . ' ' . $widths[1], 'Correct output for image with srcset attribute and width descriptors.'); + } + }