diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigSchemaTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigSchemaTest.php index d3bceb8..ce81657 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigSchemaTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigSchemaTest.php @@ -104,8 +104,8 @@ function testSchemaMapping() { $expected['mapping']['label']['type'] = 'label'; $expected['mapping']['effects']['type'] = 'sequence'; $expected['mapping']['effects']['sequence'][0]['type'] = 'mapping'; - $expected['mapping']['effects']['sequence'][0]['mapping']['name']['type'] = 'string'; - $expected['mapping']['effects']['sequence'][0]['mapping']['data']['type'] = 'image.effect.[%parent.name]'; + $expected['mapping']['effects']['sequence'][0]['mapping']['id']['type'] = 'string'; + $expected['mapping']['effects']['sequence'][0]['mapping']['data']['type'] = 'image.effect.[%parent.id]'; $expected['mapping']['effects']['sequence'][0]['mapping']['weight']['type'] = 'integer'; $expected['mapping']['effects']['sequence'][0]['mapping']['ieid']['type'] = 'string'; $expected['mapping']['langcode']['label'] = 'Default language'; @@ -191,7 +191,7 @@ function testSchemaData() { $this->assertTrue(count($effects) == 1, 'Got an array with effects for image.style.large data'); $ieid = key($effects->getValue()); $effect = $effects[$ieid]; - $this->assertTrue(count($effect['data']) && $effect['name']->getValue() == 'image_scale', 'Got data for the image scale effect from metadata.'); + $this->assertTrue(count($effect['data']) && $effect['id']->getValue() == 'image_scale', 'Got data for the image scale effect from metadata.'); $this->assertEqual($effect['data']['width']->getType(), 'integer', 'Got the right type for the scale effect width.'); $this->assertEqual($effect['data']['width']->getValue(), 480, 'Got the right value for the scale effect width.' ); diff --git a/core/modules/image/config/image.style.large.yml b/core/modules/image/config/image.style.large.yml index 30bb1af..3c0ccb9 100644 --- a/core/modules/image/config/image.style.large.yml +++ b/core/modules/image/config/image.style.large.yml @@ -2,7 +2,7 @@ name: large label: 'Large (480x480)' effects: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d: - name: image_scale + id: image_scale data: width: '480' height: '480' diff --git a/core/modules/image/config/image.style.medium.yml b/core/modules/image/config/image.style.medium.yml index 1047f86..0cad324 100644 --- a/core/modules/image/config/image.style.medium.yml +++ b/core/modules/image/config/image.style.medium.yml @@ -2,7 +2,7 @@ name: medium label: 'Medium (220x220)' effects: bddf0d06-42f9-4c75-a700-a33cafa25ea0: - name: image_scale + id: image_scale data: width: '220' height: '220' diff --git a/core/modules/image/config/image.style.thumbnail.yml b/core/modules/image/config/image.style.thumbnail.yml index 5834812..557237b 100644 --- a/core/modules/image/config/image.style.thumbnail.yml +++ b/core/modules/image/config/image.style.thumbnail.yml @@ -2,7 +2,7 @@ name: thumbnail label: 'Thumbnail (100x100)' effects: 1cfec298-8620-4749-b100-ccb6c4500779: - name: image_scale + id: image_scale data: width: '100' height: '100' diff --git a/core/modules/image/config/schema/image.schema.yml b/core/modules/image/config/schema/image.schema.yml index 6916f19..5c4692a 100644 --- a/core/modules/image/config/schema/image.schema.yml +++ b/core/modules/image/config/schema/image.schema.yml @@ -26,10 +26,10 @@ image.style.*: sequence: - type: mapping mapping: - name: + id: type: string data: - type: image.effect.[%parent.name] + type: image.effect.[%parent.id] weight: type: integer ieid: diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc index 02af74e..e1cbbbf 100644 --- a/core/modules/image/image.admin.inc +++ b/core/modules/image/image.admin.inc @@ -38,6 +38,7 @@ function image_style_list() { function image_style_form($form, &$form_state, $style) { $title = t('Edit style %name', array('%name' => $style->label())); drupal_set_title($title, PASS_THROUGH); + $manager = Drupal::service('plugin.manager.image.effect'); $form_state['image_style'] = $style; $form['#tree'] = TRUE; @@ -71,13 +72,12 @@ function image_style_form($form, &$form_state, $style) { ); if (!empty($style->effects)) { foreach ($style->effects as $key => $effect) { + $effect_instance = $manager->getInstance($effect); $form['effects'][$key]['#weight'] = isset($form_state['input']['effects']) ? $form_state['input']['effects'][$key]['weight'] : NULL; $form['effects'][$key]['label'] = array( '#markup' => check_plain($effect['label']), ); - $form['effects'][$key]['summary'] = array( - '#markup' => isset($effect['summary theme']) ? theme($effect['summary theme'], array('data' => $effect['data'])) : '', - ); + $form['effects'][$key]['summary'] = $effect_instance->getSummary(); $form['effects'][$key]['weight'] = array( '#type' => 'weight', '#title' => t('Weight for @title', array('@title' => $effect['label'])), @@ -86,7 +86,7 @@ function image_style_form($form, &$form_state, $style) { ); $links = array(); - if (isset($effect['form callback'])) { + if (!$effect['no_form']) { $links['edit'] = array( 'title' => t('edit'), 'href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key, @@ -104,7 +104,7 @@ function image_style_form($form, &$form_state, $style) { '#type' => 'link', '#title' => t('edit'), '#href' => 'admin/config/media/image-styles/manage/' . $style->id() . '/effects/' . $key, - '#access' => isset($effect['form callback']), + '#access' => !$effect['no_form'], ); $form['effects'][$key]['remove'] = array( '#type' => 'link', @@ -116,7 +116,9 @@ function image_style_form($form, &$form_state, $style) { // Build the new image effect addition form and add it to the effect list. $new_effect_options = array(); - foreach (image_effect_definitions() as $effect => $definition) { + $effects = $manager->getDefinitions(); + uasort($effects, '_image_effect_definitions_sort'); + foreach ($effects as $effect => $definition) { $new_effect_options[$effect] = $definition['label']; } $form['effects']['new'] = array( @@ -168,17 +170,17 @@ function image_style_form_add_validate($form, &$form_state) { function image_style_form_add_submit($form, &$form_state) { $style = $form_state['image_style']; // Check if this field has any configuration options. - $effect = image_effect_definition_load($form_state['values']['new']); + $effect = Drupal::service('plugin.manager.image.effect')->getDefinition($form_state['values']['new']); // Load the configuration form for this option. - if (isset($effect['form callback'])) { + if (!$effect['no_form']) { $path = 'admin/config/media/image-styles/manage/' . $style->id() . '/add/' . $form_state['values']['new']; $form_state['redirect'] = array($path, array('query' => array('weight' => $form_state['values']['weight']))); } // If there's no form, immediately add the image effect. else { $effect = array( - 'name' => $effect['name'], + 'id' => $effect['id'], 'data' => array(), 'weight' => $form_state['values']['weight'], ); @@ -198,7 +200,7 @@ function image_style_form_submit($form, &$form_state) { foreach ($form_state['values']['effects'] as $ieid => $effect_data) { if (isset($style->effects[$ieid])) { $effect = array( - 'name' => $style->effects[$ieid]['name'], + 'id' => $style->effects[$ieid]['id'], 'data' => $style->effects[$ieid]['data'], 'weight' => $effect_data['weight'], 'ieid' => $ieid, @@ -265,8 +267,8 @@ function image_style_add_form_submit($form, &$form_state) { * Form builder; Form for adding and editing image effects. * * This form is used universally for editing all image effects. Each effect adds - * its own custom section to the form by calling the 'form callback' specified - * in hook_image_effect_info(). + * its own custom section to the form by overriding + * \Drupal\image\ImageEffectInterface::getForm(). * * @param $form_state * An associative array containing the current state of the form. @@ -276,16 +278,13 @@ function image_style_add_form_submit($form, &$form_state) { * An image effect array. * * @ingroup forms - * @see image_resize_form() - * @see image_scale_form() - * @see image_rotate_form() - * @see image_crop_form() + * * @see image_effect_form_submit() */ function image_effect_form($form, &$form_state, $style, $effect) { // If there's no configuration for this image effect, return to // the image style page. - if (!isset($effect['form callback'])) { + if ($effect['no_form']) { return new RedirectResponse(url('admin/config/media/image-styles/manage/' . $style->id(), array('absolute' => TRUE))); } $form_state['image_style'] = $style; @@ -305,12 +304,12 @@ function image_effect_form($form, &$form_state, $style, $effect) { '#type' => 'value', '#value' => !empty($effect['ieid']) ? $effect['ieid'] : NULL, ); - $form['name'] = array( + $form['id'] = array( '#type' => 'value', - '#value' => $effect['name'], + '#value' => $effect['id'], ); - $form['data'] = call_user_func($effect['form callback'], $effect['data']); + $form['data'] = Drupal::service('plugin.manager.image.effect')->getInstance($effect)->getForm(); $form['data']['#tree'] = TRUE; // Check the URL for a weight, then the image effect, otherwise use default. @@ -371,137 +370,6 @@ function image_effect_scale_validate($element, &$form_state) { } /** - * Form structure for the image resize form. - * - * Note that this is not a complete form, it only contains the portion of the - * form for configuring the resize options. Therefore it does not not need to - * include metadata about the effect, nor a submit button. - * - * @param $data - * The current configuration for this resize effect. - */ -function image_resize_form($data) { - $form['width'] = array( - '#type' => 'number', - '#title' => t('Width'), - '#default_value' => isset($data['width']) ? $data['width'] : '', - '#field_suffix' => ' ' . t('pixels'), - '#required' => TRUE, - '#min' => 1, - ); - $form['height'] = array( - '#type' => 'number', - '#title' => t('Height'), - '#default_value' => isset($data['height']) ? $data['height'] : '', - '#field_suffix' => ' ' . t('pixels'), - '#required' => TRUE, - '#min' => 1, - ); - return $form; -} - -/** - * Form structure for the image scale form. - * - * Note that this is not a complete form, it only contains the portion of the - * form for configuring the scale options. Therefore it does not not need to - * include metadata about the effect, nor a submit button. - * - * @param $data - * The current configuration for this scale effect. - */ -function image_scale_form($data) { - $form = image_resize_form($data); - $form['#element_validate'] = array('image_effect_scale_validate'); - $form['width']['#required'] = FALSE; - $form['height']['#required'] = FALSE; - $form['upscale'] = array( - '#type' => 'checkbox', - '#default_value' => (isset($data['upscale'])) ? $data['upscale'] : 0, - '#title' => t('Allow Upscaling'), - '#description' => t('Let scale make images larger than their original size'), - ); - return $form; -} - -/** - * Form structure for the image crop form. - * - * Note that this is not a complete form, it only contains the portion of the - * form for configuring the crop options. Therefore it does not not need to - * include metadata about the effect, nor a submit button. - * - * @param $data - * The current configuration for this crop effect. - */ -function image_crop_form($data) { - $data += array( - 'width' => '', - 'height' => '', - 'anchor' => 'center-center', - ); - - $form = image_resize_form($data); - $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'), - ), - '#theme' => 'image_anchor', - '#default_value' => $data['anchor'], - '#description' => t('The part of the image that will be retained during the crop.'), - ); - - return $form; -} - -/** - * Form structure for the image rotate form. - * - * Note that this is not a complete form, it only contains the portion of the - * form for configuring the rotate options. Therefore it does not not need to - * include metadata about the effect, nor a submit button. - * - * @param $data - * The current configuration for this rotate effect. - */ -function image_rotate_form($data) { - $form['degrees'] = array( - '#type' => 'number', - '#default_value' => (isset($data['degrees'])) ? $data['degrees'] : 0, - '#title' => t('Rotation angle'), - '#description' => t('The number of degrees the image should be rotated. Positive numbers are clockwise, negative are counter-clockwise.'), - '#field_suffix' => '°', - '#required' => TRUE, - ); - $form['bgcolor'] = array( - '#type' => 'textfield', - '#default_value' => (isset($data['bgcolor'])) ? $data['bgcolor'] : '#FFFFFF', - '#title' => t('Background color'), - '#description' => t('The background color to use for exposed areas of the image. Use web-style hex colors (#FFFFFF for white, #000000 for black). Leave blank for transparency on image types that support it.'), - '#size' => 7, - '#maxlength' => 7, - '#element_validate' => array('image_effect_color_validate'), - ); - $form['random'] = array( - '#type' => 'checkbox', - '#default_value' => (isset($data['random'])) ? $data['random'] : 0, - '#title' => t('Randomize'), - '#description' => t('Randomize the rotation angle for each image. The angle specified above is used as a maximum.'), - ); - return $form; -} - -/** * Returns HTML for the page containing the list of image styles. * * @param $variables diff --git a/core/modules/image/image.api.php b/core/modules/image/image.api.php index d2990f5..471f9fa 100644 --- a/core/modules/image/image.api.php +++ b/core/modules/image/image.api.php @@ -11,58 +11,16 @@ */ /** - * Define information about image effects provided by a module. - * - * This hook enables modules to define image manipulation effects for use with - * an image style. - * - * @return - * An array of image effects. This array is keyed on the machine-readable - * effect name. Each effect is defined as an associative array containing the - * following items: - * - "label": The human-readable name of the effect. - * - "effect callback": The function to call to perform this image effect. - * - "dimensions passthrough": (optional) Set this item if the effect doesn't - * change the dimensions of the image. - * - "dimensions callback": (optional) The function to call to transform - * dimensions for this effect. - * - "help": (optional) A brief description of the effect that will be shown - * when adding or configuring this image effect. - * - "form callback": (optional) The name of a function that will return a - * $form array providing a configuration form for this image effect. - * - "summary theme": (optional) The name of a theme function that will output - * a summary of this image effect's configuration. - * - * @see hook_image_effect_info_alter() - */ -function hook_image_effect_info() { - $effects = array(); - - $effects['mymodule_resize'] = array( - 'label' => t('Resize'), - 'help' => t('Resize an image to an exact set of dimensions, ignoring aspect ratio.'), - 'effect callback' => 'mymodule_resize_effect', - 'dimensions callback' => 'mymodule_resize_dimensions', - 'form callback' => 'mymodule_resize_form', - 'summary theme' => 'mymodule_resize_summary', - ); - - return $effects; -} - -/** - * Alter the information provided in hook_image_effect_info(). + * Alter the information provided in \Drupal\image\Annotation\ImageEffect. * * @param $effects * The array of image effects, keyed on the machine-readable effect name. - * - * @see hook_image_effect_info() */ function hook_image_effect_info_alter(&$effects) { // Override the Image module's crop effect with more options. - $effects['image_crop']['effect callback'] = 'mymodule_crop_effect'; - $effects['image_crop']['dimensions callback'] = 'mymodule_crop_dimensions'; - $effects['image_crop']['form callback'] = 'mymodule_crop_form'; + $effects['image_crop']['effect_callback'] = 'mymodule_crop_effect'; + $effects['image_crop']['dimensions_callback'] = 'mymodule_crop_dimensions'; + $effects['image_crop']['form_callback'] = 'mymodule_crop_form'; } /** diff --git a/core/modules/image/image.effects.inc b/core/modules/image/image.effects.inc deleted file mode 100644 index 619b09b..0000000 --- a/core/modules/image/image.effects.inc +++ /dev/null @@ -1,322 +0,0 @@ - array( - 'label' => t('Resize'), - 'help' => t('Resizing will make images an exact set of dimensions. This may cause images to be stretched or shrunk disproportionately.'), - 'effect callback' => 'image_resize_effect', - 'dimensions callback' => 'image_resize_dimensions', - 'form callback' => 'image_resize_form', - 'summary theme' => 'image_resize_summary', - ), - 'image_scale' => array( - 'label' => t('Scale'), - 'help' => t('Scaling will maintain the aspect-ratio of the original image. If only a single dimension is specified, the other dimension will be calculated.'), - 'effect callback' => 'image_scale_effect', - 'dimensions callback' => 'image_scale_dimensions', - 'form callback' => 'image_scale_form', - 'summary theme' => 'image_scale_summary', - ), - 'image_scale_and_crop' => array( - 'label' => t('Scale and crop'), - 'help' => t('Scale and crop will maintain the aspect-ratio of the original image, then crop the larger dimension. This is most useful for creating perfectly square thumbnails without stretching the image.'), - 'effect callback' => 'image_scale_and_crop_effect', - 'dimensions callback' => 'image_resize_dimensions', - 'form callback' => 'image_resize_form', - 'summary theme' => 'image_resize_summary', - ), - 'image_crop' => array( - 'label' => t('Crop'), - 'help' => t('Cropping will remove portions of an image to make it the specified dimensions.'), - 'effect callback' => 'image_crop_effect', - 'dimensions callback' => 'image_resize_dimensions', - 'form callback' => 'image_crop_form', - 'summary theme' => 'image_crop_summary', - ), - 'image_desaturate' => array( - 'label' => t('Desaturate'), - 'help' => t('Desaturate converts an image to grayscale.'), - 'effect callback' => 'image_desaturate_effect', - 'dimensions passthrough' => TRUE, - ), - 'image_rotate' => array( - 'label' => t('Rotate'), - 'help' => t('Rotating an image may cause the dimensions of an image to increase to fit the diagonal.'), - 'effect callback' => 'image_rotate_effect', - 'dimensions callback' => 'image_rotate_dimensions', - 'form callback' => 'image_rotate_form', - 'summary theme' => 'image_rotate_summary', - ), - ); - - return $effects; -} - -/** - * Image effect callback; Resize an image resource. - * - * @param object $image - * An image object returned by image_load(). - * @param array $data - * An array of attributes to use when performing the resize effect with the - * following items: - * - "width": An integer representing the desired width in pixels. - * - "height": An integer representing the desired height in pixels. - * - * @return bool - * TRUE on success. FALSE on failure to resize image. - * - * @see image_resize() - */ -function image_resize_effect($image, array $data) { - if (!image_resize($image, $data['width'], $data['height'])) { - watchdog('image', 'Image resize failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); - return FALSE; - } - return TRUE; -} - -/** - * Image dimensions callback; Resize. - * - * @param array $dimensions - * Dimensions to be modified - an array with components width and height, in - * pixels. - * @param array $data - * An array of attributes to use when performing the resize effect with the - * following items: - * - "width": An integer representing the desired width in pixels. - * - "height": An integer representing the desired height in pixels. - */ -function image_resize_dimensions(array &$dimensions, array $data) { - // The new image will have the exact dimensions defined for the effect. - $dimensions['width'] = $data['width']; - $dimensions['height'] = $data['height']; -} - -/** - * Image effect callback; Scale an image resource. - * - * @param object $image - * An image object returned by image_load(). - * @param array $data - * An array of attributes to use when performing the scale effect with the - * following items: - * - "width": An integer representing the desired width in pixels. - * - "height": An integer representing the desired height in pixels. - * - "upscale": A boolean indicating that the image should be upscaled if the - * dimensions are larger than the original image. - * - * @return bool - * TRUE on success. FALSE on failure to scale image. - * - * @see image_scale() - */ -function image_scale_effect($image, array $data) { - // Set sane default values. - $data += array( - 'width' => NULL, - 'height' => NULL, - 'upscale' => FALSE, - ); - - if (!image_scale($image, $data['width'], $data['height'], $data['upscale'])) { - watchdog('image', 'Image scale failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); - return FALSE; - } - return TRUE; -} - -/** - * Image dimensions callback; Scale. - * - * @param array $dimensions - * Dimensions to be modified - an array with components width and height, in - * pixels. - * @param array $data - * An array of attributes to use when performing the scale effect with the - * following items: - * - "width": An integer representing the desired width in pixels. - * - "height": An integer representing the desired height in pixels. - * - "upscale": A boolean indicating that the image should be upscaled if the - * dimensions are larger than the original image. - */ -function image_scale_dimensions(array &$dimensions, array $data) { - if ($dimensions['width'] && $dimensions['height']) { - image_dimensions_scale($dimensions, $data['width'], $data['height'], $data['upscale']); - } -} - -/** - * Image effect callback; Crop an image resource. - * - * @param object $image - * An image object returned by image_load(). - * @param array $data - * An array of attributes to use when performing the crop effect with the - * following items: - * - "width": An integer representing the desired width in pixels. - * - "height": An integer representing the desired height in pixels. - * - "anchor": A string describing where the crop should originate in the form - * of "XOFFSET-YOFFSET". XOFFSET is either a number of pixels or - * "left", "center", "right" and YOFFSET is either a number of pixels or - * "top", "center", "bottom". - * - * @return bool - * TRUE on success. FALSE on failure to crop image. - * - * @see image_crop() - */ -function image_crop_effect($image, array $data) { - // Set sane default values. - $data += array( - 'anchor' => 'center-center', - ); - - list($x, $y) = explode('-', $data['anchor']); - $x = image_filter_keyword($x, $image->info['width'], $data['width']); - $y = image_filter_keyword($y, $image->info['height'], $data['height']); - if (!image_crop($image, $x, $y, $data['width'], $data['height'])) { - watchdog('image', 'Image crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); - return FALSE; - } - return TRUE; -} - -/** - * Image effect callback; Scale and crop an image resource. - * - * @param object $image - * An image object returned by image_load(). - * @param array $data - * An array of attributes to use when performing the scale and crop effect - * with the following items: - * - "width": An integer representing the desired width in pixels. - * - "height": An integer representing the desired height in pixels. - * - * @return bool - * TRUE on success. FALSE on failure to scale and crop image. - * - * @see image_scale_and_crop() - */ -function image_scale_and_crop_effect($image, array $data) { - if (!image_scale_and_crop($image, $data['width'], $data['height'])) { - watchdog('image', 'Image scale and crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); - return FALSE; - } - return TRUE; -} - -/** - * Image effect callback; Desaturate (grayscale) an image resource. - * - * @param object $image - * An image object returned by image_load(). - * @param array $data - * An array of attributes to use when performing the desaturate effect. - * - * @return bool - * TRUE on success. FALSE on failure to desaturate image. - * - * @see image_desaturate() - */ -function image_desaturate_effect($image, $data) { - if (!image_desaturate($image)) { - watchdog('image', 'Image desaturate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); - return FALSE; - } - return TRUE; -} - -/** - * Image effect callback; Rotate an image resource. - * - * @param object $image - * An image object returned by image_load(). - * @param array $data - * An array of attributes to use when performing the rotate effect containing - * the following items: - * - "degrees": The number of (clockwise) degrees to rotate the image. - * - "random": A boolean indicating that a random rotation angle should be - * used for this image. The angle specified in "degrees" is used as a - * positive and negative maximum. - * - "bgcolor": The background color to use for exposed areas of the image. - * Use web-style hex colors (#FFFFFF for white, #000000 for black). Leave - * blank for transparency on image types that support it. - * - * @return bool - * TRUE on success. FALSE on failure to rotate image. - * - * @see image_rotate(). - */ -function image_rotate_effect($image, $data) { - // Set sane default values. - $data += array( - 'degrees' => 0, - 'bgcolor' => NULL, - 'random' => FALSE, - ); - - // Convert short #FFF syntax to full #FFFFFF syntax. - if (strlen($data['bgcolor']) == 4) { - $c = $data['bgcolor']; - $data['bgcolor'] = $c[0] . $c[1] . $c[1] . $c[2] . $c[2] . $c[3] . $c[3]; - } - - // Convert #FFFFFF syntax to hexadecimal colors. - if ($data['bgcolor'] != '') { - $data['bgcolor'] = hexdec(str_replace('#', '0x', $data['bgcolor'])); - } - else { - $data['bgcolor'] = NULL; - } - - if (!empty($data['random'])) { - $degrees = abs((float) $data['degrees']); - $data['degrees'] = rand(-1 * $degrees, $degrees); - } - - if (!image_rotate($image, $data['degrees'], $data['bgcolor'])) { - watchdog('image', 'Image rotate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); - return FALSE; - } - return TRUE; -} - -/** - * Image dimensions callback; Rotate. - * - * @param array $dimensions - * Dimensions to be modified - an array with components width and height, in - * pixels. - * @param array $data - * An array of attributes to use when performing the rotate effect containing - * the following items: - * - "degrees": The number of (clockwise) degrees to rotate the image. - * - "random": A boolean indicating that a random rotation angle should be - * used for this image. The angle specified in "degrees" is used as a - * positive and negative maximum. - */ -function image_rotate_dimensions(array &$dimensions, array $data) { - // If the rotate is not random and the angle is a multiple of 90 degrees, - // then the new dimensions can be determined. - if (!$data['random'] && ((int) ($data['degrees']) == $data['degrees']) && ($data['degrees'] % 90 == 0)) { - if ($data['degrees'] % 180 != 0) { - $temp = $dimensions['width']; - $dimensions['width'] = $dimensions['height']; - $dimensions['height'] = $temp; - } - } - else { - $dimensions['width'] = $dimensions['height'] = NULL; - } -} diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 9a3dd64..d3bb6ab 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -76,10 +76,15 @@ function image_help($path, $arg) { case 'admin/config/media/image-styles': return '

' . t('Image styles commonly provide thumbnail sizes by scaling and cropping images, but can also add various effects before an image is displayed. When an image is displayed with a style, a new file is created and the original image is left unchanged.') . '

'; case 'admin/config/media/image-styles/manage/%/add/%': - $effect = image_effect_definition_load($arg[7]); + $effect = Drupal::service('plugin.manager.image.effect')->getDefinition($arg[7]); return isset($effect['help']) ? ('

' . $effect['help'] . '

') : NULL; case 'admin/config/media/image-styles/manage/%/effects/%': - $effect = ($arg[5] == 'add') ? image_effect_definition_load($arg[6]) : image_effect_load($arg[6], $arg[4]); + if ($arg[5] == 'add') { + $effect = Drupal::service('plugin.manager.image.effect')->getDefinition($arg[6]); + } + else { + $effect = image_effect_load($arg[6], $arg[4]); + } return isset($effect['help']) ? ('

' . $effect['help'] . '

') : NULL; } } @@ -525,8 +530,9 @@ function image_style_create_derivative($style, $source, $destination) { } if (!empty($style->effects)) { + $manager = Drupal::service('plugin.manager.image.effect'); foreach ($style->effects as $effect) { - image_effect_apply($image, $effect); + $manager->getInstance($effect)->processEffect($image); } } @@ -552,20 +558,13 @@ function image_style_create_derivative($style, $source, $destination) { * pixels. */ function image_style_transform_dimensions($style_name, array &$dimensions) { - module_load_include('inc', 'image', 'image.effects'); $style = entity_load('image_style', $style_name); if (!empty($style->effects)) { + $manager = Drupal::service('plugin.manager.image.effect'); foreach ($style->effects as $effect) { - if (isset($effect['dimensions passthrough'])) { - continue; - } - - if (isset($effect['dimensions callback'])) { - $effect['dimensions callback']($dimensions, $effect['data']); - } - else { - $dimensions['width'] = $dimensions['height'] = NULL; + if (!$effect['dimensions_passthrough']) { + $manager->getInstance($effect)->processDimensions($dimensions); } } } @@ -704,51 +703,6 @@ function image_style_path($style_name, $uri) { } /** - * Returns a set of image effects. - * - * These image effects are exposed by modules implementing - * hook_image_effect_info(). - * - * @return - * An array of image effects to be used when transforming images. - * @see hook_image_effect_info() - * @see image_effect_definition_load() - */ -function image_effect_definitions() { - $language_interface = language(Language::TYPE_INTERFACE); - - // hook_image_effect_info() includes translated strings, so each language is - // cached separately. - $langcode = $language_interface->id; - - $effects = &drupal_static(__FUNCTION__); - - if (!isset($effects)) { - if ($cache = cache()->get("image_effects:$langcode")) { - $effects = $cache->data; - } - else { - $effects = array(); - include_once __DIR__ . '/image.effects.inc'; - foreach (module_implements('image_effect_info') as $module) { - foreach (module_invoke($module, 'image_effect_info') as $name => $effect) { - // Ensure the current toolkit supports the effect. - $effect['module'] = $module; - $effect['name'] = $name; - $effect['data'] = isset($effect['data']) ? $effect['data'] : array(); - $effects[$name] = $effect; - } - } - uasort($effects, '_image_effect_definitions_sort'); - drupal_alter('image_effect_info', $effects); - cache()->set("image_effects:$langcode", $effects); - } - } - - return $effects; -} - -/** * Loads the definition for an image effect. * * The effect definition is a set of core properties for an image effect, not @@ -771,8 +725,7 @@ function image_effect_definitions() { * one-line summary of the effect. Does not include the "theme_" prefix. */ function image_effect_definition_load($effect) { - $definitions = image_effect_definitions(); - return isset($definitions[$effect]) ? $definitions[$effect] : NULL; + return Drupal::service('plugin.manager.image.effect')->getDefinition($effect); } /** @@ -792,12 +745,11 @@ function image_effect_definition_load($effect) { * Besides these keys, the entirety of the image definition is merged into * the image effect array. Returns NULL if the specified effect cannot be * found. - * @see image_effect_definition_load() */ function image_effect_load($ieid, $style_name) { if (($style = entity_load('image_style', $style_name)) && isset($style->effects[$ieid])) { $effect = $style->effects[$ieid]; - $definition = image_effect_definition_load($effect['name']); + $definition = Drupal::service('plugin.manager.image.effect')->getDefinition($effect['id']); $effect = array_merge($definition, $effect); // @todo The effect's key name within the style is unknown. It *should* be // identical to the ieid, but that is in no way guaranteed. And of course, @@ -826,7 +778,7 @@ function image_effect_load($ieid, $style_name) { function image_effect_save($style, &$effect) { // Remove all values that are not properties of an image effect. // @todo Convert image effects into plugins. - $effect = array_intersect_key($effect, array_flip(array('ieid', 'module', 'name', 'data', 'weight'))); + $effect = array_intersect_key($effect, array_flip(array('ieid', 'module', 'id', 'data', 'weight'))); // Generate a unique image effect ID for a new effect. if (empty($effect['ieid'])) { @@ -856,22 +808,6 @@ function image_effect_delete($style, $effect) { } /** - * Applies an image effect to the image object. - * - * @param $image - * An image object returned by image_load(). - * @param $effect - * An image effect array. - * @return - * TRUE on success. FALSE if unable to perform the image effect on the image. - */ -function image_effect_apply($image, $effect) { - module_load_include('inc', 'image', 'image.effects'); - $function = $effect['effect callback']; - return $function($image, $effect['data']); -} - -/** * Returns HTML for an image using a specific image style. * * @param $variables @@ -946,11 +882,9 @@ function image_filter_keyword($value, $current_pixels, $new_pixels) { /** * Internal function for sorting image effect definitions through uasort(). - * - * @see image_effect_definitions() */ function _image_effect_definitions_sort($a, $b) { - return strcasecmp($a['name'], $b['name']); + return strcasecmp($a['id'], $b['id']); } /** diff --git a/core/modules/image/image.services.yml b/core/modules/image/image.services.yml new file mode 100644 index 0000000..0658bf7 --- /dev/null +++ b/core/modules/image/image.services.yml @@ -0,0 +1,4 @@ +services: + plugin.manager.image.effect: + class: Drupal\image\ImageEffectManager + arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler'] diff --git a/core/modules/image/lib/Drupal/image/Annotation/ImageEffect.php b/core/modules/image/lib/Drupal/image/Annotation/ImageEffect.php new file mode 100644 index 0000000..7d2038c --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Annotation/ImageEffect.php @@ -0,0 +1,74 @@ + '', + ); + } + + /** + * {@inheritdoc} + */ + public function getForm() { + return array(); + } + +} diff --git a/core/modules/image/lib/Drupal/image/ImageEffectInterface.php b/core/modules/image/lib/Drupal/image/ImageEffectInterface.php new file mode 100644 index 0000000..825b197 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/ImageEffectInterface.php @@ -0,0 +1,39 @@ + $namespaces['Drupal\image']); + parent::__construct('ImageEffect', $namespaces, $annotation_namespaces, 'Drupal\image\Annotation\ImageEffect'); + + $this->alterInfo($module_handler, 'image_effect_info'); + $this->setCacheBackend($cache_backend, $language_manager, 'image_effect'); + } + + /** + * Returns a preconfigured image effect plugin. + * + * @param array $options + * An array of options that can be used to determine a suitable plugin to + * instantiate and how to configure it. + * + * @return \Drupal\image\ImageEffectInterface + * An image effect plugin. + */ + public function getInstance(array $options) { + $options += array('data' => array()); + return $this->createInstance($options['id'], $options['data']); + } + +} diff --git a/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php index 3f35f5b..8459d7a 100644 --- a/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php +++ b/core/modules/image/lib/Drupal/image/ImageStyleStorageController.php @@ -19,10 +19,11 @@ class ImageStyleStorageController extends ConfigStorageController { * Overrides \Drupal\Core\Config\Entity\ConfigStorageController::attachLoad(). */ protected function attachLoad(&$queried_entities, $revision_id = FALSE) { + $manager = \Drupal::service('plugin.manager.image.effect'); foreach ($queried_entities as $style) { if (!empty($style->effects)) { foreach ($style->effects as $ieid => $effect) { - $definition = image_effect_definition_load($effect['name']); + $definition = $manager->getDefinition($effect['id']); $effect = array_merge($definition, $effect); $style->effects[$ieid] = $effect; } diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php new file mode 100644 index 0000000..391564a --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php @@ -0,0 +1,84 @@ +configuration += array( + 'anchor' => 'center-center', + ); + + list($x, $y) = explode('-', $this->configuration['anchor']); + $x = image_filter_keyword($x, $image->info['width'], $this->configuration['width']); + $y = image_filter_keyword($y, $image->info['height'], $this->configuration['height']); + if (!image_crop($image, $x, $y, $this->configuration['width'], $this->configuration['height'])) { + watchdog('image', 'Image crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + return FALSE; + } + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function getSummary() { + return array( + '#theme' => 'image_crop_summary', + '#data' => $this->configuration, + ); + } + + /** + * {@inheritdoc} + */ + public function getForm() { + $this->configuration += array( + 'width' => '', + 'height' => '', + 'anchor' => 'center-center', + ); + $form = parent::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'), + ), + '#theme' => 'image_anchor', + '#default_value' => $this->configuration['anchor'], + '#description' => t('The part of the image that will be retained during the crop.'), + ); + return $form; + } + +} diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php new file mode 100644 index 0000000..9150032 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php @@ -0,0 +1,38 @@ + $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + return FALSE; + } + return TRUE; + } + +} diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php new file mode 100644 index 0000000..a40f7d3 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php @@ -0,0 +1,78 @@ +configuration['width'], $this->configuration['height'])) { + watchdog('image', 'Image resize failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + return FALSE; + } + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function processDimensions(array &$dimensions) { + // The new image will have the exact dimensions defined for the effect. + $dimensions['width'] = $this->configuration['width']; + $dimensions['height'] = $this->configuration['height']; + } + + /** + * {@inheritdoc} + */ + public function getSummary() { + return array( + '#theme' => 'image_resize_summary', + '#data' => $this->configuration, + ); + } + + /** + * {@inheritdoc} + */ + public function getForm() { + $form['width'] = array( + '#type' => 'number', + '#title' => t('Width'), + '#default_value' => isset($this->configuration['width']) ? $this->configuration['width'] : '', + '#field_suffix' => ' ' . t('pixels'), + '#required' => TRUE, + '#min' => 1, + ); + $form['height'] = array( + '#type' => 'number', + '#title' => t('Height'), + '#default_value' => isset($this->configuration['height']) ? $this->configuration['height'] : '', + '#field_suffix' => ' ' . t('pixels'), + '#required' => TRUE, + '#min' => 1, + ); + return $form; + } + +} diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php new file mode 100644 index 0000000..5bf0d28 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php @@ -0,0 +1,120 @@ +configuration += array( + 'degrees' => 0, + 'bgcolor' => NULL, + 'random' => FALSE, + ); + + // Convert short #FFF syntax to full #FFFFFF syntax. + if (strlen($this->configuration['bgcolor']) == 4) { + $c = $this->configuration['bgcolor']; + $this->configuration['bgcolor'] = $c[0] . $c[1] . $c[1] . $c[2] . $c[2] . $c[3] . $c[3]; + } + + // Convert #FFFFFF syntax to hexadecimal colors. + if ($this->configuration['bgcolor'] != '') { + $this->configuration['bgcolor'] = hexdec(str_replace('#', '0x', $this->configuration['bgcolor'])); + } + else { + $this->configuration['bgcolor'] = NULL; + } + + if (!empty($this->configuration['random'])) { + $degrees = abs((float) $this->configuration['degrees']); + $this->configuration['degrees'] = rand(-1 * $degrees, $degrees); + } + + if (!image_rotate($image, $this->configuration['degrees'], $this->configuration['bgcolor'])) { + watchdog('image', 'Image rotate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + return FALSE; + } + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function processDimensions(array &$dimensions) { + // If the rotate is not random and the angle is a multiple of 90 degrees, + // then the new dimensions can be determined. + if (!$this->configuration['random'] && ((int) ($this->configuration['degrees']) == $this->configuration['degrees']) && ($this->configuration['degrees'] % 90 == 0)) { + if ($this->configuration['degrees'] % 180 != 0) { + $temp = $dimensions['width']; + $dimensions['width'] = $dimensions['height']; + $dimensions['height'] = $temp; + } + } + else { + $dimensions['width'] = $dimensions['height'] = NULL; + } + } + + /** + * {@inheritdoc} + */ + public function getSummary() { + return array( + '#theme' => 'image_rotate_summary', + '#data' => $this->configuration, + ); + } + + /** + * {@inheritdoc} + */ + public function getForm() { + $form['degrees'] = array( + '#type' => 'number', + '#default_value' => (isset($this->configuration['degrees'])) ? $this->configuration['degrees'] : 0, + '#title' => t('Rotation angle'), + '#description' => t('The number of degrees the image should be rotated. Positive numbers are clockwise, negative are counter-clockwise.'), + '#field_suffix' => '°', + '#required' => TRUE, + ); + $form['bgcolor'] = array( + '#type' => 'textfield', + '#default_value' => (isset($this->configuration['bgcolor'])) ? $this->configuration['bgcolor'] : '#FFFFFF', + '#title' => t('Background color'), + '#description' => t('The background color to use for exposed areas of the image. Use web-style hex colors (#FFFFFF for white, #000000 for black). Leave blank for transparency on image types that support it.'), + '#size' => 7, + '#maxlength' => 7, + '#element_validate' => array('image_effect_color_validate'), + ); + $form['random'] = array( + '#type' => 'checkbox', + '#default_value' => (isset($this->configuration['random'])) ? $this->configuration['random'] : 0, + '#title' => t('Randomize'), + '#description' => t('Randomize the rotation angle for each image. The angle specified above is used as a maximum.'), + ); + return $form; + } + +} diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php new file mode 100644 index 0000000..9ee30f0 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php @@ -0,0 +1,35 @@ +configuration['width'], $this->configuration['height'])) { + watchdog('image', 'Image scale and crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + return FALSE; + } + return TRUE; + } + +} diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php new file mode 100644 index 0000000..aab5ae8 --- /dev/null +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php @@ -0,0 +1,79 @@ +configuration += array( + 'width' => NULL, + 'height' => NULL, + 'upscale' => FALSE, + ); + + if (!image_scale($image, $this->configuration['width'], $this->configuration['height'], $this->configuration['upscale'])) { + watchdog('image', 'Image scale failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + return FALSE; + } + return TRUE; + } + + /** + * {@inheritdoc} + */ + public function processDimensions(array &$dimensions) { + if ($dimensions['width'] && $dimensions['height']) { + Image::scaleDimensions($dimensions, $this->configuration['width'], $this->configuration['height'], $this->configuration['upscale']); + } + } + + /** + * {@inheritdoc} + */ + public function getSummary() { + return array( + '#theme' => 'image_scale_summary', + '#data' => $this->configuration, + ); + } + + /** + * {@inheritdoc} + */ + public function getForm() { + $form = parent::getForm(); + $form['#element_validate'] = array('image_effect_scale_validate'); + $form['width']['#required'] = FALSE; + $form['height']['#required'] = FALSE; + $form['upscale'] = array( + '#type' => 'checkbox', + '#default_value' => (isset($this->configuration['upscale'])) ? $this->configuration['upscale'] : 0, + '#title' => t('Allow Upscaling'), + '#description' => t('Let scale make images larger than their original size'), + ); + return $form; + } + +} diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php index 973a8ef..1f842a1 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php @@ -132,10 +132,10 @@ function testStyle() { $ieids = array(); foreach ($style->effects as $ieid => $effect) { // Store the ieid for later use. - $ieids[$effect['name']] = $ieid; + $ieids[$effect['id']] = $ieid; $this->drupalGet($style_path . '/effects/' . $ieid); - foreach ($effect_edits[$effect['name']] as $field => $value) { - $this->assertFieldByName($field, $value, format_string('The %field field in the %effect effect has the correct value of %value.', array('%field' => $field, '%effect' => $effect['name'], '%value' => $value))); + foreach ($effect_edits[$effect['id']] as $field => $value) { + $this->assertFieldByName($field, $value, format_string('The %field field in the %effect effect has the correct value of %value.', array('%field' => $field, '%effect' => $effect['id'], '%value' => $value))); } } @@ -157,7 +157,7 @@ function testStyle() { $effects_order = array_values($style->effects); $order_correct = TRUE; foreach ($effects_order as $index => $effect) { - if ($effect_edits_order[$index] != $effect['name']) { + if ($effect_edits_order[$index] != $effect['id']) { $order_correct = FALSE; } } @@ -203,7 +203,7 @@ function testStyle() { $effects_order = array_values($style->effects); $order_correct = TRUE; foreach ($effects_order as $index => $effect) { - if ($effect_edits_order[$index] != $effect['name']) { + if ($effect_edits_order[$index] != $effect['id']) { $order_correct = FALSE; } } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php index e7552d2..802690d 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php @@ -59,7 +59,7 @@ function testImageDimensions() { // Scale an image that is wider than it is high. $effect = array( - 'name' => 'image_scale', + 'id' => 'image_scale', 'data' => array( 'width' => 120, 'height' => 90, @@ -81,7 +81,7 @@ function testImageDimensions() { // Rotate 90 degrees anticlockwise. $effect = array( - 'name' => 'image_rotate', + 'id' => 'image_rotate', 'data' => array( 'degrees' => -90, 'random' => FALSE, @@ -102,7 +102,7 @@ function testImageDimensions() { // Scale an image that is higher than it is wide (rotated by previous effect). $effect = array( - 'name' => 'image_scale', + 'id' => 'image_scale', 'data' => array( 'width' => 120, 'height' => 90, @@ -124,7 +124,7 @@ function testImageDimensions() { // Test upscale disabled. $effect = array( - 'name' => 'image_scale', + 'id' => 'image_scale', 'data' => array( 'width' => 400, 'height' => 200, @@ -146,7 +146,7 @@ function testImageDimensions() { // Add a desaturate effect. $effect = array( - 'name' => 'image_desaturate', + 'id' => 'image_desaturate', 'data' => array(), 'weight' => 4, ); @@ -164,7 +164,7 @@ function testImageDimensions() { // Add a random rotate effect. $effect = array( - 'name' => 'image_rotate', + 'id' => 'image_rotate', 'data' => array( 'degrees' => 180, 'random' => TRUE, @@ -183,7 +183,7 @@ function testImageDimensions() { // Add a crop effect. $effect = array( - 'name' => 'image_crop', + 'id' => 'image_crop', 'data' => array( 'width' => 30, 'height' => 30, @@ -205,7 +205,7 @@ function testImageDimensions() { // Rotate to a non-multiple of 90 degrees. $effect = array( - 'name' => 'image_rotate', + 'id' => 'image_rotate', 'data' => array( 'degrees' => 57, 'random' => FALSE, @@ -226,7 +226,7 @@ function testImageDimensions() { // Ensure that an effect with no dimensions callback unsets the dimensions. // This ensures compatibility with 7.0 contrib modules. $effect = array( - 'name' => 'image_module_test_null', + 'id' => 'image_module_test_null', 'data' => array(), 'weight' => 8, ); diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php index 7f24796..4ec5fb5 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php @@ -22,6 +22,13 @@ class ImageEffectsTest extends ToolkitTestBase { */ public static $modules = array('image', 'image_test', 'image_module_test'); + /** + * The image effect manager. + * + * @var \Drupal\image\ImageEffectManager + */ + protected $manager; + public static function getInfo() { return array( 'name' => 'Image effects', @@ -30,17 +37,19 @@ public static function getInfo() { ); } - function setUp() { + public function setUp() { parent::setUp(); - - module_load_include('inc', 'image', 'image.effects'); + $this->manager = $this->container->get('plugin.manager.image.effect'); } /** * Test the image_resize_effect() function. */ function testResizeEffect() { - $this->assertTrue(image_resize_effect($this->image, array('width' => 1, 'height' => 2)), 'Function returned the expected value.'); + $this->assertImageEffect('image_resize', array( + 'width' => 1, + 'height' => 2, + )); $this->assertToolkitOperationsCalled(array('resize')); // Check the parameters. @@ -54,7 +63,10 @@ function testResizeEffect() { */ function testScaleEffect() { // @todo: need to test upscaling. - $this->assertTrue(image_scale_effect($this->image, array('width' => 10, 'height' => 10)), 'Function returned the expected value.'); + $this->assertImageEffect('image_scale', array( + 'width' => 10, + 'height' => 10, + )); $this->assertToolkitOperationsCalled(array('resize')); // Check the parameters. @@ -68,7 +80,11 @@ function testScaleEffect() { */ function testCropEffect() { // @todo should test the keyword offsets. - $this->assertTrue(image_crop_effect($this->image, array('anchor' => 'top-1', 'width' => 3, 'height' => 4)), 'Function returned the expected value.'); + $this->assertImageEffect('image_crop', array( + 'anchor' => 'top-1', + 'width' => 3, + 'height' => 4, + )); $this->assertToolkitOperationsCalled(array('crop')); // Check the parameters. @@ -83,7 +99,10 @@ function testCropEffect() { * Test the image_scale_and_crop_effect() function. */ function testScaleAndCropEffect() { - $this->assertTrue(image_scale_and_crop_effect($this->image, array('width' => 5, 'height' => 10)), 'Function returned the expected value.'); + $this->assertImageEffect('image_scale_and_crop', array( + 'width' => 5, + 'height' => 10, + )); $this->assertToolkitOperationsCalled(array('resize', 'crop')); // Check the parameters. @@ -98,7 +117,7 @@ function testScaleAndCropEffect() { * Test the image_desaturate_effect() function. */ function testDesaturateEffect() { - $this->assertTrue(image_desaturate_effect($this->image, array()), 'Function returned the expected value.'); + $this->assertImageEffect('image_desaturate', array()); $this->assertToolkitOperationsCalled(array('desaturate')); // Check the parameters. @@ -111,7 +130,10 @@ function testDesaturateEffect() { */ function testRotateEffect() { // @todo: need to test with 'random' => TRUE - $this->assertTrue(image_rotate_effect($this->image, array('degrees' => 90, 'bgcolor' => '#fff')), 'Function returned the expected value.'); + $this->assertImageEffect('image_rotate', array( + 'degrees' => 90, + 'bgcolor' => '#fff', + )); $this->assertToolkitOperationsCalled(array('rotate')); // Check the parameters. @@ -127,15 +149,35 @@ function testImageEffectsCaching() { $image_effect_definitions_called = &drupal_static('image_module_test_image_effect_info_alter'); // First call should grab a fresh copy of the data. - $effects = image_effect_definitions(); + $manager = $this->container->get('plugin.manager.image.effect'); + $effects = $manager->getDefinitions(); $this->assertTrue($image_effect_definitions_called === 1, 'image_effect_definitions() generated data.'); // Second call should come from cache. - drupal_static_reset('image_effect_definitions'); drupal_static_reset('image_module_test_image_effect_info_alter'); - $cached_effects = image_effect_definitions(); + $cached_effects = $manager->getDefinitions(); $this->assertTrue(is_null($image_effect_definitions_called), 'image_effect_definitions() returned data from cache.'); $this->assertTrue($effects == $cached_effects, 'Cached effects are the same as generated effects.'); } + + /** + * Asserts the effect processing of an image effect plugin. + * + * @param string $effect_name + * The name of the image effect to test. + * @param array $data + * The data to pass to the image effect. + * + * @return bool + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertImageEffect($effect_name, array $data) { + $effect = $this->manager->getInstance(array( + 'id' => $effect_name, + 'data' => $data, + )); + return $this->assertTrue($effect->processEffect($this->image), 'Function returned the expected value.'); + } + } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php index 3b9be9f..596816c 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php @@ -20,7 +20,6 @@ * image.module: * image_style_options() * image_style_flush() - * image_effect_definition_load() * image_effect_load() * image_effect_save() * image_effect_delete() diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageStyleFlushTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageStyleFlushTest.php index 298819a..08b4d28 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageStyleFlushTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageStyleFlushTest.php @@ -102,7 +102,7 @@ function testFlush() { $style_path = 'admin/config/media/image-styles/manage/' . $style->id(); $ieids = array(); foreach ($style->effects as $ieid => $effect) { - $ieids[$effect['name']] = $ieid; + $ieids[$effect['id']] = $ieid; } $this->drupalPost($style_path . '/effects/' . $ieids['image_scale'] . '/delete', array(), t('Delete')); $this->assertResponse(200); diff --git a/core/modules/image/tests/image_module_test.module b/core/modules/image/tests/image_module_test.module deleted file mode 100644 index 7cc6cdd..0000000 --- a/core/modules/image/tests/image_module_test.module +++ /dev/null @@ -1,51 +0,0 @@ -get('image.test_file_download') ?: FALSE; - if ($default_uri == $uri) { - return array('X-Image-Owned-By' => 'image_module_test'); - } -} - -/** - * Implements hook_image_effect_info(). - */ -function image_module_test_image_effect_info() { - $effects = array( - 'image_module_test_null' => array( - 'effect callback' => 'image_module_test_null_effect', - ), - ); - - return $effects; -} - -/** - * Image effect callback; Null. - * - * @param $image - * An image object returned by image_load(). - * @param $data - * An array with no attributes. - * - * @return - * TRUE - */ -function image_module_test_null_effect(array &$image, array $data) { - return TRUE; -} - -/** - * Implements hook_image_effect_info_alter(). - * - * Used to keep a count of cache misses in image_effect_definitions(). - */ -function image_module_test_image_effect_info_alter(&$effects) { - $image_effects_definition_called = &drupal_static(__FUNCTION__, 0); - $image_effects_definition_called++; -} diff --git a/core/modules/image/tests/image_module_test.info.yml b/core/modules/image/tests/modules/image_module_test/image_module_test.info.yml similarity index 100% rename from core/modules/image/tests/image_module_test.info.yml rename to core/modules/image/tests/modules/image_module_test/image_module_test.info.yml diff --git a/core/modules/image/tests/modules/image_module_test/image_module_test.module b/core/modules/image/tests/modules/image_module_test/image_module_test.module new file mode 100644 index 0000000..7d64d2c --- /dev/null +++ b/core/modules/image/tests/modules/image_module_test/image_module_test.module @@ -0,0 +1,23 @@ +get('image.test_file_download') ?: FALSE; + if ($default_uri == $uri) { + return array('X-Image-Owned-By' => 'image_module_test'); + } +} + +/** + * Implements hook_image_effect_info_alter(). + * + * Used to keep a count of cache misses in \Drupal\image\ImageEffectManager. + */ +function image_module_test_image_effect_info_alter(&$effects) { + $image_effects_definition_called = &drupal_static(__FUNCTION__, 0); + $image_effects_definition_called++; +} diff --git a/core/modules/image/tests/modules/image_module_test/lib/Drupal/image_module_test/Plugin/ImageEffect/NullTestImageEffect.php b/core/modules/image/tests/modules/image_module_test/lib/Drupal/image_module_test/Plugin/ImageEffect/NullTestImageEffect.php new file mode 100644 index 0000000..2550f56 --- /dev/null +++ b/core/modules/image/tests/modules/image_module_test/lib/Drupal/image_module_test/Plugin/ImageEffect/NullTestImageEffect.php @@ -0,0 +1,31 @@ + 'test-custom', 'effects' => array( 'image_rotate' => array( - 'name' => 'image_rotate', + 'id' => 'image_rotate', 'data' => array( 'degrees' => '90', 'bgcolor' => '#FFFFFF', @@ -47,7 +47,7 @@ public function testImageStyleUpgrade() { 'weight' => '1', ), 'image_desaturate' => array( - 'name' => 'image_desaturate', + 'id' => 'image_desaturate', 'data' => array(), 'weight' => '2', ), @@ -57,7 +57,7 @@ public function testImageStyleUpgrade() { 'name' => 'thumbnail', 'effects' => array ( 'image_scale' => array( - 'name' => 'image_scale', + 'id' => 'image_scale', 'data' => array ( 'width' => '177', 'height' => '177', @@ -73,11 +73,11 @@ public function testImageStyleUpgrade() { // during by the image style upgrade functions. foreach ($config->get('effects') as $uuid => $effect) { // Copy placeholder data. - $style['effects'][$uuid] = $style['effects'][$effect['name']]; + $style['effects'][$uuid] = $style['effects'][$effect['id']]; // Set the missing ieid key as this is unknown because it is a UUID. $style['effects'][$uuid]['ieid'] = $uuid; // Remove the placeholder data. - unset($style['effects'][$effect['name']]); + unset($style['effects'][$effect['id']]); } $this->assertEqual($this->sortByKey($style), $config->get(), format_string('@first is equal to @second.', array( '@first' => var_export($this->sortByKey($style), TRUE),