Permalink
Browse files

feature(iconservice): it is possible to save unaltered version of an …

…image

The EntityIconService now saves an unaltered version (no cropping or resizing)
of the image if the configuration for the image size is an empty array. This
makes it possible to always have access to a high quality version of the image.

Fixes #9970
  • Loading branch information...
juho-jaakkola committed Jul 11, 2016
1 parent 45b2da7 commit 7157a33f647a937191c6961d960b4e76d325edd4
View
@@ -410,7 +410,38 @@ Other
``entity_subtype`` will be passed with the ``$params`` array to the callback.
**entity:<icon_type>:sizes, <entity_type>**
- Allows filtering sizes for custom icon types, see ``entity:icon:sizes, <entity_type>``
+ Allows filtering sizes for custom icon types, see ``entity:icon:sizes, <entity_type>``.
+
+ The hook must return an associative array where keys are the names of the icon sizes
+ (e.g. "large"), and the values are arrays with the following keys:
+
+ * ``w`` - Width of the image in pixels
+ * ``h`` - Height of the image in pixels
+ * ``square`` - Should the aspect ratio be a square (true/false)
+ * ``upscale`` - Should the image be upscaled in case it is smaller than the given
+ width and height (true/false)
+
+ If the configuration array for an image size is empty, the image will be
+ saved as an exact copy of the source without resizing or cropping.
+
+ Example:
+
+.. code:: php
+
+ return [
+ 'small' => [
+ 'w' => 60,
+ 'h' => 60,
+ 'square' => true,
+ 'upscale' => true,
+ ],
+ 'large' => [
+ 'w' => 600,
+ 'h' => 600,
+ 'upscale' => false,
+ ],
+ 'original' => [],
+ ];
**entity:icon:url, <entity_type>**
Triggered when entity icon URL is requested, see :ref:`entity icons <guides/database#entity-icons>`. Callback should
@@ -262,6 +262,14 @@ public function saveIcon(ElggEntity $entity, ElggFile $file, $type = 'icon', arr
}
$icon = $this->getIcon($entity, $size, $type);
+
+ // Save the image without resizing or cropping if the
+ // image size value is an empty array
+ if (is_array($opts) && empty($opts)) {
+ copy($file->getFilenameOnFilestore(), $icon->getFilenameOnFilestore());
+ continue;
+ }
+
$image_bytes = get_resized_image_from_existing_file($file->getFilenameOnFilestore(), $width, $height, $square, $x1, $y1, $x2, $y2, $upscale);
if ($image_bytes) {
$icon->open("write");
@@ -282,7 +290,7 @@ public function saveIcon(ElggEntity $entity, ElggFile $file, $type = 'icon', arr
* The icon file may or may not exist on filestore
*
* @note Returned ElggIcon object may be a placeholder. Use ElggIcon::exists() to validate if file has been written to filestore
- *
+ *
* @param ElggEntity $entity Entity that owns the icon
* @param string $size Size of the icon
* @param string $type The name of the icon. e.g., 'icon', 'cover_photo'
@@ -130,7 +130,9 @@ public static function getCoverSizes() {
'w' => 1280,
'h' => 720,
'square' => false,
- ]
+ ],
+ // Empty config means that image should not be altered
+ 'original' => [],
];
}
@@ -536,6 +538,53 @@ public function testCanSaveIconWithCroppingCoordinates() {
$this->assertNotEquals($medium_bytes, file_get_contents($service->getIcon($this->entity, 'medium')->getFilenameOnFilestore()));
}
+ /**
+ * @group IconService
+ */
+ function testEmptySizeConfigSavesUnmodifiedVersion() {
+ $this->hooks->registerHandler('entity:cover:sizes', 'object', array($this, 'getCoverSizes'));
+
+ $service = $this->createService();
+
+ $file = new \ElggFile();
+ $file->owner_guid = 1;
+ $file->setFilename('600x300.jpg');
+ $file->mimetype = 'image/jpeg';
+
+ $service->saveIconFromElggFile($this->entity, $file, 'cover');
+
+ // original file should stay where it is
+ $this->assertTrue($file->exists());
+
+ $this->assertTrue($service->hasIcon($this->entity, 'medium', 'cover'));
+ $this->assertTrue($service->hasIcon($this->entity, 'original', 'cover'));
+
+ $medium = $service->getIcon($this->entity, 'original', 'cover');
+ $medium_bytes = file_get_contents($medium->getFilenameOnFilestore());
+
+ $source_bytes = file_get_contents($file->getFilenameOnFilestore());
+
+ // crop with coordinates
+ $service->saveIconFromElggFile($this->entity, $file, 'cover', [
+ 'x1' => 10,
+ 'y1' => 10,
+ 'x2' => 110,
+ 'y2' => 110,
+ ]);
+
+ // source file should stay where it is
+ $this->assertTrue($file->exists());
+
+ $this->assertTrue($service->hasIcon($this->entity, 'medium', 'cover'));
+ $this->assertTrue($service->hasIcon($this->entity, 'original', 'cover'));
+
+ // original should remain the same
+ $this->assertEquals($source_bytes, file_get_contents($service->getIcon($this->entity, 'original', 'cover')->getFilenameOnFilestore()));
+
+ // medium should have been cropped
+ $this->assertNotEquals($medium_bytes, file_get_contents($service->getIcon($this->entity, 'medium', 'cover')->getFilenameOnFilestore()));
+ }
+
/**
* @group IconService
* @expectedException \LogicException
@@ -913,7 +962,7 @@ public function testCanHandleServeIconRequest() {
$this->assertEquals('max-age=86400, private', $response->headers->get('cache-control'));
// now try conditional request
-
+
$this->request->headers->set('if-none-match', '"' . $icon->getModifiedTime() . '"');
$response = $service->handleServeIconRequest(false);

0 comments on commit 7157a33

Please sign in to comment.