diff --git a/core/core.services.yml b/core/core.services.yml
index 43c6104..efffebf 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -620,7 +620,10 @@ services:
- { name: event_subscriber }
image.toolkit.manager:
class: Drupal\Core\ImageToolkit\ImageToolkitManager
- arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@config.factory', '@module_handler']
+ arguments: ['@container.namespaces', '@cache.cache', '@language_manager', '@config.factory', '@module_handler', '@image.toolkit.operation.manager']
+ image.toolkit.operation.manager:
+ class: Drupal\Core\ImageToolkit\ImageToolkitOperationManager
+ parent: default_plugin_manager
image.factory:
class: Drupal\Core\Image\ImageFactory
arguments: ['@image.toolkit.manager']
diff --git a/core/lib/Drupal/Core/Image/Image.php b/core/lib/Drupal/Core/Image/Image.php
index f7a5cd7..deff4b5 100644
--- a/core/lib/Drupal/Core/Image/Image.php
+++ b/core/lib/Drupal/Core/Image/Image.php
@@ -266,39 +266,10 @@ protected function processInfo() {
}
/**
- * Passes through calls that represent image toolkit operations onto the
- * image toolkit.
- *
- * This is a temporary solution to keep patches reviewable. The __call()
- * method will be replaced in https://drupal.org/node/2110499 with a new
- * interface method ImageInterface::apply(). An image operation will be
- * performed as in the next example:
- * @code
- * $image = new Image($path, $toolkit);
- * $image->apply('scale', array('width' => 50, 'height' => 100));
- * @endcode
- * Also in https://drupal.org/node/2110499 operation arguments sent to toolkit
- * will be moved to a keyed array, unifying the interface of toolkit
- * operations.
- *
- * @todo Drop this in https://drupal.org/node/2110499 in favor of new apply().
+ * {@inheritdoc}
*/
- public function __call($method, $arguments) {
- // @todo Temporary to avoid that legacy GD setResource(), getResource(),
- // hasResource() methods moved to GD toolkit in #2103621 get invoked
- // from this class anyway through the magic __call. Will be removed
- // through https://drupal.org/node/2110499, when call_user_func_array()
- // will be replaced by $this->toolkit->apply($name, $this, $arguments).
- if (in_array($method, array('setResource', 'getResource', 'hasResource'))) {
- throw new \BadMethodCallException();
- }
- if (is_callable(array($this->toolkit, $method))) {
- // @todo In https://drupal.org/node/2110499, call_user_func_array() will
- // be replaced by $this->toolkit->apply($name, $this, $arguments).
- array_unshift($arguments, $this);
- return call_user_func_array(array($this->toolkit, $method), $arguments);
- }
- throw new \BadMethodCallException();
+ public function apply($operation, array $arguments = array()) {
+ return $this->toolkit->apply($operation, $this, $arguments);
}
/**
diff --git a/core/lib/Drupal/Core/Image/ImageInterface.php b/core/lib/Drupal/Core/Image/ImageInterface.php
index b6edda0..eb01474 100644
--- a/core/lib/Drupal/Core/Image/ImageInterface.php
+++ b/core/lib/Drupal/Core/Image/ImageInterface.php
@@ -133,6 +133,22 @@ public function getToolkit();
public function getToolkitId();
/**
+ * Applies a toolkit operation to the image.
+ *
+ * The operation is deferred to the active toolkit.
+ *
+ * @param string $operation
+ * The operation to be performed against the image.
+ * @param array $arguments
+ * An associative array with required arguments to be passed to the toolkit
+ * operation. E.g. array('width' => 50, 'height' => 100, 'upscale' => TRUE).
+ *
+ * @return bool
+ * TRUE on success, FALSE on failure.
+ */
+ public function apply($operation, array $arguments = array());
+
+ /**
* Closes the image and saves the changes to a file.
*
* @param string|null $destination
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..0db12e8
--- /dev/null
+++ b/core/lib/Drupal/Core/ImageToolkit/Annotation/ImageToolkitOperation.php
@@ -0,0 +1,78 @@
+operationManager = $operation_manager;
+ }
+
+ /**
* {@inheritdoc}
*/
public function getRequirements() {
return array();
}
+ /**
+ * Return a toolkit operation plugin instance.
+ *
+ * @param string $operation
+ * The toolkit operation requested.
+ *
+ * @return \Drupal\Core\ImageToolkit\ImageToolkitOperationInterface
+ * An instance of the requested toolkit operation plugin.
+ */
+ protected function getToolkitOperation($operation) {
+ $plugin_id = $this->operationManager->getToolkitOperationPluginId($this->getPluginId(), $operation);
+ return $this->operationManager->createInstance($plugin_id, array(), $this);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function apply($operation, ImageInterface $image, array $arguments = array()) {
+ $plugin = $this->getToolkitOperation($operation);
+
+ // Validate and prepare arguments before applying the operation. The
+ // operation might be cancelled if prepare() decides that the final image
+ // will not change.
+ if ($plugin->prepare($image, $arguments) !== FALSE) {
+ return $plugin->apply($image, $arguments);
+ }
+
+ // No operation is required because the target image will be the same as the
+ // original but the result is still successful.
+ return TRUE;
+ }
+
}
diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitInterface.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitInterface.php
index 61c6ece..7926302 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);
-
- /**
* Writes an image resource to a destination file.
*
* @param \Drupal\Core\Image\ImageInterface $image
@@ -145,49 +73,6 @@ public function desaturate(ImageInterface $image);
public function save(ImageInterface $image, $destination);
/**
- * Scales an image while maintaining aspect ratio.
- *
- * The resulting image can be smaller for one or both target dimensions.
- *
- * @param \Drupal\Core\Image\ImageInterface $image
- * An image object.
- * @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(ImageInterface $image, $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 \Drupal\Core\Image\ImageInterface $image
- * An image object.
- * @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(ImageInterface $image, $width, $height);
-
- /**
* Gets details about an image.
*
* @param \Drupal\Core\Image\ImageInterface $image
@@ -236,4 +121,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 $arguments
+ * 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 $arguments = array());
+
}
diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php
index e503558..4671042 100644
--- a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php
+++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitManager.php
@@ -10,8 +10,10 @@
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\ImageToolkit\ImageToolkitOperationManagerInterface;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Plugin\DefaultPluginManager;
+use Drupal\Component\Plugin\Factory\DefaultFactory;
/**
* Manages toolkit plugins.
@@ -26,6 +28,13 @@ class ImageToolkitManager extends DefaultPluginManager {
protected $configFactory;
/**
+ * The image toolkit operation manager.
+ *
+ * @var \Drupal\Core\ImageToolkit\ImageToolkitOperationManagerInterface
+ */
+ protected $operationManager;
+
+ /**
* Constructs the ImageToolkitManager object.
*
* @param \Traversable $namespaces
@@ -39,12 +48,15 @@ class ImageToolkitManager extends DefaultPluginManager {
* The config factory.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
+ * @param \Drupal\Core\ImageToolkit\ImageToolkitOperationManagerInterface $operation_manager
+ * The toolkit operation manager.
*/
- public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler) {
+ public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, LanguageManager $language_manager, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, ImageToolkitOperationManagerInterface $operation_manager) {
parent::__construct('Plugin/ImageToolkit', $namespaces, $module_handler, 'Drupal\Core\ImageToolkit\Annotation\ImageToolkit');
$this->setCacheBackend($cache_backend, $language_manager, 'image_toolkit_plugins');
$this->configFactory = $config_factory;
+ $this->operationManager = $operation_manager;
}
/**
@@ -100,4 +112,14 @@ public function getAvailableToolkits() {
return $output;
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createInstance($plugin_id, array $configuration = array()) {
+ $plugin_definition = $this->getDefinition($plugin_id);
+ $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
+ return new $plugin_class($configuration, $plugin_id, $plugin_definition, $this->operationManager);
+ }
+
}
diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationBase.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationBase.php
new file mode 100644
index 0000000..4786b7e
--- /dev/null
+++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationBase.php
@@ -0,0 +1,105 @@
+toolkit = $toolkit;
+ }
+
+ /**
+ * Validates and normalizes arguments.
+ *
+ * @param array $arguments
+ * An associative array of arguments to be used by the toolkit operation.
+ *
+ * @throws \InvalidArgumentException.
+ */
+ protected function validateArguments(array $arguments) {
+ $manager = \Drupal::typedDataManager();
+
+ // Get arguments definition.
+ $definition = $this->getPluginDefinition()['arguments'];
+
+ foreach ($definition as $id => $argument) {
+
+ // The defined argument has been provided.
+ if (array_key_exists($id, $arguments)) {
+ $data_definition = DataDefinition::create($argument['type']);
+ $typed_data = $manager->create($data_definition, $arguments[$id]);
+ $violations = $typed_data->validate();
+
+ // There are violations against defined TypedData.
+ if ($violations->count()) {
+ $fail = TRUE;
+
+ // One more try: Check if casted value passes.
+ if (method_exists($typed_data, 'getCastedValue')) {
+ $casted = $typed_data->getCastedValue();
+ $typed_data->setValue($casted);
+ $fail = (bool) $typed_data->validate()->count();
+ }
+
+ if ($fail) {
+ $message_arguments = array('@value' => $arguments[$id], '@plugin' => $this->getPluginId(), '@arg' => $id, '@type' => $argument['type']);
+ $message = String::format("The value '@value' provided to '@plugin' plugin in '@arg' argument cannot be casted as '@type'.", $message_arguments);
+ throw new \InvalidArgumentException($message);
+ }
+ }
+ }
+ // A defined argument hasn't been passed.
+ else {
+ if ($argument['required']) {
+ // If the argument is required throw an exception.
+ $message = String::format("Argument '@arg' expected by plugin '@plugin' but not passed.", array('@arg' => $id, '@plugin' => $this->getPluginId()));
+ throw new \InvalidArgumentException($message);
+ }
+ else {
+ // Optional argument? Assign the default value.
+ $arguments[$id] = $argument['default'];
+ }
+ }
+ }
+
+ return $arguments;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prepare(ImageInterface $image, array &$arguments) {
+ $arguments = $this->validateArguments($arguments);
+ }
+
+}
diff --git a/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationInterface.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationInterface.php
new file mode 100644
index 0000000..e0b9714
--- /dev/null
+++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationInterface.php
@@ -0,0 +1,52 @@
+alterInfo('image_toolkit_operation');
+ $this->setCacheBackend($cache_backend, $language_manager, 'image_toolkit_operation_plugins');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function processDefinition(&$definition, $plugin_id) {
+ parent::processDefinition($definition, $plugin_id);
+
+ // Get the toolkit ID from the image operation plugin class namespace. Each
+ // plugin is placed under Plugin\ImageToolkit\{plugin_id}.
+ $path = explode('\\', $definition['class']);
+ $definition['toolkit'] = $path[count($path) - 2];
+
+ foreach ($definition['arguments'] as $id => &$argument) {
+ // Set argument 'required' as TRUE if hasn't been specified in annotation.
+ $argument['required'] = isset($argument['required']) ? $argument['required'] : TRUE;
+
+ // If the argument is optional a 'default' should be provided.
+ if (!$argument['required'] && !array_key_exists('default', $argument)) {
+ $message = String::format("Argument '@arg' in plugin '@plugin' is optional but doesn't provide a default value.", array('@arg' => $id, '@plugin' => $definition['id']));
+ throw new PluginException($message);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getToolkitOperationPluginId($toolkit, $operation) {
+ $definitions = $this->getDefinitions();
+
+ $definitions = array_filter($definitions,
+ function ($definition) use ($toolkit, $operation) {
+ return $definition['toolkit'] == $toolkit && $definition['operation'] == $operation;
+ }
+ );
+
+ if (!$definitions) {
+ $message = String::format("No image operation plugin for '@toolkit' toolkit and '@operation' operation.", array('@toolkit' => $toolkit, '@operation' => $operation));
+ throw new UnknownPluginException('', $message);
+ }
+ else {
+ // Pickup the first plugin found.
+ // @todo In https://drupal.org/node/2110591 we'll return here the UI
+ // selected plugin or the first found if missed.
+ $definition = reset($definitions);
+ return $definition['id'];
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createInstance($plugin_id, array $configuration = array(), ImageToolkitInterface $toolkit = NULL, TypedDataManager $typed_data_manager = 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/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManagerInterface.php b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManagerInterface.php
new file mode 100644
index 0000000..57f5a14
--- /dev/null
+++ b/core/lib/Drupal/Core/ImageToolkit/ImageToolkitOperationManagerInterface.php
@@ -0,0 +1,30 @@
+get($file->getFileUri());
if ($image->isExisting()) {
- $image->scale($width, $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)));
+ if ($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)));
+ }
+ else {
+ $errors[] = t('The image exceeds the maximum allowed dimensions and an attempt to resize it failed.');
+ }
}
else {
$errors[] = t('The image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => $maximum_dimensions));
diff --git a/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
index 398860c..6f9847e 100644
--- a/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php
@@ -91,6 +91,13 @@ function testFileValidateImageResolution() {
$this->assertTrue($image->getWidth() <= 10, 'Image scaled to correct width.', 'File');
$this->assertTrue($image->getHeight() <= 5, 'Image scaled to correct height.', 'File');
+ // Once again, now with negative width and height to force an error.
+ copy('core/misc/druplicon.png', 'temporary://druplicon.png');
+ $this->image->setFileUri('temporary://druplicon.png');
+
+ $errors = file_validate_image_resolution($this->image, '-10x-5');
+ $this->assertEqual(count($errors), 1, 'An error reported for an oversized image that can not be scaled down.', 'File');
+
drupal_unlink('temporary://druplicon.png');
}
else {
diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php
index 8b1857b..40cd0de 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php
@@ -27,7 +27,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 4d899c6..62311f3 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php
@@ -31,7 +31,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 da9b176..6c02ee1 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php
@@ -26,7 +26,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 b0e6bf3..d14d260 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php
@@ -45,7 +45,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 7fed9b1..4aa77f4 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php
@@ -24,7 +24,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 4316bd0..a8b0565 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php
@@ -25,7 +25,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 8afcb22..4c692fe 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageEffectsTest.php
@@ -103,12 +103,12 @@ function testScaleAndCropEffect() {
'width' => 5,
'height' => 10,
));
- $this->assertToolkitOperationsCalled(array('scaleAndCrop'));
+ $this->assertToolkitOperationsCalled(array('scale_and_crop'));
// Check the parameters.
$calls = $this->imageTestGetAllCalls();
- $this->assertEqual($calls['scaleAndCrop'][0][1], 5, 'Width was computed and passed correctly');
- $this->assertEqual($calls['scaleAndCrop'][0][2], 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 1bd1d36..742bbec 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\Image\ImageInterface;
use Drupal\Core\ImageToolkit\ImageToolkitBase;
-use Drupal\Component\Utility\Image as ImageUtility;
/**
* Defines the GD2 toolkit for image manipulation within Drupal.
@@ -78,158 +77,6 @@ public function settingsFormSubmit($form, &$form_state) {
}
/**
- * {@inheritdoc}
- */
- public function resize(ImageInterface $image, $width, $height) {
- // @todo Dimensions computation will be moved into a dedicated functionality
- // in https://drupal.org/node/2108307.
- $width = (int) round($width);
- $height = (int) round($height);
-
- $res = $this->createTmp($image->getType(), $width, $height);
-
- if (!imagecopyresampled($res, $this->getResource(), 0, 0, 0, 0, $width, $height, $image->getWidth(), $image->getHeight())) {
- return FALSE;
- }
-
- imagedestroy($this->getResource());
- // Update image object.
- $this->setResource($res);
- $image
- ->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($this->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($this->getResource());
-
- // If no transparent colors, use white.
- if ($background == 0) {
- $background = imagecolorallocatealpha($this->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($this->getResource());
- if ($transparent_index != 0) {
- $transparent_gif_color = imagecolorsforindex($this->getResource(), $transparent_index);
- }
- }
-
- $this->setResource(imagerotate($this->getResource(), 360 - $degrees, $background));
-
- // GIFs need to reassign the transparent color after performing the rotate.
- if (isset($transparent_gif_color)) {
- $background = imagecolorexactalpha($this->getResource(), $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']);
- imagecolortransparent($this->getResource(), $background);
- }
-
- $image
- ->setWidth(imagesx($this->getResource()))
- ->setHeight(imagesy($this->getResource()));
- return TRUE;
- }
-
- /**
- * {@inheritdoc}
- */
- public function crop(ImageInterface $image, $x, $y, $width, $height) {
- // @todo Dimensions computation will be moved into a dedicated functionality
- // in https://drupal.org/node/2108307.
- $aspect = $image->getHeight() / $image->getWidth();
- $height = empty($height) ? $width * $aspect : $height;
- $width = empty($width) ? $height / $aspect : $width;
- $width = (int) round($width);
- $height = (int) round($height);
-
- $res = $this->createTmp($image->getType(), $width, $height);
-
- if (!imagecopyresampled($res, $this->getResource(), 0, 0, $x, $y, $width, $height, $width, $height)) {
- return FALSE;
- }
-
- // Destroy the original image and return the modified image.
- imagedestroy($this->getResource());
- $this->setResource($res);
- $image
- ->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($this->getResource(), IMG_FILTER_GRAYSCALE);
- }
-
- /**
- * {@inheritdoc}
- */
- public function scale(ImageInterface $image, $width = NULL, $height = NULL, $upscale = FALSE) {
- // @todo Dimensions computation will be moved into a dedicated functionality
- // in https://drupal.org/node/2108307.
- $dimensions = array(
- 'width' => $image->getWidth(),
- 'height' => $image->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($image, $dimensions['width'], $dimensions['height']);
- }
-
- /**
- * {@inheritdoc}
- */
- public function scaleAndCrop(ImageInterface $image, $width, $height) {
- // @todo Dimensions computation will be moved into a dedicated functionality
- // in https://drupal.org/node/2108307.
- $scale = max($width / $image->getWidth(), $height / $image->getHeight());
- $x = ($image->getWidth() * $scale - $width) / 2;
- $y = ($image->getHeight() * $scale - $height) / 2;
-
- if ($this->resize($image, $image->getWidth() * $scale, $image->getHeight() * $scale)) {
- return $this->crop($image, $x, $y, $width, $height);
- }
-
- return FALSE;
- }
-
- /**
* Creates a resource from a file.
*
* @param string $source
diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Crop.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Crop.php
new file mode 100644
index 0000000..fa03ecf
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Crop.php
@@ -0,0 +1,79 @@
+getHeight() / $image->getWidth();
+ $arguments['height'] = empty($arguments['height']) ? $arguments['width'] * $aspect : $arguments['height'];
+ $arguments['width'] = empty($arguments['width']) ? $arguments['height'] / $aspect : $arguments['width'];
+
+ // Assure integers for all arguments.
+ foreach (array('x', 'y', 'width', 'height') as $key) {
+ $arguments[$key] = (int) round($arguments[$key]);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function apply(ImageInterface $image, array $arguments = array()) {
+ $res = $this->toolkit->createTmp($image->getType(), $arguments['width'], $arguments['height']);
+
+ if (!imagecopyresampled($res, $image->getToolkit()->getResource(), 0, 0, $arguments['x'], $arguments['y'], $arguments['width'], $arguments['height'], $arguments['width'], $arguments['height'])) {
+ return FALSE;
+ }
+
+ // Destroy the original image and return the modified image.
+ imagedestroy($image->getToolkit()->getResource());
+ $image->getToolkit()->setResource($res);
+ $image
+ ->setWidth($arguments['width'])
+ ->setHeight($arguments['height']);
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Desaturate.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Desaturate.php
new file mode 100644
index 0000000..4a51a6e
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Desaturate.php
@@ -0,0 +1,39 @@
+ $image->getSource()));
+ return FALSE;
+ }
+
+ return imagefilter($image->getToolkit()->getResource(), IMG_FILTER_GRAYSCALE);
+ }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Resize.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Resize.php
new file mode 100644
index 0000000..663e4e3
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Resize.php
@@ -0,0 +1,70 @@
+toolkit->createTmp($image->getType(), $arguments['width'], $arguments['height']);
+
+ if (!imagecopyresampled($res, $image->getToolkit()->getResource(), 0, 0, 0, 0, $arguments['width'], $arguments['height'], $image->getWidth(), $image->getHeight())) {
+ return FALSE;
+ }
+
+ imagedestroy($image->getToolkit()->getResource());
+ // Update image object.
+ $image->getToolkit()->setResource($res);
+ $image
+ ->setWidth($arguments['width'])
+ ->setHeight($arguments['height']);
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Rotate.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Rotate.php
new file mode 100644
index 0000000..b90e4f2
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Rotate.php
@@ -0,0 +1,89 @@
+ $image->getSource()));
+ return FALSE;
+ }
+
+ // Convert the hexadecimal background value to a color index value.
+ if (!empty($arguments['background'])) {
+ $rgb = array();
+ for ($i = 16; $i >= 0; $i -= 8) {
+ $rgb[] = (($arguments['background'] >> $i) & 0xFF);
+ }
+ $arguments['background'] = imagecolorallocatealpha($image->getToolkit()->getResource(), $rgb[0], $rgb[1], $rgb[2], 0);
+ }
+ // Set background color as transparent if $arguments['background'] is NULL.
+ else {
+ // Get the current transparent color.
+ $arguments['background'] = imagecolortransparent($image->getToolkit()->getResource());
+
+ // If no transparent colors, use white.
+ if ($arguments['background'] == 0) {
+ $arguments['background'] = imagecolorallocatealpha($image->getToolkit()->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->getToolkit()->getResource());
+ if ($transparent_index != 0) {
+ $transparent_gif_color = imagecolorsforindex($image->getToolkit()->getResource(), $transparent_index);
+ }
+ }
+
+ $image->getToolkit()->setResource(imagerotate($image->getToolkit()->getResource(), 360 - $arguments['degrees'], $arguments['background']));
+
+ // GIFs need to reassign the transparent color after performing the rotate.
+ if (isset($transparent_gif_color)) {
+ $arguments['background'] = imagecolorexactalpha($image->getToolkit()->getResource(), $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']);
+ imagecolortransparent($image->getToolkit()->getResource(), $arguments['background']);
+ }
+
+ $image
+ ->setWidth(imagesx($image->getToolkit()->getResource()))
+ ->setHeight(imagesy($image->getToolkit()->getResource()));
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Scale.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Scale.php
new file mode 100644
index 0000000..fe414b1
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/Scale.php
@@ -0,0 +1,80 @@
+ $this->getPluginId()));
+ throw new \InvalidArgumentException($message);
+ }
+
+ // Calculate one of the dimensions from the other target dimension,
+ // ensuring the same aspect ratio as the source dimensions. If one of the
+ // target dimensions is missing, that is the one that is calculated. If both
+ // are specified then the dimension calculated is the one that would not be
+ // calculated to be bigger than its target.
+ $scale = $image->getHeight() / $image->getWidth();
+ if (($width && !$height) || ($width && $height && $scale < $height / $width)) {
+ $height = (int) round($width * $scale);
+ }
+ else {
+ $width = (int) round($height / $scale);
+ }
+
+ // Call parent validation
+ parent::prepare($image, $arguments);
+
+ // Don't upscale if the option isn't enabled.
+ if (!$arguments['upscale'] && ($width >= $image->getWidth() || $height >= $image->getHeight())) {
+ return FALSE;
+ }
+ }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/ScaleAndCrop.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/ScaleAndCrop.php
new file mode 100644
index 0000000..7ce04e9
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/Operation/gd/ScaleAndCrop.php
@@ -0,0 +1,65 @@
+getWidth();
+ $height = $image->getHeight();
+
+ $scale = max($arguments['width'] / $width, $arguments['height'] / $height);
+
+ $arguments['x'] = (int) round(($width * $scale - $arguments['width']) / 2);
+ $arguments['y'] = (int) round(($height * $scale - $arguments['height']) / 2);
+ $arguments['resize'] = array(
+ 'width' => (int) round($width * $scale),
+ 'height' => (int) round($height * $scale),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function apply(ImageInterface $image, array $arguments = array()) {
+ if ($this->toolkit->apply('resize', $image, $arguments['resize'])) {
+ return $this->toolkit->apply('crop', $image, $arguments);
+ }
+
+ return FALSE;
+ }
+
+}
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 d683b70..aca8b08 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php
@@ -107,49 +107,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),
@@ -161,28 +161,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),
@@ -234,7 +234,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 34376ba..ab98be1 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,7 +68,8 @@ function testResize() {
*/
function testScale() {
// TODO: need to test upscaling
- $this->assertTrue($this->image->scale(10, 10), 'Function returned the expected value.');
+ $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.
@@ -80,21 +82,23 @@ function testScale() {
* Test the image_scale_and_crop() function.
*/
function testScaleAndCrop() {
- $this->assertTrue($this->image->scaleAndCrop(5, 10), 'Function returned the expected value.');
- $this->assertToolkitOperationsCalled(array('scaleAndCrop'));
+ $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['scaleAndCrop'][0][1], 5, 'Width was computed and passed correctly');
- $this->assertEqual($calls['scaleAndCrop'][0][2], 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.
@@ -107,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.
@@ -122,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 5c89169..61a0268 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php
@@ -108,6 +108,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/test/Crop.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Crop.php
new file mode 100644
index 0000000..6e87309
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Crop.php
@@ -0,0 +1,51 @@
+toolkit->logCall('crop', array($image, $arguments['x'], $arguments['y'], $arguments['width'], $arguments['height']));
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Desaturate.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Desaturate.php
new file mode 100644
index 0000000..e101965
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Desaturate.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/test/Resize.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Resize.php
new file mode 100644
index 0000000..4c56480
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Resize.php
@@ -0,0 +1,43 @@
+toolkit->logCall('resize', array($image, $arguments['width'], $arguments['height']));
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Rotate.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Rotate.php
new file mode 100644
index 0000000..e2fb41a
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Rotate.php
@@ -0,0 +1,45 @@
+toolkit->logCall('rotate', array($image, $arguments['degrees'], $arguments['background']));
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Scale.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Scale.php
new file mode 100644
index 0000000..f6cd0c1
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/Scale.php
@@ -0,0 +1,52 @@
+toolkit->logCall('scale', array($image, $arguments['width'], $arguments['height'], $arguments['upscale']));
+ return TRUE;
+ }
+
+}
diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/ScaleAndCrop.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/ScaleAndCrop.php
new file mode 100644
index 0000000..f0c9a6c
--- /dev/null
+++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/Operation/test/ScaleAndCrop.php
@@ -0,0 +1,42 @@
+toolkit->logCall('scale_and_crop', array($image, $arguments['width'], $arguments['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 d85d813..56c3f49 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
@@ -96,54 +96,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;
- }
-
- /**
- * {@inheritdoc}
- */
- public function scale(ImageInterface $image, $width = NULL, $height = NULL, $upscale = FALSE) {
- $this->logCall('scale', array($image, $width, $height, $upscale));
- return TRUE;
- }
-
- /**
- * {@inheritdoc}
- */
- public function scaleAndCrop(ImageInterface $image, $width, $height) {
- $this->logCall('scaleAndCrop', array($image, $width, $height));
- return TRUE;
- }
-
- /**
* Stores the values passed to a toolkit call.
*
* @param string $op
@@ -155,7 +107,7 @@ public function scaleAndCrop(ImageInterface $image, $width, $height) {
* @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 d2c5fd7..367f7d9 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
@@ -23,12 +30,22 @@ class ImageTest extends UnitTestCase {
protected $image;
/**
- * Image toolkit.
+ * Mocked image toolkit.
*
* @var \Drupal\Core\ImageToolkit\ImageToolkitInterface
*/
protected $toolkit;
+ /**
+ * Mocked image toolkit operation.
+ *
+ * @var \Drupal\Core\ImageToolkit\ImageToolkitOperationInterface
+ */
+ protected $toolkitOperation;
+
+ /**
+ * @inheritdoc
+ */
public static function getInfo() {
return array(
'name' => 'Image class functionality',
@@ -37,9 +54,55 @@ public static function getInfo() {
);
}
+ /**
+ * @inheritdoc
+ */
protected function setUp() {
// Use the Druplicon image.
$this->source = __DIR__ . '/../../../../../misc/druplicon.png';
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * Mocks a toolkit operation.
+ *
+ * @param string $class_name
+ * The name of the GD toolkit operation class to be mocked.
+ *
+ * @return PHPUnit_Framework_MockObject_MockObject
+ */
+ protected function getToolkitOperationMock($class_name) {
+ $mock_builder = $this->getMockBuilder('Drupal\\system\\Plugin\\ImageToolkit\\Operation\\gd\\' . $class_name);
+ return $mock_builder
+ ->setMethods(array('apply', 'validateArguments'))
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ /**
+ * Get an image with a mocked toolkit, for testing.
+ *
+ * @param array $stubs
+ * (optional) Array containing toolkit methods to be replaced with stubs.
+ */
+ protected function getTestImage(array $stubs = array()) {
$this->toolkit = $this->getToolkitMock();
$this->toolkit->expects($this->any())
@@ -60,87 +123,113 @@ protected function setUp() {
}
/**
- * Mocks a toolkit.
- *
- * @param array $stubs
- * (optional) Array containing methods to be replaced with stubs.
+ * Get an image with mocked toolkit and operation, for operation testing.
*
- * @return PHPUnit_Framework_MockObject_MockObject
+ * @param string $class_name
+ * The name of the GD toolkit operation class to be mocked.
*/
- 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();
+ protected function getTestImageForOperation($class_name) {
+ $this->toolkit = $this->getToolkitMock(array('getToolkitOperation', 'getPluginId', 'getInfo'));
+ $this->toolkitOperation = $this->getToolkitOperationMock($class_name);
+
+ $this->toolkit->expects($this->any())
+ ->method('getPluginId')
+ ->will($this->returnValue('gd'));
+
+ $this->toolkit->expects($this->any())
+ ->method('getInfo')
+ ->will($this->returnValue(array(
+ 'width' => 88,
+ 'height' => 100,
+ 'extension' => 'png',
+ 'type' => IMAGETYPE_PNG,
+ 'mime_type' => 'image/png',
+ )));
+
+ $this->toolkit->expects($this->any())
+ ->method('getToolkitOperation')
+ ->will($this->returnValue($this->toolkitOperation));
+
+ $this->toolkitOperation->expects($this->any())
+ ->method('validateArguments')
+ ->will($this->returnArgument(0));
+
+ $this->image = new Image($this->source, $this->toolkit);
}
/**
* Tests \Drupal\Core\Image\Image::getExtension().
*/
public function testGetExtension() {
- $this->assertEquals($this->image->getExtension(), 'png');
+ $this->getTestImage();
+ $this->assertEquals('png', $this->image->getExtension());
}
/**
* Tests \Drupal\Core\Image\Image::getHeight().
*/
public function testGetHeight() {
- $this->assertEquals($this->image->getHeight(), 100);
+ $this->getTestImage();
+ $this->assertEquals(100, $this->image->getHeight());
}
/**
* Tests \Drupal\Core\Image\Image::setHeight().
*/
public function testSetHeight() {
+ $this->getTestImage();
$this->image->getHeight();
$this->image->setHeight(400);
- $this->assertEquals($this->image->getHeight(), 400);
+ $this->assertEquals(400, $this->image->getHeight());
}
/**
* Tests \Drupal\Core\Image\Image::getWidth().
*/
public function testGetWidth() {
- $this->assertEquals($this->image->getWidth(), 88);
+ $this->getTestImage();
+ $this->assertEquals(88, $this->image->getWidth());
}
/**
* Tests \Drupal\Core\Image\Image::setWidth().
*/
public function testSetWidth() {
+ $this->getTestImage();
$this->image->getHeight();
$this->image->setWidth(337);
- $this->assertEquals($this->image->getWidth(), 337);
+ $this->assertEquals(337, $this->image->getWidth());
}
/**
* Tests \Drupal\Core\Image\Image::getFileSize
*/
public function testGetFileSize() {
- $this->assertEquals($this->image->getFileSize(), 3905);
+ $this->getTestImage();
+ $this->assertEquals(3905, $this->image->getFileSize());
}
/**
* Tests \Drupal\Core\Image\Image::getType().
*/
public function testGetType() {
- $this->assertEquals($this->image->getType(), IMAGETYPE_PNG);
+ $this->getTestImage();
+ $this->assertEquals(IMAGETYPE_PNG, $this->image->getType());
}
/**
* Tests \Drupal\Core\Image\Image::getMimeType().
*/
public function testGetMimeType() {
- $this->assertEquals($this->image->getMimeType(), 'image/png');
+ $this->getTestImage();
+ $this->assertEquals('image/png', $this->image->getMimeType());
}
/**
* Tests \Drupal\Core\Image\Image::isExisting().
*/
public function testIsExisting() {
+ $this->getTestImage();
$this->assertTrue($this->image->isExisting());
$this->assertTrue(is_readable($this->image->getSource()));
}
@@ -149,22 +238,25 @@ public function testIsExisting() {
* Tests \Drupal\Core\Image\Image::setSource().
*/
public function testSetSource() {
+ $this->getTestImage();
$source = __DIR__ . '/../../../../../misc/grippie.png';
$this->image->setSource($source);
- $this->assertEquals($this->image->getSource(), $source);
+ $this->assertEquals($source, $this->image->getSource());
}
/**
* Tests \Drupal\Core\Image\Image::getToolkitId().
*/
public function testGetToolkitId() {
- $this->assertEquals($this->image->getToolkitId(), 'gd');
+ $this->getTestImage();
+ $this->assertEquals('gd', $this->image->getToolkitId());
}
/**
* Tests \Drupal\Core\Image\Image::save().
*/
public function testSave() {
+ $this->getTestImage();
// This will fail if save() method isn't called on the toolkit.
$this->toolkit->expects($this->once())
->method('save')
@@ -182,6 +274,7 @@ public function testSave() {
* Tests \Drupal\Core\Image\Image::save().
*/
public function testSaveFails() {
+ $this->getTestImage();
// This will fail if save() method isn't called on the toolkit.
$this->toolkit->expects($this->once())
->method('save')
@@ -194,6 +287,7 @@ public function testSaveFails() {
* Tests \Drupal\Core\Image\Image::save().
*/
public function testChmodFails() {
+ $this->getTestImage();
// This will fail if save() method isn't called on the toolkit.
$this->toolkit->expects($this->once())
->method('save')
@@ -211,6 +305,7 @@ public function testChmodFails() {
* Tests \Drupal\Core\Image\Image::save().
*/
public function testProcessInfoFails() {
+ $this->getTestImage();
$this->image->setSource('magic-foobars.png');
$this->assertFalse((bool) $this->image->getWidth());
}
@@ -219,157 +314,176 @@ public function testProcessInfoFails() {
* Tests \Drupal\Core\Image\Image::scale().
*/
public function testScaleWidth() {
- $toolkit = $this->getToolkitMock(array('resize'));
- $image = new Image($this->source, $toolkit);
+ $this->getTestImageForOperation('Scale');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
- $toolkit->expects($this->any())
- ->method('resize')
- ->will($this->returnArgument(2));
- $height = $image->scale(44);
- $this->assertEquals($height, 50);
+ $ret = $this->image->apply('scale', array('width' => 44, 'upscale' => FALSE));
+ $this->assertEquals(50, $ret['height']);
}
/**
* Tests \Drupal\Core\Image\Image::scale().
*/
public function testScaleHeight() {
- $toolkit = $this->getToolkitMock(array('resize'));
- $image = new Image($this->source, $toolkit);
-
- $toolkit->expects($this->any())
- ->method('resize')
+ $this->getTestImageForOperation('Scale');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
->will($this->returnArgument(1));
- $width = $image->scale(NULL, 50);
- $this->assertEquals($width, 44);
+
+ $ret = $this->image->apply('scale', array('height' => 50, 'upscale' => FALSE));
+ $this->assertEquals(44, $ret['width']);
}
/**
* Tests \Drupal\Core\Image\Image::scale().
*/
public function testScaleSame() {
- $toolkit = $this->getToolkitMock(array('resize'));
- $image = new Image($this->source, $toolkit);
-
+ $this->getTestImageForOperation('Scale');
// Dimensions are the same, resize should not be called.
- $toolkit->expects($this->never())
- ->method('resize')
- ->will($this->returnArgument(1));
+ $this->toolkitOperation->expects($this->never())
+ ->method('apply');
- $width = $image->scale(88, 100);
- $this->assertEquals($width, 88);
+ $ret = $this->image->apply('scale', array ('width' => 88, 'height' => 100, 'upscale' => FALSE));
}
/**
* Tests \Drupal\Core\Image\Image::scaleAndCrop().
*/
public function testScaleAndCropWidth() {
- $toolkit = $this->getToolkitMock(array('resize', 'crop'));
- $image = new Image($this->source, $toolkit);
-
- $toolkit->expects($this->once())
- ->method('resize')
- ->will($this->returnValue(TRUE));
-
- $toolkit->expects($this->once())
- ->method('crop')
+ $this->getTestImageForOperation('ScaleAndCrop');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
->will($this->returnArgument(1));
- $x = $image->scaleAndCrop(34, 50);
- $this->assertEquals($x, 5);
+ $ret = $this->image->apply('scale_and_crop', array ('width' => 34, 'height' => 50, 'upscale' => FALSE));
+ $this->assertEquals(5, $ret['x']);
}
/**
* Tests \Drupal\Core\Image\Image::scaleAndCrop().
*/
public function testScaleAndCropHeight() {
- $toolkit = $this->getToolkitMock(array('resize', 'crop'));
- $image = new Image($this->source, $toolkit);
-
- $toolkit->expects($this->once())
- ->method('resize')
- ->will($this->returnValue(TRUE));
-
- $toolkit->expects($this->once())
- ->method('crop')
- ->will($this->returnArgument(2));
+ $this->getTestImageForOperation('ScaleAndCrop');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
- $y = $image->scaleAndCrop(44, 40);
- $this->assertEquals($y, 5);
+ $ret = $this->image->apply('scale_and_crop', array ('width' => 44, 'height' => 40));
+ $this->assertEquals(5, $ret['y']);
}
/**
* Tests \Drupal\Core\Image\Image::scaleAndCrop().
*/
public function testScaleAndCropFails() {
- $toolkit = $this->getToolkitMock(array('resize', 'crop'));
- $image = new Image($this->source, $toolkit);
-
- $toolkit->expects($this->once())
- ->method('resize')
- ->will($this->returnValue(FALSE));
+ $this->getTestImageForOperation('ScaleAndCrop');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
- $toolkit->expects($this->never())
- ->method('crop');
- $image->scaleAndCrop(44, 40);
+ $ret = $this->image->apply('scale_and_crop', array('width' => 44, 'height' => 40));
+ $this->assertEquals(0, $ret['x']);
+ $this->assertEquals(5, $ret['y']);
+ $this->assertEquals(44, $ret['resize']['width']);
+ $this->assertEquals(50, $ret['resize']['height']);
}
/**
* Tests \Drupal\Core\Image\Image::crop().
- *
- * @todo Because \Drupal\Tests\Core\Image\ImageTest::testCropWidth() tests
- * image geometry conversions (like dimensions, coordinates, etc) and has
- * lost its scope in https://drupal.org/node/2103635, it was temporarily
- * removed. The test will be added back when implementing the dedicated
- * functionality from https://drupal.org/node/2108307.
*/
+ public function testCropWidth() {
+ $this->getTestImageForOperation('Crop');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
+
+ // Cropping with width only should preserve the aspect ratio.
+ $ret = $this->image->apply('crop', array ('x' => 0, 'y' => 0, 'width' => 44));
+ $this->assertEquals(50, $ret['height']);
+ }
/**
* Tests \Drupal\Core\Image\Image::crop().
- *
- * @todo Because \Drupal\Tests\Core\Image\ImageTest::testCropHeight() tests
- * image geometry conversions (like dimensions, coordinates, etc) and has
- * lost its scope in https://drupal.org/node/2103635, it was temporarily
- * removed. The test will be added back when implementing the dedicated
- * functionality from https://drupal.org/node/2108307.
*/
+ public function testCropHeight() {
+ $this->getTestImageForOperation('Crop');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
+
+ // Cropping with height only should preserve the aspect ratio.
+ $ret = $this->image->apply('crop', array ('x' => 0, 'y' => 0, 'height' => 50));
+ $this->assertEquals(44, $ret['width']);
+ }
/**
* 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);
+ $this->getTestImageForOperation('Crop');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
+
+ $ret = $this->image->apply('crop', array ('x' => 0, 'y' => 0, 'width' => 44, 'height' => 50));
+ $this->assertEquals(44, $ret['width']);
+ }
+
+ /**
+ * Tests \Drupal\Core\Image\Image::resize().
+ */
+ public function testResize() {
+ $this->getTestImageForOperation('Resize');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
+
+ // Resize with integer for width and height.
+ $ret = $this->image->apply('resize', array('width' => 30, 'height' => 40));
+ $this->assertEquals(30, $ret['width']);
+ $this->assertEquals(40, $ret['height']);
}
/**
* Tests \Drupal\Core\Image\Image::resize().
- *
- * @todo Because \Drupal\Tests\Core\Image\ImageTest::testResize() tests image
- * geometry conversions (like dimensions, coordinates, etc) and has lost its
- * scope in https://drupal.org/node/2103635, it was temporarily removed. The
- * test will be added back when implementing the dedicated functionality
- * from https://drupal.org/node/2108307.
*/
+ public function testFloatResize() {
+ $this->getTestImageForOperation('Resize');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
+
+ // Pass a float for width.
+ $ret = $this->image->apply('resize', array('width' => 30.4, 'height' => 40));
+ // Ensure that the float was rounded to an integer first.
+ $this->assertEquals(30, $ret['width']);
+ }
/**
* Tests \Drupal\Core\Image\Image::desaturate().
*/
public function testDesaturate() {
- $this->toolkit->expects($this->once())
- ->method('desaturate');
- $this->image->desaturate();
+ $this->getTestImageForOperation('Desaturate');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
+
+ $this->image->apply('desaturate');
}
/**
* Tests \Drupal\Core\Image\Image::rotate().
*/
public function testRotate() {
- $this->toolkit->expects($this->once())
- ->method('rotate');
- $this->image->rotate(90);
+ $this->getTestImageForOperation('Rotate');
+ $this->toolkitOperation->expects($this->once())
+ ->method('apply')
+ ->will($this->returnArgument(1));
+
+ $ret = $this->image->apply('rotate', array('degrees' => 90));
+ $this->assertEquals(90, $ret['degrees']);
}
}
diff --git a/sites/simpletest/.htaccess b/sites/simpletest/.htaccess
new file mode 100644
index 0000000..7051eb8
--- /dev/null
+++ b/sites/simpletest/.htaccess
@@ -0,0 +1,15 @@
+# Turn off all options we don't need.
+Options None
+Options +FollowSymLinks
+
+# Set the catch-all handler to prevent scripts from being executed.
+SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+
+ # Override the handler again if we're run later in the evaluation list.
+ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
+
+
+# If we know how to do it safely, disable the PHP engine entirely.
+
+ php_flag engine off
+
\ No newline at end of file