[BUGFIX] Deliver detected file type for IM identify 11/60311/7
authorBenni Mack <benni@typo3.org>
Fri, 22 Mar 2019 19:28:20 +0000 (20:28 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Fri, 5 Apr 2019 16:52:21 +0000 (18:52 +0200)
Although not used in TYPO3 Core directly, the identify
command by ImageMagick now delivers the file extension
from IM plus the file type identified by IM as well.

This saves some regexp magic, and a foreach() loop,
as the "-format" output delivers proper IM results.

As this functionality is not actually fixing a core
bug, but rather a small improvement and correction
in the identified usage, the change is targeted to master-only.

Resolves: #23348
Releases: master
Change-Id: Ia380ee34dbbef7f9f763ecc088ee0c9b83167ce6
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/60311
Tested-by: Sebastian Rosskopf <sebastian.rosskopf@gmx.de>
Tested-by: Jochen <rothjochen@gmail.com>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Sebastian Rosskopf <sebastian.rosskopf@gmx.de>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Jochen <rothjochen@gmail.com>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php
typo3/sysext/core/Tests/Unit/Imaging/GraphicalFunctionsTest.php

index 740157b..36adf70 100644 (file)
@@ -2401,7 +2401,7 @@ class GraphicalFunctions
      * Call the identify command
      *
      * @param string $imagefile The relative to public web path image filepath
-     * @return array|null Returns an array where [0]/[1] is w/h, [2] is extension and [3] is the filename.
+     * @return array|null Returns an array where [0]/[1] is w/h, [2] is extension, [3] is the filename and [4] the real image type identified by ImageMagick.
      */
     public function imageMagickIdentify($imagefile)
     {
@@ -2409,34 +2409,34 @@ class GraphicalFunctions
             return null;
         }
 
-        $frame = $this->addFrameSelection ? '[0]' : '';
-        $cmd = CommandUtility::imageMagickCommand('identify', CommandUtility::escapeShellArgument($imagefile) . $frame);
-        $returnVal = [];
-        CommandUtility::exec($cmd, $returnVal);
-        $splitstring = array_pop($returnVal);
-        $this->IM_commands[] = ['identify', $cmd, $splitstring];
-        if ($splitstring) {
-            preg_match('/([^\\.]*)$/', $imagefile, $reg);
-            $splitinfo = explode(' ', $splitstring);
-            $dim = false;
-            foreach ($splitinfo as $key => $val) {
-                $temp = '';
-                if ($val) {
-                    $temp = explode('x', $val);
-                }
-                if ((int)$temp[0] && (int)$temp[1]) {
-                    $dim = $temp;
-                    break;
-                }
-            }
-            if (!empty($dim[0]) && !empty($dim[1])) {
-                return [$dim[0], $dim[1], strtolower($reg[0]), $imagefile];
+        $result = $this->executeIdentifyCommandForImageFile($imagefile);
+        if ($result) {
+            [$width, $height, $fileExtension, $fileType] = explode(' ', $result);
+            if ((int)$width && (int)$height) {
+                return [$width, $height, strtolower($fileExtension), $imagefile, strtolower($fileType)];
             }
         }
         return null;
     }
 
     /**
+     * Internal function to execute an IM command fetching information on an image
+     *
+     * @param string $imageFile the absolute path to the image
+     * @return string|null the raw result of the identify command.
+     */
+    protected function executeIdentifyCommandForImageFile(string $imageFile): ?string
+    {
+        $frame = $this->addFrameSelection ? '[0]' : '';
+        $cmd = CommandUtility::imageMagickCommand('identify', '-format "%w %h %e %m" ' . CommandUtility::escapeShellArgument($imageFile . $frame));
+        $returnVal = [];
+        CommandUtility::exec($cmd, $returnVal);
+        $result = array_pop($returnVal);
+        $this->IM_commands[] = ['identify', $cmd, $result];
+        return $result;
+    }
+
+    /**
      * Executes an ImageMagick "convert" on two filenames, $input and $output using $params before them.
      * Can be used for many things, mostly scaling and effects.
      *
index 59d507f..0b79909 100644 (file)
@@ -19,6 +19,8 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 class GraphicalFunctionsTest extends UnitTestCase
 {
+    protected $resetSingletonInstances = true;
+
     /**
      * Dataprovider for getScaleForImage
      *
@@ -91,8 +93,49 @@ class GraphicalFunctionsTest extends UnitTestCase
      */
     public function getScaleForImage($info, $width, $height, $options, $expected)
     {
-        $this->resetSingletonInstances = true;
         $result = (new GraphicalFunctions())->getImageScale($info, $width, $height, $options);
         $this->assertEquals($result, $expected);
     }
+
+    /**
+     * @test
+     */
+    public function imageMagickIdentifyReturnsFormattedValues()
+    {
+        $file = 'myImageFile.png';
+        $expected = [
+            '123',
+            '234',
+            'png',
+            'myImageFile.png',
+            'png'
+        ];
+
+        $subject = $this->getAccessibleMock(GraphicalFunctions::class, ['executeIdentifyCommandForImageFile'], [], '', false);
+        $subject->_set('processorEnabled', true);
+        $subject->expects($this->once())->method('executeIdentifyCommandForImageFile')->with($file)->willReturn('123 234 png PNG');
+        $result = $subject->imageMagickIdentify($file);
+        $this->assertEquals($result, $expected);
+    }
+
+    /**
+     * @test
+     */
+    public function imageMagickIdentifyReturnsFormattedValuesWithOffset()
+    {
+        $file = 'myImageFile.png';
+        $expected = [
+            '200+0+0',
+            '400+0+0',
+            'png',
+            'myImageFile.png',
+            'png'
+        ];
+
+        $subject = $this->getAccessibleMock(GraphicalFunctions::class, ['executeIdentifyCommandForImageFile'], [], '', false);
+        $subject->_set('processorEnabled', true);
+        $subject->expects($this->once())->method('executeIdentifyCommandForImageFile')->with($file)->willReturn('200+0+0 400+0+0 png PNG');
+        $result = $subject->imageMagickIdentify($file);
+        $this->assertEquals($result, $expected);
+    }
 }