Commit 9f47a874 authored by webchick's avatar webchick

Issue #1898420 by mondrake, joelpittet, InternetDevels, claudiu.cristea, c4rl,...

Issue #1898420 by mondrake, joelpittet, InternetDevels, claudiu.cristea, c4rl, DamienMcKenna, Albert Volkman, shanethehat, thedavidmeister: Image.module - Convert theme_ functions to Twig.
parent d4ac8181
This diff is collapsed.
......@@ -6,41 +6,38 @@
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Render\Element;
/**
* 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 .= '<div class="image-widget form-managed-file clearfix">';
if (isset($element['preview'])) {
$output .= '<div class="image-preview">';
$output .= drupal_render($element['preview']);
$output .= '</div>';
}
$variables['attributes'] = array('class' => array('image-widget', 'form-managed-file', 'clearfix'));
$output .= '<div class="image-widget-data">';
if (!empty($element['fids']['#value'])) {
$file = reset($element['#files']);
$element['file_' . $file->id()]['filename']['#suffix'] = ' <span class="file-size">(' . format_size($file->getSize()) . ')</span> ';
}
$output .= drupal_render_children($element);
$output .= '</div>';
$output .= '</div>';
return $output;
$variables['data'] = array();
foreach (Element::children($element) as $child) {
$variables['data'][$child] = $element[$child];
}
}
/**
* 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 +46,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;
}
......@@ -108,6 +108,7 @@ function image_theme() {
'title' => NULL,
'attributes' => array(),
),
'template' => 'image-style',
),
// Theme functions in image.admin.inc.
......@@ -118,36 +119,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',
),
);
}
......@@ -268,18 +273,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
......@@ -293,12 +297,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.
......@@ -312,7 +312,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'],
......@@ -321,13 +321,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);
}
/**
......
......@@ -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'],
),
);
}
......
......@@ -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;
}
/**
......
......@@ -45,10 +45,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;
}
/**
......
......@@ -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;
}
/**
......
......@@ -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;
}
/**
......
......@@ -49,15 +49,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(
......@@ -72,8 +73,7 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="120" height="60" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" width="120" height="60" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -94,8 +94,7 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="60" height="120" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" width="60" height="120" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -117,8 +116,7 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -140,8 +138,7 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -159,8 +156,7 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -181,8 +177,7 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -202,8 +197,7 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="30" height="30" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" width="30" height="30" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -224,8 +218,7 @@ function testImageDimensions() {
$effect_id = $style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" alt="" />');
$this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
$this->drupalGet($url);
$this->assertResponse(200, 'Image was generated at the URL.');
......@@ -244,7 +237,20 @@ function testImageDimensions() {
$style->addImageEffect($effect);
$style->save();
$img_tag = theme_image_style($variables);
$this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />' . "\n");
$this->assertEqual($this->getImageTag($variables), '<img class="image-style-test" src="' . $url . '" alt="" />');
}
/**
* 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));
}
}
......@@ -73,7 +73,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.
......@@ -123,11 +123,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'] = '';
......@@ -218,7 +226,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.
......@@ -294,7 +302,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.');
......@@ -310,7 +318,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.');
......@@ -357,7 +365,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.');
......
{#
/**
* @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 }}
{#
/**
* @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 %}
{#
/**
* @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 %}
<a href="{{ url }}">{{ image }}</a>
{% else %}
{{ image }}
{% endif %}
{#
/**
* @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 %}
{#
/**
* @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 }}&deg; and {{ data.degrees|abs }}&deg;
{% endtrans %}
{% else %}
{{ data.degrees }}&deg;
{% endif %}
{#
/**
* @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 %}
{#
/**
* @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
*/
#}
<div class="image-style-preview preview clearfix">