diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc index e87ec99..84c5dc0 100644 --- a/core/modules/image/image.admin.inc +++ b/core/modules/image/image.admin.inc @@ -71,113 +71,105 @@ function theme_image_style_effects($variables) { } /** - * Returns HTML for a preview of an image style. + * Prepares variables for image style preview templates. * - * @param $variables + * Default template: image-style-preview.html.twig. + * + * @param array $variables * An associative array containing: * - style: \Drupal\image\ImageStyleInterface image style being previewed. - * - * @ingroup themeable */ -function theme_image_style_preview($variables) { +function template_preprocess_image_style_preview(&$variables) { + // Style information. $style = $variables['style']; + $variables['style_id'] = String::checkPlain($style->id()); + $variables['style_name'] = String::checkPlain($style->label()); - $sample_image = \Drupal::config('image.settings')->get('preview_image'); + // Cache bypass token. + $variables['cache_bypass'] = REQUEST_TIME; + + // Sample image info. $sample_width = 160; $sample_height = 160; + $image_factory = \Drupal::service('image.factory'); // Set up original file information. - $original_path = $sample_image; - $image_factory = \Drupal::service('image.factory'); + $original_path = \Drupal::config('image.settings')->get('preview_image'); $original_image = $image_factory->get($original_path); - $original_image = array( + $variables['original'] = array( + 'url' => file_create_url($original_path), 'width' => $original_image->getWidth(), 'height' => $original_image->getHeight(), ); - if ($original_image['width'] > $original_image['height']) { - $original_width = min($original_image['width'], $sample_width); - $original_height = round($original_width / $original_image['width'] * $original_image['height']); + if ($variables['original']['width'] > $variables['original']['height']) { + $variables['preview']['original']['width'] = min($variables['original']['width'], $sample_width); + $variables['preview']['original']['height'] = round($variables['preview']['original']['width'] / $variables['original']['width'] * $variables['original']['height']); } else { - $original_height = min($original_image['height'], $sample_height); - $original_width = round($original_height / $original_image['height'] * $original_image['width']); + $variables['preview']['original']['height'] = min($variables['original']['height'], $sample_height); + $variables['preview']['original']['width'] = round($variables['preview']['original']['height'] / $variables['original']['height'] * $variables['original']['width']); } - $original_image['style'] = 'width: ' . $original_width . 'px; height: ' . $original_height . 'px;'; - // Set up preview file information. + // Set up derivative file information. $preview_file = $style->buildUri($original_path); + // Create derivative if necessary. if (!file_exists($preview_file)) { $style->createDerivative($original_path, $preview_file); } $preview_image = $image_factory->get($preview_file); - $preview_image = array( + $variables['derivative'] = array( + 'url' => file_create_url($preview_file), 'width' => $preview_image->getWidth(), 'height' => $preview_image->getHeight(), ); - if ($preview_image['width'] > $preview_image['height']) { - $preview_width = min($preview_image['width'], $sample_width); - $preview_height = round($preview_width / $preview_image['width'] * $preview_image['height']); + if ($variables['derivative']['width'] > $variables['derivative']['height']) { + $variables['preview']['derivative']['width'] = min($variables['derivative']['width'], $sample_width); + $variables['preview']['derivative']['height'] = round($variables['preview']['derivative']['width'] / $variables['derivative']['width'] * $variables['derivative']['height']); } else { - $preview_height = min($preview_image['height'], $sample_height); - $preview_width = round($preview_height / $preview_image['height'] * $preview_image['width']); + $variables['preview']['derivative']['height'] = min($variables['derivative']['height'], $sample_height); + $variables['preview']['derivative']['width'] = round($variables['preview']['derivative']['height'] / $variables['derivative']['height'] * $variables['derivative']['width']); } - $preview_image['style'] = 'width: ' . $preview_width . 'px; height: ' . $preview_height . 'px;'; - - // In the previews, timestamps are added to prevent caching of images. - $output = '
'; // Build the preview of the original image. - $original_url = file_create_url($original_path); - $image = array( + $variables['original']['rendered'] = array( '#theme' => 'image', '#uri' => $original_path, '#alt' => t('Sample original image'), '#title' => '', - '#attributes' => $original_image, + '#attributes' => array( + 'width' => $variables['original']['width'], + 'height' => $variables['original']['height'], + 'style' => 'width: ' . $variables['preview']['original']['width'] . 'px; height: ' . $variables['preview']['original']['height'] . 'px;', + ), ); - $output .= '
'; - $output .= t('original') . ' (' . l(t('view actual size'), $original_url) . ')'; - $output .= '
'; - $output .= '' . drupal_render($image) . ''; - $output .= '
' . $original_image['height'] . 'px
'; - $output .= '
' . $original_image['width'] . 'px
'; - $output .= '
'; // End preview-image. - $output .= '
'; // End preview-image-wrapper. - // Build the preview of the image style. - $preview_url = file_create_url($preview_file) . '?cache_bypass=' . REQUEST_TIME; - $image = array( + // Build the preview of the image style derivative. Timestamps are added + // to prevent caching of images on the client side. + $variables['derivative']['rendered'] = array( '#theme' => 'image', - '#uri' => $preview_url, + '#uri' => $variables['derivative']['url'] . '?cache_bypass=' . $variables['cache_bypass'], '#alt' => t('Sample modified image'), '#title' => '', - '#attributes' => $preview_image, + '#attributes' => array( + 'width' => $variables['derivative']['width'], + 'height' => $variables['derivative']['height'], + 'style' => 'width: ' . $variables['preview']['derivative']['width'] . 'px; height: ' . $variables['preview']['derivative']['height'] . 'px;', + ), ); - $output .= '
'; - $output .= String::checkPlain($style->label()) . ' (' . l(t('view actual size'), file_create_url($preview_file) . '?' . time()) . ')'; - $output .= '
'; - $output .= '' . drupal_render($image) . ''; - $output .= '
' . $preview_image['height'] . 'px
'; - $output .= '
' . $preview_image['width'] . 'px
'; - $output .= '
'; // End preview-image. - $output .= '
'; // End preview-image-wrapper. - $output .= '
'; // End image-style-preview. - - return $output; } /** - * Returns HTML for a 3x3 grid of checkboxes for image anchors. + * Prepares variables for image anchor templates. * - * @param $variables - * An associative array containing: - * - element: A render element containing radio buttons. + * Default template: image-anchor.html.twig. * - * @ingroup themeable + * @param array $variables + * An associative array containing: + * - element: An associative array containing the image. */ -function theme_image_anchor($variables) { +function template_preprocess_image_anchor(&$variables) { $element = $variables['element']; $rows = array(); @@ -185,86 +177,21 @@ function theme_image_anchor($variables) { foreach (Element::children($element) as $n => $key) { $element[$key]['#attributes']['title'] = $element[$key]['#title']; unset($element[$key]['#title']); - $row[] = drupal_render($element[$key]); + $row[] = array( + 'data' => $element[$key], + ); if ($n % 3 == 3 - 1) { $rows[] = $row; $row = array(); } } - $table = array( + $variables['table'] = array( '#type' => 'table', '#header' => array(), '#rows' => $rows, - '#attributes' => array('class' => array('image-anchor')), - ); - return drupal_render($table); -} - -/** - * Returns HTML for a summary of an image resize effect. - * - * @param $variables - * An associative array containing: - * - data: The current configuration for this resize effect. - * - * @ingroup themeable - */ -function theme_image_resize_summary($variables) { - $data = $variables['data']; - - if ($data['width'] && $data['height']) { - return String::checkPlain($data['width']) . 'x' . String::checkPlain($data['height']); - } - else { - return ($data['width']) ? t('width @width', array('@width' => $data['width'])) : t('height @height', array('@height' => $data['height'])); - } -} - -/** - * Returns HTML for a summary of an image scale effect. - * - * @param $variables - * An associative array containing: - * - data: The current configuration for this scale effect. - * - * @ingroup themeable - */ -function theme_image_scale_summary($variables) { - $image_resize_summary = array( - '#theme' => 'image_resize_summary', - '#data' => $variables['data'], - ); - return drupal_render($image_resize_summary) . ' ' . ($variables['data']['upscale'] ? '(' . t('upscaling allowed') . ')' : ''); -} - -/** - * Returns HTML for a summary of an image crop effect. - * - * @param $variables - * An associative array containing: - * - data: The current configuration for this crop effect. - * - * @ingroup themeable - */ -function theme_image_crop_summary($variables) { - $image_resize_summary = array( - '#theme' => 'image_resize_summary', - '#data' => $variables['data'], + '#attributes' => array( + 'class' => array('image-anchor'), + ), ); - return drupal_render($image_resize_summary); -} - -/** - * Returns HTML for a summary of an image rotate effect. - * - * @param $variables - * An associative array containing: - * - data: The current configuration for this rotate effect. - * - * @ingroup themeable - */ -function theme_image_rotate_summary($variables) { - $data = $variables['data']; - return ($data['random']) ? t('random between -@degrees° and @degrees°', array('@degrees' => str_replace('-', '', $data['degrees']))) : t('@degrees°', array('@degrees' => $data['degrees'])); } diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc index 5462520..f05ae4c 100644 --- a/core/modules/image/image.field.inc +++ b/core/modules/image/image.field.inc @@ -8,39 +8,35 @@ use Drupal\Component\Utility\NestedArray; /** - * Returns HTML for an image field widget. + * Prepares variables for image widget templates. + * + * Default template: image-widget.html.twig. * * @param array $variables * An associative array containing: * - element: A render element representing the image field widget. - * - * @ingroup themeable */ -function theme_image_widget($variables) { +function template_preprocess_image_widget(&$variables) { $element = $variables['element']; - $output = ''; - $output .= '
'; + $element['#attributes']['class'] = array('image-widget', 'form-managed-file', 'clearfix'); if (isset($element['preview'])) { - $output .= '
'; - $output .= drupal_render($element['preview']); - $output .= '
'; + $variables['preview'] = $element['preview']; } - $output .= '
'; if (!empty($element['fids']['#value'])) { $file = reset($element['#files']); $element['file_' . $file->id()]['filename']['#suffix'] = ' (' . format_size($file->getSize()) . ') '; } - $output .= drupal_render_children($element); - $output .= '
'; - $output .= '
'; - return $output; + $variables['data'] = $element; + $variables['attributes'] = $element['#attributes']; } /** - * Returns HTML for an image field formatter. + * Prepares variables for image formatter templates. + * + * Default template: image-formatter.html.twig. * * @param array $variables * An associative array containing: @@ -49,54 +45,46 @@ function theme_image_widget($variables) { * placed in the img tag. * - image_style: An optional image style. * - path: An optional array containing the link 'path' and link 'options'. - * - * @ingroup themeable */ -function theme_image_formatter($variables) { +function template_preprocess_image_formatter(&$variables) { if ($variables['image_style']) { - $image = array( + $variables['image'] = array( '#theme' => 'image_style', '#style_name' => $variables['image_style'], ); } else { - $image = array( + $variables['image'] = array( '#theme' => 'image', ); } - $image['#attributes'] = $variables['item_attributes']; + $variables['image']['#attributes'] = $variables['item_attributes']; $item = $variables['item']; // Do not output an empty 'title' attribute. if (drupal_strlen($item->title) != 0) { - $image['#title'] = $item->title; + $variables['image']['#title'] = $item->title; } if (($entity = $item->entity) && empty($item->uri)) { - $image['#uri'] = $entity->getFileUri(); + $variables['image']['#uri'] = $entity->getFileUri(); } else { - $image['#uri'] = $item->uri; + $variables['image']['#uri'] = $item->uri; } foreach (array('width', 'height', 'alt') as $key) { - $image["#$key"] = $item->$key; + $variables['image']["#$key"] = $item->$key; } // The link path and link options are both optional, but for the options to be // processed, the link path must at least be an empty string. // @todo Add support for route names. + $variables['url'] = NULL; if (isset($variables['path']['path'])) { $path = $variables['path']['path']; $options = isset($variables['path']['options']) ? $variables['path']['options'] : array(); - // When displaying an image inside a link, the html option must be TRUE. - $options['html'] = TRUE; - $output = l($image, $path, $options); + $variables['url'] = url($path, $options); } - else { - $output = drupal_render($image); - } - - return $output; } diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 9c9e82c..1243594 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -110,6 +110,7 @@ function image_theme() { 'title' => NULL, 'attributes' => array(), ), + 'template' => 'image-style', ), // Theme functions in image.admin.inc. @@ -120,36 +121,40 @@ function image_theme() { 'image_style_preview' => array( 'variables' => array('style' => NULL), 'file' => 'image.admin.inc', + 'template' => 'image-style-preview', ), 'image_anchor' => array( 'render element' => 'element', 'file' => 'image.admin.inc', + 'template' => 'image-anchor', ), 'image_resize_summary' => array( - 'variables' => array('data' => NULL), - 'file' => 'image.admin.inc', + 'variables' => array('data' => NULL, 'effect' => array()), + 'template' => 'image-resize-summary', ), 'image_scale_summary' => array( - 'variables' => array('data' => NULL), - 'file' => 'image.admin.inc', + 'variables' => array('data' => NULL, 'effect' => array()), + 'template' => 'image-scale-summary', ), 'image_crop_summary' => array( - 'variables' => array('data' => NULL), - 'file' => 'image.admin.inc', + 'variables' => array('data' => NULL, 'effect' => array()), + 'template' => 'image-crop-summary', ), 'image_rotate_summary' => array( - 'variables' => array('data' => NULL), - 'file' => 'image.admin.inc', + 'variables' => array('data' => NULL, 'effect' => array()), + 'template' => 'image-rotate-summary', ), // Theme functions in image.field.inc. 'image_widget' => array( 'render element' => 'element', 'file' => 'image.field.inc', + 'template' => 'image-widget', ), 'image_formatter' => array( 'variables' => array('item' => NULL, 'item_attributes' => NULL, 'path' => NULL, 'image_style' => NULL), 'file' => 'image.field.inc', + 'template' => 'image-formatter', ), ); } @@ -280,18 +285,17 @@ function image_style_options($include_empty = TRUE) { } /** - * Returns HTML for an image using a specific image style. + * Prepares variables for image style templates. + * + * Default template: image-style.html.twig. * - * @param $variables + * @param array $variables * An associative array containing: - * - style_name: The name of the style to be used to alter the original image. - * - uri: The path of the image file relative to the Drupal files directory. - * This function does not work with images outside the files directory nor - * with remotely hosted images. This should be in a format such as - * 'images/image.jpg', or using a stream wrapper such as - * 'public://images/image.jpg'. - * - width: The width of the source image (if known). - * - height: The height of the source image (if known). + * - width: The width of the image. + * - height: The height of the image. + * - style_name: The name of the image style to be applied. + * - attributes: Additional attributes to apply to the image. + * - uri: URI of the source image before styling. * - alt: The alternative text for text-based browsers. HTML 4 and XHTML 1.0 * always require an alt attribute. The HTML 5 draft allows the alt * attribute to be omitted in some cases. Therefore, this variable defaults @@ -305,12 +309,8 @@ function image_style_options($include_empty = TRUE) { * - 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. - * - * @ingroup themeable */ -function theme_image_style($variables) { - // @todo Image style loading will be moved outside theme in - // https://drupal.org/node/2029649 +function template_preprocess_image_style(&$variables) { $style = entity_load('image_style', $variables['style_name']); // Determine the dimensions of the styled image. @@ -324,7 +324,7 @@ function theme_image_style($variables) { // Add in the image style name as an HTML class. $variables['attributes']['class'][] = 'image-style-' . drupal_html_class($variables['style_name']); - $image = array( + $variables['image'] = array( '#theme' => 'image', '#width' => $dimensions['width'], '#height' => $dimensions['height'], @@ -333,13 +333,12 @@ function theme_image_style($variables) { ); if (isset($variables['alt']) || array_key_exists('alt', $variables)) { - $image['#alt'] = $variables['alt']; + $variables['image']['#alt'] = $variables['alt']; } if (isset($variables['title']) || array_key_exists('title', $variables)) { - $image['#title'] = $variables['title']; + $variables['image']['#title'] = $variables['title']; } - return drupal_render($image); } /** diff --git a/core/modules/image/lib/Drupal/image/ImageEffectBase.php b/core/modules/image/lib/Drupal/image/ImageEffectBase.php index ea3208a..91bdc29 100644 --- a/core/modules/image/lib/Drupal/image/ImageEffectBase.php +++ b/core/modules/image/lib/Drupal/image/ImageEffectBase.php @@ -50,6 +50,11 @@ public function transformDimensions(array &$dimensions) { public function getSummary() { return array( '#markup' => '', + '#effect' => array( + 'id' => $this->pluginDefinition['id'], + 'label' => $this->label(), + 'description' => $this->pluginDefinition['description'], + ), ); } diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php index 8b1857b..efb4f1c 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php @@ -38,10 +38,13 @@ public function applyEffect(ImageInterface $image) { * {@inheritdoc} */ public function getSummary() { - return array( + $summary = array( '#theme' => 'image_crop_summary', '#data' => $this->configuration, ); + $summary += parent::getSummary(); + + return $summary; } /** diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php index da9b176..a06ff11 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php @@ -46,10 +46,13 @@ public function transformDimensions(array &$dimensions) { * {@inheritdoc} */ public function getSummary() { - return array( + $summary = array( '#theme' => 'image_resize_summary', '#data' => $this->configuration, ); + $summary += parent::getSummary(); + + return $summary; } /** diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php index b0e6bf3..65ee957 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php @@ -74,10 +74,13 @@ public function transformDimensions(array &$dimensions) { * {@inheritdoc} */ public function getSummary() { - return array( + $summary = array( '#theme' => 'image_rotate_summary', '#data' => $this->configuration, ); + $summary += parent::getSummary(); + + return $summary; } /** diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php index 4316bd0..62d92a0 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php @@ -45,10 +45,13 @@ public function transformDimensions(array &$dimensions) { * {@inheritdoc} */ public function getSummary() { - return array( + $summary = array( '#theme' => 'image_scale_summary', '#data' => $this->configuration, ); + $summary += parent::getSummary(); + + return $summary; } /** diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php index 04c6303..4a67167 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php @@ -48,15 +48,16 @@ function testImageDimensions() { $url = $style->buildUrl($original_uri); $variables = array( - 'style_name' => 'test', - 'uri' => $original_uri, - 'width' => 40, - 'height' => 20, + '#theme' => 'image_style', + '#style_name' => 'test', + '#uri' => $original_uri, + '#width' => 40, + '#height' => 20, ); // Verify that the original image matches the hard-coded values. $image_file = $image_factory->get($original_uri); - $this->assertEqual($image_file->getWidth(), $variables['width']); - $this->assertEqual($image_file->getHeight(), $variables['height']); + $this->assertEqual($image_file->getWidth(), $variables['#width']); + $this->assertEqual($image_file->getHeight(), $variables['#height']); // Scale an image that is wider than it is high. $effect = array( @@ -70,8 +71,7 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -91,8 +91,7 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -113,8 +112,7 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -135,8 +133,7 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -153,8 +150,7 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -174,8 +170,7 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -194,8 +189,7 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -215,8 +209,7 @@ function testImageDimensions() { ); $effect_id = $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); @@ -234,7 +227,20 @@ function testImageDimensions() { ); $style->saveImageEffect($effect); - $img_tag = theme_image_style($variables); - $this->assertEqual($img_tag, '' . "\n"); + $this->assertEqual($this->getImageTag($variables), ''); } + + /** + * Render an image style element. + * + * drupal_render() alters the passed $variables array by adding a new key + * '#printed' => TRUE. This prevents next call to re-render the element. We + * wrap drupal_render() in a helper protected method and pass each time a + * fresh array so that $variables won't get altered and the element is + * re-rendered each time. + */ + protected function getImageTag($variables) { + return str_replace("\n", NULL, drupal_render($variables)); + } + } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php index 1a6f890..8f0b472 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php @@ -72,7 +72,7 @@ function _testImageFieldFormatters($scheme) { '#width' => 40, '#height' => 20, ); - $default_output = drupal_render($image); + $default_output = str_replace("\n", NULL, drupal_render($image)); $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.'); // Test the image linked to file formatter. @@ -122,11 +122,19 @@ function _testImageFieldFormatters($scheme) { '#width' => 40, '#height' => 20, ); - $default_output = l($image, 'node/' . $nid, array('html' => TRUE)); $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->assertRaw($default_output, 'Image linked to content formatter displaying correctly on full node view.'); + $elements = $this->xpath( + '//a[@href=:path]/img[@src=:url and @alt="" and @width=:width and @height=:height]', + array( + ':path' => url('node/' . $nid), + ':url' => file_create_url($image['#uri']), + ':width' => $image['#width'], + ':height' => $image['#height'], + ) + ); + $this->assertEqual(count($elements), 1, 'Image linked to content formatter displaying correctly on full node view.'); // Test the image style 'thumbnail' formatter. $display_options['settings']['image_link'] = ''; @@ -217,7 +225,7 @@ function testImageFieldSettings() { $field_name . '[0][title]' => $image['#title'], ); $this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save and keep published')); - $default_output = drupal_render($image); + $default_output = str_replace("\n", NULL, drupal_render($image)); $this->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.'); // Verify that alt/title longer than allowed results in a validation error. @@ -293,7 +301,7 @@ function testImageFieldDefaultImage() { '#width' => 40, '#height' => 20, ); - $default_output = drupal_render($image); + $default_output = str_replace("\n", NULL, drupal_render($image)); $this->drupalGet('node/' . $node->id()); $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); @@ -309,7 +317,7 @@ function testImageFieldDefaultImage() { '#width' => 40, '#height' => 20, ); - $image_output = drupal_render($image); + $image_output = str_replace("\n", NULL, drupal_render($image)); $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.'); @@ -356,7 +364,7 @@ function testImageFieldDefaultImage() { '#width' => 40, '#height' => 20, ); - $default_output = drupal_render($image); + $default_output = str_replace("\n", NULL, drupal_render($image)); $this->drupalGet('node/' . $node->id()); $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); diff --git a/core/modules/image/templates/image-anchor.html.twig b/core/modules/image/templates/image-anchor.html.twig new file mode 100644 index 0000000..eb670a4 --- /dev/null +++ b/core/modules/image/templates/image-anchor.html.twig @@ -0,0 +1,14 @@ +{# +/** + * @file + * Default theme implementation for a 3x3 grid of checkboxes for image anchors. + * + * Available variables: + * - table: HTML for the table of image anchors. + * + * @see template_preprocess_image_anchor() + * + * @ingroup themeable + */ +#} +{{ table }} diff --git a/core/modules/image/templates/image-crop-summary.html.twig b/core/modules/image/templates/image-crop-summary.html.twig new file mode 100644 index 0000000..7c3ded0 --- /dev/null +++ b/core/modules/image/templates/image-crop-summary.html.twig @@ -0,0 +1,32 @@ +{# +/** + * @file + * Default theme implementation for a summary of an image crop effect. + * + * Available variables: + * - data: The current configuration for this resize effect, including: + * - width: The width of the resized image. + * - height: The height of the resized image. + * - anchor: The part of the image that will be retained after cropping. + * - anchor_label: The translated label of the crop anchor. + * - effect: The effect information, including: + * - id: The effect identifier. + * - label: The effect name. + * - description: The effect description. + * + * @ingroup themeable + */ +#} +{% if data.width and data.height -%} + {{ data.width|e }}x{{ data.height|e }} +{%- else -%} + {% if data.width %} + {% trans %} + width {{ data.width|e }} + {% endtrans %} + {% elseif data.height %} + {% trans %} + height {{ data.height|e }} + {% endtrans %} + {% endif %} +{%- endif %} diff --git a/core/modules/image/templates/image-formatter.html.twig b/core/modules/image/templates/image-formatter.html.twig new file mode 100644 index 0000000..0283fcc --- /dev/null +++ b/core/modules/image/templates/image-formatter.html.twig @@ -0,0 +1,21 @@ +{# +/** + * @file + * Default theme implementation to display a formatted image field. + * + * Available variables: + * - image: A collection of image data. + * - image_style: An optional image style. + * - path: An optional array containing the link 'path' and link 'options'. + * - url: An optional URL the image can be linked to. + * + * @see template_preprocess_image_formatter() + * + * @ingroup themeable + */ +#} +{% if url %} + {{ image }} +{% else %} + {{ image }} +{% endif %} diff --git a/core/modules/image/templates/image-resize-summary.html.twig b/core/modules/image/templates/image-resize-summary.html.twig new file mode 100644 index 0000000..3a9c7a7 --- /dev/null +++ b/core/modules/image/templates/image-resize-summary.html.twig @@ -0,0 +1,30 @@ +{# +/** + * @file + * Default theme implementation for a summary of an image resize effect. + * + * Available variables: + * - data: The current configuration for this resize effect, including: + * - width: The width of the resized image. + * - height: The height of the resized image. + * - effect: The effect information, including: + * - id: The effect identifier. + * - label: The effect name. + * - description: The effect description. + * + * @ingroup themeable + */ +#} +{% if data.width and data.height -%} + {{ data.width|e }}x{{ data.height|e }} +{%- else -%} + {% if data.width %} + {% trans %} + width {{ data.width|e }} + {% endtrans %} + {% elseif data.height %} + {% trans %} + height {{ data.height|e }} + {% endtrans %} + {% endif %} +{%- endif %} diff --git a/core/modules/image/templates/image-rotate-summary.html.twig b/core/modules/image/templates/image-rotate-summary.html.twig new file mode 100644 index 0000000..c3cae9d --- /dev/null +++ b/core/modules/image/templates/image-rotate-summary.html.twig @@ -0,0 +1,27 @@ +{# +/** + * @file + * Default theme implementation for a summary of an image rotate effect. + * + * Available variables: + * - data: The current configuration for this resize effect, including: + * - degrees: Degrees to rotate the image, positive values will rotate the + * image clockwise, negative values counter-clockwise. + * - bgcolor: The hex background color of the new areas created as consequence + * of rotation. + * - random: If the rotation angle is randomized. + * - effect: The effect information, including: + * - id: The effect identifier. + * - label: The effect name. + * - description: The effect description. + * + * @ingroup themeable + */ +#} +{% if data.random %} + {% trans %} + random between -{{ data.degrees|abs }}° and {{ data.degrees|abs }}° + {% endtrans %} +{% else %} + {{ data.degrees }}° +{% endif %} diff --git a/core/modules/image/templates/image-scale-summary.html.twig b/core/modules/image/templates/image-scale-summary.html.twig new file mode 100644 index 0000000..2f2f91f --- /dev/null +++ b/core/modules/image/templates/image-scale-summary.html.twig @@ -0,0 +1,37 @@ +{# +/** + * @file + * Default theme implementation for a summary of an image scale effect. + * + * Available variables: + * - data: The current configuration for this resize effect, including: + * - width: The width of the resized image. + * - height: The height of the resized image. + * - upscale: If images larger than their original size can scale. + * - effect: The effect information, including: + * - id: The effect identifier. + * - label: The effect name. + * - description: The effect description. + * + * @ingroup themeable + */ +#} +{% if data.width and data.height -%} + {{ data.width|e }}x{{ data.height|e }} +{%- else -%} + {% if data.width %} + {% trans %} + width {{ data.width|e }} + {% endtrans %} + {% elseif data.height %} + {% trans %} + height {{ data.height|e }} + {% endtrans %} + {% endif %} +{%- endif %} + +{% if data.upscale %} + {% trans %} + (upscaling allowed) + {% endtrans %} +{% endif %} diff --git a/core/modules/image/templates/image-style-preview.html.twig b/core/modules/image/templates/image-style-preview.html.twig new file mode 100644 index 0000000..d6e715c --- /dev/null +++ b/core/modules/image/templates/image-style-preview.html.twig @@ -0,0 +1,57 @@ +{# +/** + * @file + * Default theme implementation to display a preview of an image style. + * + * Available variables: + * - style_id: The ID of the image style. + * - style_name: The name of the image style. + * - cache_bypass: A timestamp token used to avoid browser caching of images. + * - original: An associative array containing: + * - url: The URL of the original image. + * - width: The width in pixels of the original image. + * - height: The height in pixels of the original image. + * - rendered: The render array for the original image. + * - derivative: An associative array containing: + * - url: The URL of the derivative image. + * - width: The width in pixels of the derivative image. + * - height: The height in pixels of the derivative image. + * - rendered: The rendered derivative image. + * - preview: An associative array containing: + * - original: An associative array containing: + * - width: The width in pixels of the original image in the preview. + * - height: The height in pixels of the original image in the preview. + * - derivative: An associative array containing: + * - width: The width in pixels of the derivative image in the preview. + * - height: The height in pixels of the derivative image in the preview. + * + * @see template_preprocess_image_style_preview() + * + * @ingroup themeable + */ +#} +
+ {# Preview of the original image. #} +
+ {{ 'original'|t }} ({{ 'view actual size'|t }}) +
+ + {{ original.rendered }} + +
{{ original.height }}px
+
{{ original.width }}px
+
+
+ + {# Derivative of the image style. #} +
+ {{ style_name }} ({{ 'view actual size'|t }}) +
+ + {{ derivative.rendered }} + +
{{ derivative.height }}px
+
{{ derivative.width }}px
+
+
+
diff --git a/core/modules/image/templates/image-style.html.twig b/core/modules/image/templates/image-style.html.twig new file mode 100644 index 0000000..0c3a291 --- /dev/null +++ b/core/modules/image/templates/image-style.html.twig @@ -0,0 +1,20 @@ +{# +/** + * @file + * Default theme implementation for an image using a specific image style. + * + * Available variables: + * - attributes: HTML attributes for the image, including the following: + * - src: Full URL or relative path to the image file. + * - class: One or more classes to be applied to the image. + * - width: The width of the image (if known). + * - height: The height of the image (if known). + * - title: The title of the image. + * - alt: The alternate text for the image. + * + * @see template_preprocess_image_style() + * + * @ingroup themeable + */ +#} +{{ image }} diff --git a/core/modules/image/templates/image-widget.html.twig b/core/modules/image/templates/image-widget.html.twig new file mode 100644 index 0000000..5435e5e --- /dev/null +++ b/core/modules/image/templates/image-widget.html.twig @@ -0,0 +1,26 @@ +{# +/** + * @file + * Default theme implementation for an image field widget. + * + * Available variables: + * - attributes: HTML attributes for the containing element. + * - preview: A rendered preview image. + * - data: Render elements of image data. + * + * @see template_preprocess_image_widget() + * + * @ingroup themeable + */ +#} + + {% if preview is defined %} +
+ {{ preview }} +
+ {% endif %} +
+ {# Render widget data without the image preview that was output already. #} + {{ data|without('preview') }} +
+ diff --git a/core/modules/responsive_image/lib/Drupal/responsive_image/Tests/ResponsiveImageFieldDisplayTest.php b/core/modules/responsive_image/lib/Drupal/responsive_image/Tests/ResponsiveImageFieldDisplayTest.php index 5d34845..26c8c00 100644 --- a/core/modules/responsive_image/lib/Drupal/responsive_image/Tests/ResponsiveImageFieldDisplayTest.php +++ b/core/modules/responsive_image/lib/Drupal/responsive_image/Tests/ResponsiveImageFieldDisplayTest.php @@ -133,7 +133,7 @@ public function _testResponsiveImageFieldFormatters($scheme) { '#width' => 40, '#height' => 20, ); - $default_output = drupal_render($image); + $default_output = str_replace("\n", NULL, drupal_render($image)); $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.'); // Use the responsive image formatter linked to file formatter.