From 87558fa811e3f81e5945b45f5a6e4a805225a8bd Mon Sep 17 00:00:00 2001 From: Claudiu Cristea Date: Sun, 25 Aug 2013 15:38:08 +0300 Subject: [PATCH] Issue #1898420 by claudiu.cristea, thedavidmeister, Albert Volkman, shanethehat, DamienMcKenna, c4rl: Image.module - Convert theme_ functions to Twig. --- core/modules/image/image.admin.inc | 225 ++++++--------------- core/modules/image/image.field.inc | 53 ++--- core/modules/image/image.module | 61 +++--- .../image/lib/Drupal/image/ImageEffectBase.php | 5 + .../image/Plugin/ImageEffect/CropImageEffect.php | 45 +++-- .../image/Plugin/ImageEffect/ResizeImageEffect.php | 6 +- .../image/Plugin/ImageEffect/RotateImageEffect.php | 5 +- .../image/Plugin/ImageEffect/ScaleImageEffect.php | 5 +- .../lib/Drupal/image/Tests/ImageDimensionsTest.php | 56 ++--- .../Drupal/image/Tests/ImageFieldDisplayTest.php | 13 +- .../modules/image/templates/image-anchor.html.twig | 14 ++ .../image/templates/image-crop-summary.html.twig | 22 ++ .../image/templates/image-formatter.html.twig | 24 +++ .../image/templates/image-resize-summary.html.twig | 18 ++ .../image/templates/image-rotate-summary.html.twig | 29 +++ .../image/templates/image-scale-summary.html.twig | 39 ++++ .../image/templates/image-style-preview.html.twig | 51 +++++ core/modules/image/templates/image-style.html.twig | 29 +++ .../modules/image/templates/image-widget.html.twig | 25 +++ 19 files changed, 457 insertions(+), 268 deletions(-) create mode 100644 core/modules/image/templates/image-anchor.html.twig create mode 100644 core/modules/image/templates/image-crop-summary.html.twig create mode 100644 core/modules/image/templates/image-formatter.html.twig create mode 100644 core/modules/image/templates/image-resize-summary.html.twig create mode 100644 core/modules/image/templates/image-rotate-summary.html.twig create mode 100644 core/modules/image/templates/image-scale-summary.html.twig create mode 100644 core/modules/image/templates/image-style-preview.html.twig create mode 100644 core/modules/image/templates/image-style.html.twig create mode 100644 core/modules/image/templates/image-widget.html.twig diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc index f90a4c8..ca97c41 100644 --- a/core/modules/image/image.admin.inc +++ b/core/modules/image/image.admin.inc @@ -5,6 +5,8 @@ * Administration pages for image settings. */ +use Drupal\Component\Utility\String; + /** * Returns HTML for a listing of the effects within a specific image style. * @@ -64,113 +66,81 @@ 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 = $variables['style']; + $image_factory = \Drupal::service('image.factory'); - $sample_image = Drupal::config('image.settings')->get('preview_image'); - $sample_width = 160; - $sample_height = 160; - - // Set up original file information. - $original_path = $sample_image; - $image_factory = Drupal::service('image.factory'); - $original_image = $image_factory->get($original_path); - $original_image = array( - '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']); - } - else { - $original_height = min($original_image['height'], $sample_height); - $original_width = round($original_height / $original_image['height'] * $original_image['width']); - } - $original_image['style'] = 'width: ' . $original_width . 'px; height: ' . $original_height . 'px;'; - - // Set up preview file information. - $preview_file = $style->buildUri($original_path); - if (!file_exists($preview_file)) { - $style->createDerivative($original_path, $preview_file); - } - $preview_image = $image_factory->get($preview_file); - $preview_image = array( - 'width' => $preview_image->getWidth(), - 'height' => $preview_image->getHeight(), + // Sample image path, width and height. + $sample = array( + 'path' => \Drupal::config('image.settings')->get('preview_image'), + 'width' => 160, + 'height' => 160, ); - 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']); - } - else { - $preview_height = min($preview_image['height'], $sample_height); - $preview_width = round($preview_height / $preview_image['height'] * $preview_image['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( - '#theme' => 'image', - '#uri' => $original_path, - '#alt' => t('Sample original image'), - '#title' => '', - '#attributes' => $original_image, + // Init the set of original and preview images data. + $variables += array( + 'style_id' => String::checkPlain($style->id()), + 'style_name' => String::checkPlain($style->label()), + 'original' => array(), + 'derivative' => array(), ); - $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( - '#theme' => 'image', - '#uri' => $preview_url, - '#alt' => t('Sample modified image'), - '#title' => '', - '#attributes' => $preview_image, + $images = array( + 'original' => array('label' => t('Sample original image'), 'path' => $sample['path']), + 'derivative' => array('label' => t('Sample modified image'), 'path' => $style->buildUri($sample['path'])), ); - $output .= '
'; - $output .= check_plain($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. + // Create derivative if necessary. + if (!file_exists($images['derivative']['path'])) { + $style->createDerivative($sample['path'], $images['derivative']['path']); + } - return $output; + foreach ($images as $type => $image_info) { + $image = $image_factory->get($image_info['path']); + if ($image->getWidth() > $image->getHeight()) { + $width = min($image->getWidth(), $sample['width']); + $height = round($width / $image->getWidth() * $image->getHeight()); + } + else { + $height = min($image->getHeight(), $sample['height']); + $width = round($height / $image->getHeight() * $image->getWidth()); + } + $variables[$type]['url'] = file_create_url($image_info['path']); + $variables[$type]['width'] = $image->getWidth(); + $variables[$type]['height'] = $image->getHeight(); + $variables[$type]['attributes'] = array( + 'width' => $width, + 'height' => $height, + 'style' => String::format('width: @width; height: @height;', array('@width' => $width . 'px', '@height' => $height . 'px')), + 'alt' => $image_info['label'], + ); + $variables[$type]['rendered'] = array( + '#theme' => 'image', + '#uri' => $image_info['path'], + '#alt' => $image_info['label'], + '#attributes' => $variables[$type]['attributes'], + ); + } } /** - * 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(); @@ -178,86 +148,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( '#theme' => 'table', '#header' => array(), '#rows' => $rows, - '#attributes' => array('class' => array('image-anchor')), + '#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 check_plain($data['width']) . 'x' . check_plain($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'], - ); - 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 ef40ca2..ae53804 100644 --- a/core/modules/image/image.field.inc +++ b/core/modules/image/image.field.inc @@ -384,76 +384,70 @@ function _image_field_required_fields_validate($element, &$form_state) { } /** - * 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: * - item: An array of image data. * - 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) { $item = $variables['item']; - $image = array(); + $variables['image'] = array(); // Do not output an empty 'title' attribute. if (isset($item['title']) && drupal_strlen($item['title']) != 0) { - $image['#title'] = $item['title']; + $variables['image']['#title'] = $item['title']; } if (isset($item['entity']) && empty($item['uri'])) { - $image['#uri'] = $item['entity']->getFileUri(); + $variables['image']['#uri'] = $item['entity']->getFileUri(); } else { - $image['#uri'] = $item['uri']; + $variables['image']['#uri'] = $item['uri']; } foreach (array('width', 'height', 'alt', 'attributes') as $key) { if (isset($item[$key]) || array_key_exists($key, $item)) { - $image["#$key"] = $item[$key]; + $variables['image']["#$key"] = $item[$key]; } } if ($variables['image_style']) { - $image['#theme'] = 'image_style'; - $image['#style_name'] = $variables['image_style']; + $variables['image']['#theme'] = 'image_style'; + $variables['image']['#style_name'] = $variables['image_style']; } else { - $image['#theme'] = 'image'; + $variables['image']['#theme'] = 'image'; } // The link path and link options are both optional, but for the options to be @@ -463,11 +457,6 @@ function theme_image_formatter($variables) { $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 fa03dcd..1e7972b 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -170,6 +170,7 @@ function image_theme() { 'title' => NULL, 'attributes' => array(), ), + 'template' => 'image-style', ), // Theme functions in image.admin.inc. @@ -180,36 +181,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, 'path' => NULL, 'image_style' => NULL), 'file' => 'image.field.inc', + 'template' => 'image-formatter', ), ); } @@ -343,18 +348,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 @@ -368,12 +372,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. @@ -381,28 +381,21 @@ function theme_image_style($variables) { 'width' => $variables['width'], 'height' => $variables['height'], ); - $style->transformDimensions($dimensions); // 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'], '#attributes' => $variables['attributes'], '#uri' => $style->buildUrl($variables['uri']), + '#alt' => isset($variables['alt']) ? $variables['alt'] : NULL, + '#title' => isset($variables['title']) ? $variables['title'] : NULL, + '#style' => $style, ); - - if (isset($variables['alt']) || array_key_exists('alt', $variables)) { - $image['#alt'] = $variables['alt']; - } - if (isset($variables['title']) || array_key_exists('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 2babe0d..c433bc9 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 e46d2fa..9a97fe1 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php @@ -45,10 +45,14 @@ public function applyEffect(ImageInterface $image) { * {@inheritdoc} */ public function getSummary() { - return array( + $summary = array( '#theme' => 'image_crop_summary', '#data' => $this->configuration, ); + $summary += parent::getSummary(); + $summary['#data']['anchor_label'] = self::getAnchorOptions($this->configuration['anchor']); + + return $summary; } /** @@ -64,17 +68,7 @@ public function getForm() { $form['anchor'] = array( '#type' => 'radios', '#title' => t('Anchor'), - '#options' => array( - 'left-top' => t('Top') . ' ' . t('Left'), - 'center-top' => t('Top') . ' ' . t('Center'), - 'right-top' => t('Top') . ' ' . t('Right'), - 'left-center' => t('Center') . ' ' . t('Left'), - 'center-center' => t('Center'), - 'right-center' => t('Center') . ' ' . t('Right'), - 'left-bottom' => t('Bottom') . ' ' . t('Left'), - 'center-bottom' => t('Bottom') . ' ' . t('Center'), - 'right-bottom' => t('Bottom') . ' ' . t('Right'), - ), + '#options' => self::getAnchorOptions(), '#theme' => 'image_anchor', '#default_value' => $this->configuration['anchor'], '#description' => t('The part of the image that will be retained during the crop.'), @@ -82,4 +76,31 @@ public function getForm() { return $form; } + /** + * Builds a list of anchor options. + * + * @var string $anchor + * (optional) If provided, only the label of this anchor will be returned. + * + * @return array|string + * A list of anchor options or an anchor label if $anchor has been provided. + */ + static protected function getAnchorOptions($anchor = NULL) { + $anchors = array( + 'left-top' => t('Top') . ' ' . t('Left'), + 'center-top' => t('Top') . ' ' . t('Center'), + 'right-top' => t('Top') . ' ' . t('Right'), + 'left-center' => t('Center') . ' ' . t('Left'), + 'center-center' => t('Center'), + 'right-center' => t('Center') . ' ' . t('Right'), + 'left-bottom' => t('Bottom') . ' ' . t('Left'), + 'center-bottom' => t('Bottom') . ' ' . t('Center'), + 'right-bottom' => t('Bottom') . ' ' . t('Right'), + ); + if (empty($anchor)) { + return $anchors; + } + return isset($anchors[$anchor]) ? $anchors[$anchor] : NULL; + } + } 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 766e5a7..18cf230 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php @@ -48,10 +48,14 @@ public function transformDimensions(array &$dimensions) { * {@inheritdoc} */ public function getSummary() { - return array( + $summary = parent::getSummary(); + unset($summary['#markup']); + $summary += array( '#theme' => 'image_resize_summary', '#data' => $this->configuration, ); + + 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 fe563ae..7efb7f2 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php @@ -83,10 +83,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 c7b2f53..189f780 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php @@ -54,10 +54,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 c136fa6..f609590 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php @@ -34,7 +34,7 @@ public static function getInfo() { /** * Test styled image dimensions cumulatively. */ - function testImageDimensions() { + public function testImageDimensions() { $image_factory = $this->container->get('image.factory'); // Create a working copy of the file. $files = $this->drupalGetTestFiles('image'); @@ -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, ''); + $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, ''); + $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, ''); + $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, ''); + $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, ''); + $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, ''); + $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, ''); + $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, ''); + $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, ''); + $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 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 e7f8d72..d0eb976 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php @@ -107,15 +107,24 @@ function _testImageFieldFormatters($scheme) { $display_options['settings']['image_link'] = 'content'; $display->setComponent($field_name, $display_options) ->save(); + $image = array( '#theme' => 'image', '#uri' => $image_uri, '#width' => 40, '#height' => 20, ); - $default_output = l($image, 'node/' . $nid, array('html' => TRUE, 'attributes' => array('class' => 'active'))); $this->drupalGet('node/' . $nid); - $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'] = ''; 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..39585b3 --- /dev/null +++ b/core/modules/image/templates/image-crop-summary.html.twig @@ -0,0 +1,22 @@ +{# +/** + * @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 + */ +#} +{% spaceless %} + {{ data.width }}x{{ data.height }} +{% endspaceless %} 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..3ed72b4 --- /dev/null +++ b/core/modules/image/templates/image-formatter.html.twig @@ -0,0 +1,24 @@ +{# +/** + * @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() + * @see template_preprocess_image_formatter() + * + * @ingroup themeable + */ +#} +{% spaceless %} + {% if url %} + {{ image }} + {% else %} + {{ image }} + {% endif %} +{% endspaceless %} 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..cc502c5 --- /dev/null +++ b/core/modules/image/templates/image-resize-summary.html.twig @@ -0,0 +1,18 @@ +{# +/** + * @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 + */ +#} +{{ data.width }}x{{ data.height }} 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..913728a --- /dev/null +++ b/core/modules/image/templates/image-rotate-summary.html.twig @@ -0,0 +1,29 @@ +{# +/** + * @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 + */ +#} +{% spaceless %} + {% if data.random %} + {% trans %} + random between -{{ data.degrees|abs }}° and {{ data.degrees|abs }}° + {% endtrans %} + {% else %} + {{ data.degrees }}° + {% endif %} +{% endspaceless %} 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..cd3cfbb --- /dev/null +++ b/core/modules/image/templates/image-scale-summary.html.twig @@ -0,0 +1,39 @@ +{# +/** + * @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 + */ +#} +{% spaceless %} + {% if data.width and data.height %} + {{ data.width }}x{{ data.height }} + {% else %} + {% if data.width %} + {% trans %} + width {{ data.width }} + {% endtrans %} + {% elseif data.height %} + {% trans %} + height {{ data.height }} + {% endtrans %} + {% endif %} + {% endif %} + + {% if data.upscale %} + {% trans %} + (upscaling allowed) + {% endtrans %} + {% endif %} +{% endspaceless %} 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..1f52a67 --- /dev/null +++ b/core/modules/image/templates/image-style-preview.html.twig @@ -0,0 +1,51 @@ +{# +/** + * @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. + * - 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. + * - attributes: HTML sample attributes for the original style. + * - rendered: The rendered 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. + * - attributes: HTML sample attributes for the derivative style. + * - rendered: The rendered derivative image. + * + * @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
+
+
{# End preview-image-wrapper. #} + + {# Derivative of the image style. #} +
+ {{ style_name }} ({{ 'view actual size'|t }}) +
+ + {{ derivative.rendered }} + +
{{ derivative.height }}px
+
{{ derivative.width }}px
+
+
{# End preview-image-wrapper. #} +
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..9a24420 --- /dev/null +++ b/core/modules/image/templates/image-style.html.twig @@ -0,0 +1,29 @@ +{# +/** + * @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. 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 to an empty + * string, but can be set to NULL for the attribute to be omitted. Usually, + * neither omission nor an empty string satisfies accessibility + * requirements, so it is strongly encouraged for code calling + * theme('image') to pass a meaningful value for this variable. + * http://www.w3.org/TR/REC-html40/struct/objects.html#h-13.8 + * http://www.w3.org/TR/xhtml1/dtds.html + * http://dev.w3.org/html5/spec/Overview.html#alt + * + * @see template_preprocess_image_style() + * + * @ingroup themeable + */ +#} +{% spaceless %}{{ image }}{% endspaceless %} 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..99e14e1 --- /dev/null +++ b/core/modules/image/templates/image-widget.html.twig @@ -0,0 +1,25 @@ +{# +/** + * @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 %} +
+ {{ data }} +
+
-- 1.8.3.1