/** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { $elements = parent::viewElements($items, $langcode); // Unset #item_attributes to test that the theme function can handle that. foreach ($elements as &$element) { if (isset($element['#item_attributes'])) { unset($element['#item_attributes']); } } return $elements; }
/** * Test responsive image formatters on node display. * * If the empty styles param is set, then the function only tests for the * fallback image style (large). * * @param string $scheme * File scheme to use. * @param bool $empty_styles * If true, use an empty string for image style names. * Defaults to false. */ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles = FALSE) { /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = $this->container->get('renderer'); $node_storage = $this->container->get('entity.manager')->getStorage('node'); $field_name = Unicode::strtolower($this->randomMachineName()); $this->createImageField($field_name, 'article', array('uri_scheme' => $scheme)); // Create a new node with an image attached. Make sure we use a large image // so the scale effects of the image styles always have an effect. $test_image = current($this->drupalGetTestFiles('image', 39325)); // Create alt text for the image. $alt = $this->randomMachineName(); $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt); $node_storage->resetCache(array($nid)); $node = $node_storage->load($nid); // Test that the default formatter is being used. $image_uri = File::load($node->{$field_name}->target_id)->getFileUri(); $image = array('#theme' => 'image', '#uri' => $image_uri, '#width' => 360, '#height' => 240, '#alt' => $alt); $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.'); // Test field not being configured. This should not cause a fatal error. $display_options = array('type' => 'responsive_image_test', 'settings' => ResponsiveImageFormatter::defaultSettings()); $display = $this->container->get('entity.manager')->getStorage('entity_view_display')->load('node.article.default'); if (!$display) { $values = ['targetEntityType' => 'node', 'bundle' => 'article', 'mode' => 'default', 'status' => TRUE]; $display = $this->container->get('entity.manager')->getStorage('entity_view_display')->create($values); } $display->setComponent($field_name, $display_options)->save(); $this->drupalGet('node/' . $nid); // Test theme function for responsive image, but using the test formatter. $display_options = array('type' => 'responsive_image_test', 'settings' => array('image_link' => 'file', 'responsive_image_style' => 'style_one')); $display = entity_get_display('node', 'article', 'default'); $display->setComponent($field_name, $display_options)->save(); $this->drupalGet('node/' . $nid); // Use the responsive image formatter linked to file formatter. $display_options = array('type' => 'responsive_image', 'settings' => array('image_link' => 'file', 'responsive_image_style' => 'style_one')); $display = entity_get_display('node', 'article', 'default'); $display->setComponent($field_name, $display_options)->save(); $default_output = '<a href="' . file_url_transform_relative(file_create_url($image_uri)) . '"><picture'; $this->drupalGet('node/' . $nid); $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); $this->assertTrue(!preg_match('/ image_style\\:/', $cache_tags_header), 'No image style cache tag found.'); $this->removeWhiteSpace(); $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.'); // Verify that the image can be downloaded. $this->assertEqual(file_get_contents($test_image->uri), $this->drupalGet(file_create_url($image_uri)), 'File was downloaded successfully.'); if ($scheme == 'private') { // Only verify HTTP headers when using private scheme and the headers are // sent by Drupal. $this->assertEqual($this->drupalGetHeader('Content-Type'), 'image/png', 'Content-Type header was sent.'); $this->assertTrue(strstr($this->drupalGetHeader('Cache-Control'), 'private') !== FALSE, 'Cache-Control header was sent.'); // Log out and try to access the file. $this->drupalLogout(); $this->drupalGet(file_create_url($image_uri)); $this->assertResponse('403', 'Access denied to original image as anonymous user.'); // Log in again. $this->drupalLogin($this->adminUser); } // Use the responsive image formatter with a responsive image style. $display_options['settings']['responsive_image_style'] = 'style_one'; $display_options['settings']['image_link'] = ''; $display->setComponent($field_name, $display_options)->save(); // Create a derivative so at least one MIME type will be known. $large_style = ImageStyle::load('large'); $large_style->createDerivative($image_uri, $large_style->buildUri($image_uri)); // Output should contain all image styles and all breakpoints. $this->drupalGet('node/' . $nid); if (!$empty_styles) { $this->assertRaw('/styles/medium/'); // Make sure the IE9 workaround is present. $this->assertRaw('<!--[if IE 9]><video style="display: none;"><![endif]-->'); $this->assertRaw('<!--[if IE 9]></video><![endif]-->'); // Assert the empty image is present. $this->assertRaw('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='); $thumbnail_style = ImageStyle::load('thumbnail'); // Assert the output of the 'srcset' attribute (small multipliers first). $this->assertRaw('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== 1x, ' . file_url_transform_relative($thumbnail_style->buildUrl($image_uri)) . ' 1.5x'); $this->assertRaw('/styles/medium/'); // Assert the output of the original image. $this->assertRaw(file_url_transform_relative(file_create_url($image_uri)) . ' 3x'); // Assert the output of the breakpoints. $this->assertRaw('media="(min-width: 0px)"'); $this->assertRaw('media="(min-width: 560px)"'); // Assert the output of the 'sizes' attribute. $this->assertRaw('sizes="(min-width: 700px) 700px, 100vw"'); $this->assertPattern('/media="\\(min-width: 560px\\)".+?sizes="\\(min-width: 700px\\) 700px, 100vw"/'); // Assert the output of the 'srcset' attribute (small images first). $medium_style = ImageStyle::load('medium'); $this->assertRaw(file_url_transform_relative($medium_style->buildUrl($image_uri)) . ' 220w, ' . file_url_transform_relative($large_style->buildUrl($image_uri)) . ' 360w'); $this->assertRaw('media="(min-width: 851px)"'); } $this->assertRaw('/styles/large/'); $cache_tags = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Tags')); $this->assertTrue(in_array('config:responsive_image.styles.style_one', $cache_tags)); if (!$empty_styles) { $this->assertTrue(in_array('config:image.style.medium', $cache_tags)); $this->assertTrue(in_array('config:image.style.thumbnail', $cache_tags)); $this->assertRaw('type="image/png"'); } $this->assertTrue(in_array('config:image.style.large', $cache_tags)); // Test the fallback image style. $image = \Drupal::service('image.factory')->get($image_uri); $fallback_image = array('#theme' => 'image', '#alt' => $alt, '#srcset' => array(array('uri' => file_url_transform_relative($large_style->buildUrl($image->getSource()))))); // The image.html.twig template has a newline after the <img> tag but // responsive-image.html.twig doesn't have one after the fallback image, so // we remove it here. $default_output = trim($renderer->renderRoot($fallback_image)); $this->assertRaw($default_output, 'Image style large formatter displaying correctly on full node view.'); if ($scheme == 'private') { // Log out and try to access the file. $this->drupalLogout(); $this->drupalGet($large_style->buildUrl($image_uri)); $this->assertResponse('403', 'Access denied to image style large as anonymous user.'); $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); $this->assertTrue(!preg_match('/ image_style\\:/', $cache_tags_header), 'No image style cache tag found.'); } }
/** * {@inheritdoc} */ public static function isApplicable(FieldDefinitionInterface $field_definition) { // This formatter only applies to multi-image fields return parent::isApplicable($field_definition) && $field_definition->getFieldStorageDefinition()->isMultiple(); }