diff --git a/core/core.services.yml b/core/core.services.yml index 465d145..a02200e 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -512,6 +512,9 @@ services: image.toolkit.manager: class: Drupal\Core\ImageToolkit\ImageToolkitManager arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@config.factory'] + image.toolkit.operation.manager: + class: Drupal\Core\ImageToolkit\ImageToolkitOperationManager + arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@module_handler'] image.toolkit: class: Drupal\Core\ImageToolkit\ImageToolkitInterface factory_method: getDefaultToolkit diff --git a/core/lib/Drupal/Core/Image/Image.php b/core/lib/Drupal/Core/Image/Image.php index 963ed5b..3eea90a 100644 --- a/core/lib/Drupal/Core/Image/Image.php +++ b/core/lib/Drupal/Core/Image/Image.php @@ -8,7 +8,6 @@ namespace Drupal\Core\Image; use Drupal\Core\ImageToolkit\ImageToolkitInterface; -use Drupal\Component\Utility\Image as ImageUtility; /** * Defines an image object to represent an image file. @@ -286,71 +285,13 @@ protected function processInfo() { /** * {@inheritdoc} */ - public function scale($width = NULL, $height = NULL, $upscale = FALSE) { - $dimensions = array( - 'width' => $this->getWidth(), - 'height' => $this->getHeight(), - ); - - // Scale the dimensions - if they don't change then just return success. - if (!ImageUtility::scaleDimensions($dimensions, $width, $height, $upscale)) { - return TRUE; - } - - return $this->resize($dimensions['width'], $dimensions['height']); - - } - - /** - * {@inheritdoc} - */ - public function scaleAndCrop($width, $height) { - $scale = max($width / $this->getWidth(), $height / $this->getHeight()); - $x = ($this->getWidth() * $scale - $width) / 2; - $y = ($this->getHeight() * $scale - $height) / 2; - - if ($this->resize($this->getWidth() * $scale, $this->getHeight() * $scale)) { - return $this->crop($x, $y, $width, $height); - } - return FALSE; - } - - /** - * {@inheritdoc} - */ - public function crop($x, $y, $width, $height) { - $aspect = $this->getHeight() / $this->getWidth(); - if (empty($height)) $height = $width * $aspect; - if (empty($width)) $width = $height / $aspect; + public function apply($operation, array $data = array()) { + // @todo Operation arguments provided in $data will be sanitized here first, + // in https://drupal.org/node/2109375. + // @todo Operation arguments provided in $data will be prepared here first + // before deferring to toolkit, in https://drupal.org/node/2108307. - $width = (int) round($width); - $height = (int) round($height); - - return $this->toolkit->crop($this, $x, $y, $width, $height); - } - - /** - * {@inheritdoc} - */ - public function resize($width, $height) { - $width = (int) round($width); - $height = (int) round($height); - - return $this->toolkit->resize($this, $width, $height); - } - - /** - * {@inheritdoc} - */ - public function desaturate() { - return $this->toolkit->desaturate($this); - } - - /** - * {@inheritdoc} - */ - public function rotate($degrees, $background = NULL) { - return $this->toolkit->rotate($this, $degrees, $background); + return $this->toolkit->apply($operation, $this, $data); } /** diff --git a/core/lib/Drupal/Core/Image/ImageInterface.php b/core/lib/Drupal/Core/Image/ImageInterface.php index bba3460..bdef28e 100644 --- a/core/lib/Drupal/Core/Image/ImageInterface.php +++ b/core/lib/Drupal/Core/Image/ImageInterface.php @@ -2,7 +2,7 @@ /** * @file - * Contains Drupal\Core\Image\ImageInterface. + * Contains \Drupal\Core\Image\ImageInterface. */ namespace Drupal\Core\Image; @@ -144,6 +144,19 @@ public function getSource(); public function getToolkitId(); /** + * Applies a toolkit operation to the image. + * + * The call is deferred to the active toolkit appropriate method. + * + * @param string $operation + * The operation to be performed against the image. + * @param array $data + * An associative array with required arguments to be passed to the toolkit + * operation. E.g. array('width' => 50, 'height' => 100, 'upscale' => TRUE). + */ + public function apply($operation, array $data = array()); + + /** * Closes the image and saves the changes to a file. * * @param string|null $destination @@ -157,106 +170,4 @@ public function getToolkitId(); */ public function save($destination = NULL); - /** - * Scales an image while maintaining aspect ratio. - * - * The resulting image can be smaller for one or both target dimensions. - * - * @param int $width - * (optional) The target width, in pixels. This value is omitted then the - * scaling will based only on the height value. - * @param int $height - * (optional) The target height, in pixels. This value is omitted then the - * scaling will based only on the width value. - * @param bool $upscale - * (optional) Boolean indicating that files smaller than the dimensions will - * be scaled up. This generally results in a low quality image. - * - * @return bool - * TRUE on success, FALSE on failure. - */ - public function scale($width = NULL, $height = NULL, $upscale = FALSE); - - /** - * Scales an image to the exact width and height given. - * - * This function achieves the target aspect ratio by cropping the original image - * equally on both sides, or equally on the top and bottom. This function is - * useful to create uniform sized avatars from larger images. - * - * The resulting image always has the exact target dimensions. - * - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - */ - public function scaleAndCrop($width, $height); - - /** - * Crops an image to a rectangle specified by the given dimensions. - * - * @param int $x - * The top left coordinate, in pixels, of the crop area (x axis value). - * @param int $y - * The top left coordinate, in pixels, of the crop area (y axis value). - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\Core\ImageToolkit\ImageToolkitInterface::crop() - */ - public function crop($x, $y, $width, $height); - - /** - * Resizes an image to the given dimensions (ignoring aspect ratio). - * - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\Core\ImageToolkit\ImageToolkitInterface::resize() - */ - public function resize($width, $height); - - /** - * Converts an image to grayscale. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\Core\ImageToolkit\ImageToolkitInterface::desaturate() - */ - public function desaturate(); - - /** - * Rotates an image by the given number of degrees. - * - * @param int $degrees - * The number of (clockwise) degrees to rotate the image. - * @param string $background - * (optional) An hexadecimal integer specifying the background color to use - * for the uncovered area of the image after the rotation. E.g. 0x000000 for - * black, 0xff00ff for magenta, and 0xffffff for white. For images that - * support transparency, this will default to transparent. Otherwise it will - * be white. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see \Drupal\Core\ImageToolkit\ImageToolkitInterface::rotate() - */ - public function rotate($degrees, $background = NULL); - } diff --git a/core/lib/Drupal/Core/ImageToolkit/Annotation/ImageToolkitOperation.php b/core/lib/Drupal/Core/ImageToolkit/Annotation/ImageToolkitOperation.php new file mode 100644 index 0000000..1b1eb22 --- /dev/null +++ b/core/lib/Drupal/Core/ImageToolkit/Annotation/ImageToolkitOperation.php @@ -0,0 +1,70 @@ +getToolkitOperationPluginId($this->getPluginId(), $operation); + $plugin = $manager->createInstance($plugin_id, array(), $this); + return $plugin->apply($image, $data); + } + +} diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitInterface.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitInterface.php index 2b86aef..df014bf 100644 --- a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitInterface.php +++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitInterface.php @@ -60,78 +60,6 @@ public function settingsForm(); public function settingsFormSubmit($form, &$form_state); /** - * Scales an image to the specified size. - * - * @param \Drupal\Core\Image\ImageInterface $image - * An image object. The $image->resource, $image->info['width'], and - * $image->info['height'] values will be modified by this call. - * @param int $width - * The new width of the resized image, in pixels. - * @param int $height - * The new height of the resized image, in pixels. - * - * @return bool - * TRUE or FALSE, based on success. - */ - public function resize(ImageInterface $image, $width, $height); - - /** - * Rotates an image the given number of degrees. - * - * @param \Drupal\Core\Image\ImageInterface $image - * An image object. The $image->resource, $image->info['width'], and - * $image->info['height'] values will be modified by this call. - * @param int $degrees - * The number of (clockwise) degrees to rotate the image. - * @param string $background - * (optional) An hexadecimal integer specifying the background color to use - * for the uncovered area of the image after the rotation. E.g. 0x000000 for - * black, 0xff00ff for magenta, and 0xffffff for white. For images that - * support transparency, this will default to transparent. Otherwise it will - * be white. - * - * @return bool - * TRUE or FALSE, based on success. - */ - public function rotate(ImageInterface $image, $degrees, $background = NULL); - - /** - * Crops an image. - * - * @param \Drupal\Core\Image\ImageInterface $image - * An image object. The $image->resource, $image->info['width'], and - * $image->info['height'] values will be modified by this call. - * @param int $x - * The starting x offset at which to start the crop, in pixels. - * @param int $y - * The starting y offset at which to start the crop, in pixels. - * @param int $width - * The width of the cropped area, in pixels. - * @param int $height - * The height of the cropped area, in pixels. - * - * @return bool - * TRUE or FALSE, based on success. - * - * @see image_crop() - */ - public function crop(ImageInterface $image, $x, $y, $width, $height); - - /** - * Converts an image resource to grayscale. - * - * Note that transparent GIFs loose transparency when desaturated. - * - * @param \Drupal\Core\Image\ImageInterface $image - * An image object. The $image->resource value will be modified by this - * call. - * - * @return bool - * TRUE or FALSE, based on success. - */ - public function desaturate(ImageInterface $image); - - /** * Creates an image resource from a file. * * @param \Drupal\Core\Image\ImageInterface $image @@ -190,4 +118,20 @@ public static function isAvailable(); */ public static function supportedTypes(); + /** + * Applies a toolkit specific operation to an image. + * + * @param string $operation + * The toolkit operation to be processed. + * @param \Drupal\Core\Image\ImageInterface $image + * An image object. + * @param array $data + * An associative array with required arguments to be passed to the toolkit + * operation. E.g. array('width' => 50, 'height' => 100, 'upscale' => TRUE). + * + * @return mixed + * TRUE if the operation was performed successfully, FALSE otherwise. + */ + public function apply($operation, ImageInterface $image, array $data = array()); + } diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationBase.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationBase.php new file mode 100644 index 0000000..231b918 --- /dev/null +++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationBase.php @@ -0,0 +1,38 @@ +toolkit = $toolkit; + } + +} diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationInterface.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationInterface.php new file mode 100644 index 0000000..bcda387 --- /dev/null +++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationInterface.php @@ -0,0 +1,35 @@ +alterInfo($module_handler, 'image_toolkit_operation'); + $this->setCacheBackend($cache_backend, $language_manager, 'image_toolkit_operation'); + } + + /** + * Returns the plugin ID for the plugin for a given toolkit and operation. + * + * By convention, the id of an ImageToolkitOperation plugin must look like + * "{toolkit}.{operation}". + * + * @param string $toolkit + * The toolkit ID. + * @param string $operation + * The operation (e.g. "crop"). + * + * @return string + * The plugin ID. + */ + public function getToolkitOperationPluginId($toolkit, $operation) { + return "$toolkit.$operation"; + } + + /** + * {@inheritdoc} + */ + public function createInstance($plugin_id, array $configuration = array(), ImageToolkitInterface $toolkit = NULL) { + $plugin_definition = $this->getDefinition($plugin_id); + $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition); + return new $plugin_class($configuration, $plugin_id, $plugin_definition, $toolkit); + } + +} diff --git a/core/modules/file/file.module b/core/modules/file/file.module index bb0dd76..9c64761 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -462,7 +462,7 @@ function file_validate_image_resolution(File $file, $maximum_dimensions = 0, $mi // Try to resize the image to fit the dimensions. $image = $image_factory->get($file->getFileUri()); if ($image->getResource()) { - $image->scale($width, $height); + $image->apply('scale', array('width' => $width, 'height' => $height)); $image->save(); $file->filesize = $image->getFileSize(); drupal_set_message(t('The image was resized to fit within the maximum allowed dimensions of %dimensions pixels.', array('%dimensions' => $maximum_dimensions))); 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 39f58f3..7738f9c 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php @@ -29,7 +29,8 @@ public function applyEffect(ImageInterface $image) { list($x, $y) = explode('-', $this->configuration['anchor']); $x = image_filter_keyword($x, $image->getWidth(), $this->configuration['width']); $y = image_filter_keyword($y, $image->getHeight(), $this->configuration['height']); - if (!$image->crop($x, $y, $this->configuration['width'], $this->configuration['height'])) { + $data = array('x' => $x, 'y' => $y, 'width' => $this->configuration['width'], 'height' => $this->configuration['height']); + if (!$image->apply('crop', $data)) { watchdog('image', 'Image crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php index 912bec9..d45b9bc 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php @@ -33,7 +33,7 @@ public function transformDimensions(array &$dimensions) { * {@inheritdoc} */ public function applyEffect(ImageInterface $image) { - if (!$image->desaturate()) { + if (!$image->apply('desaturate')) { watchdog('image', 'Image desaturate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } 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 27d5538..91930ca 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php @@ -28,7 +28,8 @@ class ResizeImageEffect extends ImageEffectBase implements ConfigurableImageEffe * {@inheritdoc} */ public function applyEffect(ImageInterface $image) { - if (!$image->resize($this->configuration['width'], $this->configuration['height'])) { + $data = array('width' => $this->configuration['width'], 'height' => $this->configuration['height']); + if (!$image->apply('resize', $data)) { watchdog('image', 'Image resize failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } 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 23c0560..b66ec2f 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php @@ -47,7 +47,8 @@ public function applyEffect(ImageInterface $image) { $this->configuration['degrees'] = rand(-1 * $degrees, $degrees); } - if (!$image->rotate($this->configuration['degrees'], $this->configuration['bgcolor'])) { + $data = array('degrees' => $this->configuration['degrees'], 'background' => $this->configuration['bgcolor']); + if (!$image->apply('rotate', $data)) { watchdog('image', 'Image rotate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php index 39bd2ec..0073dbf 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php @@ -26,7 +26,8 @@ class ScaleAndCropImageEffect extends ResizeImageEffect { * {@inheritdoc} */ public function applyEffect(ImageInterface $image) { - if (!$image->scaleAndCrop($this->configuration['width'], $this->configuration['height'])) { + $data = array('width' => $this->configuration['width'], 'height' => $this->configuration['height']); + if (!$image->apply('scale_and_crop', $data)) { watchdog('image', 'Image scale and crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } 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 87b0dac..39a5a62 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php @@ -27,7 +27,8 @@ class ScaleImageEffect extends ResizeImageEffect { * {@inheritdoc} */ public function applyEffect(ImageInterface $image) { - if (!$image->scale($this->configuration['width'], $this->configuration['height'], $this->configuration['upscale'])) { + $data = array('width' => $this->configuration['width'], 'height' => $this->configuration['height'], 'upscale' => $this->configuration['upscale']); + if (!$image->apply('scale', $data)) { watchdog('image', 'Image scale failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php index 74f41ec..4c692fe 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php @@ -67,12 +67,12 @@ function testScaleEffect() { 'width' => 10, 'height' => 10, )); - $this->assertToolkitOperationsCalled(array('resize')); + $this->assertToolkitOperationsCalled(array('scale')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['resize'][0][1], 10, 'Width was passed correctly'); - $this->assertEqual($calls['resize'][0][2], 5, 'Height was based off aspect ratio and passed correctly'); + $this->assertEqual($calls['scale'][0][1], 10, 'Width was passed correctly'); + $this->assertEqual($calls['scale'][0][2], 10, 'Height was based off aspect ratio and passed correctly'); } /** @@ -103,14 +103,12 @@ function testScaleAndCropEffect() { 'width' => 5, 'height' => 10, )); - $this->assertToolkitOperationsCalled(array('resize', 'crop')); + $this->assertToolkitOperationsCalled(array('scale_and_crop')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['crop'][0][1], 7.5, 'X was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][2], 0, 'Y was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][3], 5, 'Width was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][4], 10, 'Height was computed and passed correctly'); + $this->assertEqual($calls['scale_and_crop'][0][1], 5, 'Width was computed and passed correctly'); + $this->assertEqual($calls['scale_and_crop'][0][2], 10, 'Height was computed and passed correctly'); } /** diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php index 737ad27..162220b 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php @@ -2,14 +2,13 @@ /** * @file - * Contains \Drupal\system\Plugin\ImageToolkit\GDToolkit;. + * Contains \Drupal\system\Plugin\ImageToolkit\GDToolkit. */ namespace Drupal\system\Plugin\ImageToolkit; -use Drupal\Core\Plugin\PluginBase; use Drupal\Core\Image\ImageInterface; -use Drupal\Core\ImageToolkit\ImageToolkitInterface; +use Drupal\Core\ImageToolkit\ImageToolkitBase; /** * Defines the GD2 toolkit for image manipulation within Drupal. @@ -19,7 +18,7 @@ * title = @Translation("GD2 image manipulation toolkit") * ) */ -class GDToolkit extends PluginBase implements ImageToolkitInterface { +class GDToolkit extends ImageToolkitBase { /** * {@inheritdoc} @@ -49,109 +48,6 @@ public function settingsFormSubmit($form, &$form_state) { /** * {@inheritdoc} */ - public function resize(ImageInterface $image, $width, $height) { - $res = $this->createTmp($image, $width, $height); - - if (!imagecopyresampled($res, $image->getResource(), 0, 0, 0, 0, $width, $height, $image->getWidth(), $image->getHeight())) { - return FALSE; - } - - imagedestroy($image->getResource()); - // Update image object. - $image - ->setResource($res) - ->setWidth($width) - ->setHeight($height); - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function rotate(ImageInterface $image, $degrees, $background = NULL) { - // PHP installations using non-bundled GD do not have imagerotate. - if (!function_exists('imagerotate')) { - watchdog('image', 'The image %file could not be rotated because the imagerotate() function is not available in this PHP installation.', array('%file' => $image->getSource())); - return FALSE; - } - - // Convert the hexadecimal background value to a color index value. - if (isset($background)) { - $rgb = array(); - for ($i = 16; $i >= 0; $i -= 8) { - $rgb[] = (($background >> $i) & 0xFF); - } - $background = imagecolorallocatealpha($image->getResource(), $rgb[0], $rgb[1], $rgb[2], 0); - } - // Set the background color as transparent if $background is NULL. - else { - // Get the current transparent color. - $background = imagecolortransparent($image->getResource()); - - // If no transparent colors, use white. - if ($background == 0) { - $background = imagecolorallocatealpha($image->getResource(), 255, 255, 255, 0); - } - } - - // Images are assigned a new color palette when rotating, removing any - // transparency flags. For GIF images, keep a record of the transparent color. - if ($image->getType() == IMAGETYPE_GIF) { - $transparent_index = imagecolortransparent($image->getResource()); - if ($transparent_index != 0) { - $transparent_gif_color = imagecolorsforindex($image->getResource(), $transparent_index); - } - } - - $image->setResource(imagerotate($image->getResource(), 360 - $degrees, $background)); - - // GIFs need to reassign the transparent color after performing the rotate. - if (isset($transparent_gif_color)) { - $background = imagecolorexactalpha($image->getResource(), $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']); - imagecolortransparent($image->getResource(), $background); - } - - $image - ->setWidth(imagesx($image->getResource())) - ->setHeight(imagesy($image->getResource())); - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function crop(ImageInterface $image, $x, $y, $width, $height) { - $res = $this->createTmp($image, $width, $height); - - if (!imagecopyresampled($res, $image->getResource(), 0, 0, $x, $y, $width, $height, $width, $height)) { - return FALSE; - } - - // Destroy the original image and return the modified image. - imagedestroy($image->getResource()); - $image - ->setResource($res) - ->setWidth($width) - ->setHeight($height); - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function desaturate(ImageInterface $image) { - // PHP installations using non-bundled GD do not have imagefilter. - if (!function_exists('imagefilter')) { - watchdog('image', 'The image %file could not be desaturated because the imagefilter() function is not available in this PHP installation.', array('%file' => $image->getSource())); - return FALSE; - } - - return imagefilter($image->getResource(), IMG_FILTER_GRAYSCALE); - } - - /** - * {@inheritdoc} - */ public function load(ImageInterface $image) { $function = 'imagecreatefrom' . image_type_to_extension($image->getType(), FALSE); if (function_exists($function) && $resource = $function($image->getSource())) { @@ -291,4 +187,5 @@ public static function isAvailable() { public static function supportedTypes() { return array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF); } + } diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDCrop.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDCrop.php new file mode 100644 index 0000000..0ebf982 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDCrop.php @@ -0,0 +1,45 @@ +toolkit->createTmp($image, $data['width'], $data['height']); + + if (!imagecopyresampled($res, $image->getResource(), 0, 0, $data['x'], $data['y'], $data['width'], $data['height'], $data['width'], $data['height'])) { + return FALSE; + } + + // Destroy the original image and return the modified image. + imagedestroy($image->getResource()); + $image + ->setResource($res) + ->setWidth($data['width']) + ->setHeight($data['height']); + return TRUE; + } + +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDDesaturate.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDDesaturate.php new file mode 100644 index 0000000..1b00f73 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDDesaturate.php @@ -0,0 +1,39 @@ + $image->getSource())); + return FALSE; + } + + return imagefilter($image->getResource(), IMG_FILTER_GRAYSCALE); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDResize.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDResize.php new file mode 100644 index 0000000..86a1f6c --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDResize.php @@ -0,0 +1,45 @@ +toolkit->createTmp($image, $data['width'], $data['height']); + + if (!imagecopyresampled($res, $image->getResource(), 0, 0, 0, 0, $data['width'], $data['height'], $image->getWidth(), $image->getHeight())) { + return FALSE; + } + + imagedestroy($image->getResource()); + // Update image object. + $image + ->setResource($res) + ->setWidth($data['width']) + ->setHeight($data['height']); + return TRUE; + } + +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDRotate.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDRotate.php new file mode 100644 index 0000000..cb32d13 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDRotate.php @@ -0,0 +1,81 @@ + $image->getSource())); + return FALSE; + } + + // Convert the hexadecimal background value to a color index value. + if (!empty($data['background'])) { + $rgb = array(); + for ($i = 16; $i >= 0; $i -= 8) { + $rgb[] = (($data['background'] >> $i) & 0xFF); + } + $data['background'] = imagecolorallocatealpha($image->getResource(), $rgb[0], $rgb[1], $rgb[2], 0); + } + // Set the background color as transparent if $data['background'] is NULL. + else { + // Get the current transparent color. + $data['background'] = imagecolortransparent($image->getResource()); + + // If no transparent colors, use white. + if ($data['background'] == 0) { + $data['background'] = imagecolorallocatealpha($image->getResource(), 255, 255, 255, 0); + } + } + + // Images are assigned a new color palette when rotating, removing any + // transparency flags. For GIF images, keep a record of the transparent color. + if ($image->getType() == IMAGETYPE_GIF) { + $transparent_index = imagecolortransparent($image->getResource()); + if ($transparent_index != 0) { + $transparent_gif_color = imagecolorsforindex($image->getResource(), $transparent_index); + } + } + + $image->setResource(imagerotate($image->getResource(), 360 - $data['degrees'], $data['background'])); + + // GIFs need to reassign the transparent color after performing the rotate. + if (isset($transparent_gif_color)) { + $data['background'] = imagecolorexactalpha($image->getResource(), $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']); + imagecolortransparent($image->getResource(), $data['background']); + } + + $image + ->setWidth(imagesx($image->getResource())) + ->setHeight(imagesy($image->getResource())); + return TRUE; + } + +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDScale.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDScale.php new file mode 100644 index 0000000..415b5bb --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDScale.php @@ -0,0 +1,47 @@ + NULL, 'height' => NULL, 'upscale' => FALSE); + $dimensions = array( + 'width' => $image->getWidth(), + 'height' => $image->getHeight(), + ); + // Scale the dimensions - if they don't change then just return success. + if (!ImageUtility::scaleDimensions($dimensions, $data['width'], $data['height'], $data['upscale'])) { + return TRUE; + } + $data['width'] = $dimensions['width']; + $data['height'] = $dimensions['height']; + + return parent::apply($image, $data); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDScaleAndCrop.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDScaleAndCrop.php new file mode 100644 index 0000000..9a7096c --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/GDScaleAndCrop.php @@ -0,0 +1,45 @@ +getWidth(); + $height = $image->getHeight(); + $scale = max($data['width'] / $width, $data['width'] / $height); + $data['x'] = ($width * $scale - $data['width']) / 2; + $data['y'] = ($height * $scale - $data['width']) / 2; + $width *= $scale; + $height *= $scale; + + if ($this->toolkit->apply('resize', $image, array('width' => $width, 'height' => $height))) { + return parent::apply($image, $data); + } + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php index 20005e6..3bd7e8a 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php @@ -111,49 +111,49 @@ function testManipulations() { $operations = array( 'resize' => array( 'function' => 'resize', - 'arguments' => array(20, 10), + 'arguments' => array('width' => 20, 'height' => 10), 'width' => 20, 'height' => 10, 'corners' => $default_corners, ), 'scale_x' => array( 'function' => 'scale', - 'arguments' => array(20, NULL), + 'arguments' => array('width' => 20), 'width' => 20, 'height' => 10, 'corners' => $default_corners, ), 'scale_y' => array( 'function' => 'scale', - 'arguments' => array(NULL, 10), + 'arguments' => array('height' => 10), 'width' => 20, 'height' => 10, 'corners' => $default_corners, ), 'upscale_x' => array( 'function' => 'scale', - 'arguments' => array(80, NULL, TRUE), + 'arguments' => array('width' => 80, 'upscale' => TRUE), 'width' => 80, 'height' => 40, 'corners' => $default_corners, ), 'upscale_y' => array( 'function' => 'scale', - 'arguments' => array(NULL, 40, TRUE), + 'arguments' => array('height' => 40, 'upscale' => TRUE), 'width' => 80, 'height' => 40, 'corners' => $default_corners, ), 'crop' => array( 'function' => 'crop', - 'arguments' => array(12, 4, 16, 12), + 'arguments' => array('x' => 12, 'y' => 4, 'width' => 16, 'height' => 12), 'width' => 16, 'height' => 12, 'corners' => array_fill(0, 4, $this->white), ), 'scale_and_crop' => array( - 'function' => 'scaleAndCrop', - 'arguments' => array(10, 8), + 'function' => 'scale_and_crop', + 'arguments' => array('width' => 10, 'height' => 8), 'width' => 10, 'height' => 8, 'corners' => array_fill(0, 4, $this->black), @@ -165,28 +165,28 @@ function testManipulations() { $operations += array( 'rotate_5' => array( 'function' => 'rotate', - 'arguments' => array(5, 0xFF00FF), // Fuchsia background. + 'arguments' => array('degrees' => 5, 'background' => 0xFF00FF), // Fuchsia background. 'width' => 42, 'height' => 24, 'corners' => array_fill(0, 4, $this->fuchsia), ), 'rotate_90' => array( 'function' => 'rotate', - 'arguments' => array(90, 0xFF00FF), // Fuchsia background. + 'arguments' => array('degrees' => 90, 'background' => 0xFF00FF), // Fuchsia background. 'width' => 20, 'height' => 40, 'corners' => array($this->transparent, $this->red, $this->green, $this->blue), ), 'rotate_transparent_5' => array( 'function' => 'rotate', - 'arguments' => array(5), + 'arguments' => array('degrees' => 5), 'width' => 42, 'height' => 24, 'corners' => array_fill(0, 4, $this->transparent), ), 'rotate_transparent_90' => array( 'function' => 'rotate', - 'arguments' => array(90), + 'arguments' => array('degrees' => 90), 'width' => 20, 'height' => 40, 'corners' => array($this->transparent, $this->red, $this->green, $this->blue), @@ -238,7 +238,7 @@ function testManipulations() { } // Perform our operation. - call_user_func_array(array($image, $values['function']), $values['arguments']); + $image->apply($values['function'], $values['arguments']); // To keep from flooding the test with assert values, make a general // value for whether each group of values fail. diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php index 0158249..c580421 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php @@ -53,7 +53,8 @@ function testSave() { * Test the image_resize() function. */ function testResize() { - $this->assertTrue($this->image->resize(1, 2), 'Function returned the expected value.'); + $data = array('width' => 1, 'height' => 2); + $this->assertTrue($this->image->apply('resize', $data), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('resize')); // Check the parameters. @@ -67,36 +68,37 @@ function testResize() { */ function testScale() { // TODO: need to test upscaling - $this->assertTrue($this->image->scale(10, 10), 'Function returned the expected value.'); - $this->assertToolkitOperationsCalled(array('resize')); + $data = array('width' => 10, 'height' => 10); + $this->assertTrue($this->image->apply('scale', $data), 'Function returned the expected value.'); + $this->assertToolkitOperationsCalled(array('scale')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['resize'][0][1], 10, 'Width was passed correctly'); - $this->assertEqual($calls['resize'][0][2], 5, 'Height was based off aspect ratio and passed correctly'); + $this->assertEqual($calls['scale'][0][1], 10, 'Width was passed correctly'); + $this->assertEqual($calls['scale'][0][2], 10, 'Height was based off aspect ratio and passed correctly'); } /** * Test the image_scale_and_crop() function. */ function testScaleAndCrop() { - $this->assertTrue($this->image->scaleAndCrop(5, 10), 'Function returned the expected value.'); - $this->assertToolkitOperationsCalled(array('resize', 'crop')); + $data = array('width' => 5, 'height' => 10); + $this->assertTrue($this->image->apply('scale_and_crop', $data), 'Function returned the expected value.'); + $this->assertToolkitOperationsCalled(array('scale_and_crop')); // Check the parameters. $calls = $this->imageTestGetAllCalls(); - $this->assertEqual($calls['crop'][0][1], 7.5, 'X was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][2], 0, 'Y was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][3], 5, 'Width was computed and passed correctly'); - $this->assertEqual($calls['crop'][0][4], 10, 'Height was computed and passed correctly'); + $this->assertEqual($calls['scale_and_crop'][0][1], 5, 'Width was computed and passed correctly'); + $this->assertEqual($calls['scale_and_crop'][0][2], 10, 'Height was computed and passed correctly'); } /** * Test the image_rotate() function. */ function testRotate() { - $this->assertTrue($this->image->rotate(90, 1), 'Function returned the expected value.'); + $data = array('degrees' => 90, 'background' => 1); + $this->assertTrue($this->image->apply('rotate', $data), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('rotate')); // Check the parameters. @@ -109,7 +111,8 @@ function testRotate() { * Test the image_crop() function. */ function testCrop() { - $this->assertTrue($this->image->crop(1, 2, 3, 4), 'Function returned the expected value.'); + $data = array('x' => 1, 'y' => 2, 'width' => 3, 'height' => 4); + $this->assertTrue($this->image->apply('crop', $data), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('crop')); // Check the parameters. @@ -124,7 +127,7 @@ function testCrop() { * Test the image_desaturate() function. */ function testDesaturate() { - $this->assertTrue($this->image->desaturate(), 'Function returned the expected value.'); + $this->assertTrue($this->image->apply('desaturate'), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('desaturate')); // Check the parameters. diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php index 74caee4..6340c5e 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php @@ -118,6 +118,8 @@ function imageTestReset() { 'rotate' => array(), 'crop' => array(), 'desaturate' => array(), + 'scale' => array(), + 'scale_and_crop' => array(), ); \Drupal::state()->set('image_test.results', $results); } diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestCrop.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestCrop.php new file mode 100644 index 0000000..e1af3b7 --- /dev/null +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestCrop.php @@ -0,0 +1,34 @@ +toolkit->logCall('crop', array($image, $data['x'], $data['y'], $data['width'], $data['height'])); + return TRUE; + } + +} diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestDesaturate.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestDesaturate.php new file mode 100644 index 0000000..109a4f6 --- /dev/null +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestDesaturate.php @@ -0,0 +1,34 @@ +toolkit->logCall('desaturate', array($image)); + return TRUE; + } + +} diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestResize.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestResize.php new file mode 100644 index 0000000..e7bed43 --- /dev/null +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestResize.php @@ -0,0 +1,34 @@ +toolkit->logCall('resize', array($image, $data['width'], $data['height'])); + return TRUE; + } + +} diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestRotate.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestRotate.php new file mode 100644 index 0000000..2af823b --- /dev/null +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestRotate.php @@ -0,0 +1,36 @@ +toolkit->logCall('rotate', array($image, $data['degrees'], $data['background'])); + return TRUE; + } + +} diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestScale.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestScale.php new file mode 100644 index 0000000..ab5c3ac --- /dev/null +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestScale.php @@ -0,0 +1,34 @@ + NULL, 'height' => NULL, 'upscale' => FALSE); + $this->toolkit->logCall('scale', array($image, $data['width'], $data['height'], $data['upscale'])); + return TRUE; + } + +} diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestScaleAndCrop.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestScaleAndCrop.php new file mode 100644 index 0000000..2a7885a --- /dev/null +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/TestScaleAndCrop.php @@ -0,0 +1,33 @@ +toolkit->logCall('scale_and_crop', array($image, $data['width'], $data['height'])); + return TRUE; + } + +} diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php index 43800617..884621a 100644 --- a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php @@ -7,9 +7,8 @@ namespace Drupal\image_test\Plugin\ImageToolkit; -use Drupal\Core\Plugin\PluginBase; use Drupal\Core\Image\ImageInterface; -use Drupal\Core\ImageToolkit\ImageToolkitInterface; +use Drupal\Core\ImageToolkit\ImageToolkitBase; /** * Defines a Test toolkit for image manipulation within Drupal. @@ -19,7 +18,7 @@ * title = @Translation("A dummy toolkit that works") * ) */ -class TestToolkit extends PluginBase implements ImageToolkitInterface { +class TestToolkit extends ImageToolkitBase { /** * {@inheritdoc} @@ -74,38 +73,6 @@ public function save(ImageInterface $image, $destination) { } /** - * {@inheritdoc} - */ - public function crop(ImageInterface $image, $x, $y, $width, $height) { - $this->logCall('crop', array($image, $x, $y, $width, $height)); - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function resize(ImageInterface $image, $width, $height) { - $this->logCall('resize', array($image, $width, $height)); - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function rotate(ImageInterface $image, $degrees, $background = NULL) { - $this->logCall('rotate', array($image, $degrees, $background)); - return TRUE; - } - - /** - * {@inheritdoc} - */ - public function desaturate(ImageInterface $image) { - $this->logCall('desaturate', array($image)); - return TRUE; - } - - /** * Stores the values passed to a toolkit call. * * @param string $op @@ -117,7 +84,7 @@ public function desaturate(ImageInterface $image) { * @see \Drupal\system\Tests\Image\ToolkitTestBase::imageTestReset() * @see \Drupal\system\Tests\Image\ToolkitTestBase::imageTestGetAllCalls() */ - protected function logCall($op, $args) { + public function logCall($op, $args) { $results = \Drupal::state()->get('image_test.results') ?: array(); $results[$op][] = $args; \Drupal::state()->set('image_test.results', $results); diff --git a/core/tests/Drupal/Tests/Core/Image/ImageTest.php b/core/tests/Drupal/Tests/Core/Image/ImageTest.php index d2a5b61..1ee3000 100644 --- a/core/tests/Drupal/Tests/Core/Image/ImageTest.php +++ b/core/tests/Drupal/Tests/Core/Image/ImageTest.php @@ -16,6 +16,13 @@ class ImageTest extends UnitTestCase { /** + * Image source path. + * + * @var string + */ + protected $source; + + /** * Image object. * * @var \Drupal\Core\Image\Image @@ -39,10 +46,8 @@ public static function getInfo() { protected function setUp() { // Use the Druplicon image. - $source = __DIR__ . '/../../../../../misc/druplicon.png'; - $this->toolkit = $this->getMockBuilder('Drupal\system\Plugin\ImageToolkit\GDToolkit') - ->disableOriginalConstructor() - ->getMock(); + $this->source = __DIR__ . '/../../../../../misc/druplicon.png'; + $this->toolkit = $this->getToolkitMock(); $this->toolkit->expects($this->any()) ->method('getPluginId') @@ -58,7 +63,25 @@ protected function setUp() { 'mime_type' => 'image/png', ))); - $this->image = new Image($source, $this->toolkit); + $this->image = new Image($this->source, $this->toolkit); + } + + /** + * Mocks a toolkit. + * + * @param array $stubs + * (optional) Array containing methods to be replaced with stubs. + * + * @return PHPUnit_Framework_MockObject_MockObject + */ + protected function getToolkitMock(array $stubs = array()) { + $mock_builder = $this->getMockBuilder('\Drupal\system\Plugin\ImageToolkit\GDToolkit'); + if ($stubs && is_array($stubs)) { + $mock_builder->setMethods($stubs); + } + return $mock_builder + ->disableOriginalConstructor() + ->getMock(); } /** @@ -154,9 +177,9 @@ public function testSetSource() { } /** - * Tests \Drupal\Core\Image\Image::getToolkitId(). + * Tests \Drupal\Core\Image\Image::getToolkit(). */ - public function testGetToolkitId() { + public function testGetToolkit() { $this->assertEquals($this->image->getToolkitId(), 'gd'); } @@ -169,7 +192,7 @@ public function testSave() { ->method('save') ->will($this->returnValue(TRUE)); - $image = $this->getMock('Drupal\Core\Image\Image', array('chmod'), array($this->image->getSource(), $this->toolkit)); + $image = $this->getMock('\Drupal\Core\Image\Image', array('chmod'), array($this->image->getSource(), $this->toolkit)); $image->expects($this->any()) ->method('chmod') ->will($this->returnValue(TRUE)); @@ -198,7 +221,7 @@ public function testChmodFails() { ->method('save') ->will($this->returnValue(TRUE)); - $image = $this->getMock('Drupal\Core\Image\Image', array('chmod'), array($this->image->getSource(), $this->toolkit)); + $image = $this->getMock('\Drupal\Core\Image\Image', array('chmod'), array($this->image->getSource(), $this->toolkit)); $image->expects($this->any()) ->method('chmod') ->will($this->returnValue(FALSE)); @@ -215,143 +238,38 @@ public function testProcessInfoFails() { } /** - * Tests \Drupal\Core\Image\Image::scale(). - */ - public function testScaleWidth() { - $this->toolkit->expects($this->once()) - ->method('resize') - ->will($this->returnArgument(2)); - $height = $this->image->scale(44); - $this->assertEquals($height, 50); - } - - /** - * Tests \Drupal\Core\Image\Image::scale(). - */ - public function testScaleHeight() { - $this->toolkit->expects($this->once()) - ->method('resize') - ->will($this->returnArgument(1)); - - $width = $this->image->scale(NULL, 50); - $this->assertEquals($width, 44); - } - - /** - * Tests \Drupal\Core\Image\Image::scale(). - */ - public function testScaleSame() { - // Dimensions are the same, resize should not be called. - $this->toolkit->expects($this->never()) - ->method('resize') - ->will($this->returnArgument(1)); - - $width = $this->image->scale(88, 100); - $this->assertEquals($width, 88); - } - - /** - * Tests \Drupal\Core\Image\Image::scaleAndCrop(). - */ - public function testScaleAndCropWidth() { - $this->toolkit->expects($this->once()) - ->method('resize') - ->will($this->returnValue(TRUE)); - - $this->toolkit->expects($this->once()) - ->method('crop') - ->will($this->returnArgument(1)); - - $x = $this->image->scaleAndCrop(34, 50); - $this->assertEquals($x, 5); - } - - /** - * Tests \Drupal\Core\Image\Image::scaleAndCrop(). - */ - public function testScaleAndCropHeight() { - $this->toolkit->expects($this->once()) - ->method('resize') - ->will($this->returnValue(TRUE)); - - $this->toolkit->expects($this->once()) - ->method('crop') - ->will($this->returnArgument(2)); - - $y = $this->image->scaleAndCrop(44, 40); - $this->assertEquals($y, 5); - } - - /** - * Tests \Drupal\Core\Image\Image::scaleAndCrop(). - */ - public function testScaleAndCropFails() { - $this->toolkit->expects($this->once()) - ->method('resize') - ->will($this->returnValue(FALSE)); - - $this->toolkit->expects($this->never()) - ->method('crop'); - $this->image->scaleAndCrop(44, 40); - } - - /** - * Tests \Drupal\Core\Image\Image::crop(). - */ - public function testCropWidth() { - $this->toolkit->expects($this->once()) - ->method('crop') - ->will($this->returnArgument(4)); - // Cropping with width only should preserve the aspect ratio. - $height = $this->image->crop(0, 0, 44, NULL); - $this->assertEquals($height, 50); - } - - /** - * Tests \Drupal\Core\Image\Image::crop(). - */ - public function testCropHeight() { - $this->toolkit->expects($this->once()) - ->method('crop') - ->will($this->returnArgument(3)); - // Cropping with height only should preserve the aspect ratio. - $width = $this->image->crop(0, 0, NULL, 50); - $this->assertEquals($width, 44); - } - - /** - * Tests \Drupal\Core\Image\Image::crop(). - */ - public function testCrop() { - $this->toolkit->expects($this->once()) - ->method('crop') - ->will($this->returnArgument(3)); - $width = $this->image->crop(0, 0, 44, 50); - $this->assertEquals($width, 44); - } - - /** - * Tests \Drupal\Core\Image\Image::resize(). + * Note for reviewers and core committers. + * + * Next unit tests were dedicated for image geometry conversions (like + * dimensions, coordinates, etc). Because of architectural changes in issues + * https://drupal.org/node/2103635 and https://drupal.org/node/2073759 they + * have lost their scope and were temporary removed: + * - testScaleWidth() + * - testScaleHeight() + * - testScaleSame() + * - testScaleAndCropWidth() + * - testScaleAndCropHeight() + * - testScaleAndCropFails() + * - testCropWidth() + * - testCropHeight() + * - testCrop() + * - testResize() + * + * Those tests will be added back when implementing the dedicated + * functionality from https://drupal.org/node/2108307. + * + * @todo Re-add tests for dimensions and coordinates computing when + * implementing this functionality in https://drupal.org/node/2108307. */ - public function testResize() { - $this->toolkit->expects($this->exactly(2)) - ->method('resize') - ->will($this->returnArgument(1)); - // Resize with integer for width and height. - $this->image->resize(30, 40); - // Pass a float for width. - $width = $this->image->resize(30.4, 40); - // Ensure that the float was rounded to an integer first. - $this->assertEquals($width, 30); - } /** * Tests \Drupal\Core\Image\Image::desaturate(). */ public function testDesaturate() { $this->toolkit->expects($this->once()) - ->method('desaturate'); - $this->image->desaturate(); + ->method('apply') + ->with($this->equalTo('desaturate')); + $this->image->apply('desaturate'); } /** @@ -359,8 +277,9 @@ public function testDesaturate() { */ public function testRotate() { $this->toolkit->expects($this->once()) - ->method('rotate'); - $this->image->rotate(90); + ->method('apply') + ->with($this->equalTo('rotate')); + $this->image->apply('rotate', array('degrees' => 90)); } }