From 786f81abf6e0d985e38c71ec9006e7d57dbd02db Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 10 Sep 2024 18:56:24 +0200 Subject: [PATCH] WMF\Reader\WMF\Magic : Backends sorted by priority (#6) --- .gitignore | 1 + docs/changes/0.1.2.md | 14 +++ docs/usage/wmf.md | 74 ++++++++++++--- mkdocs.yml | 3 +- src/WMF/Reader/WMF/GD.php | 8 +- src/WMF/Reader/WMF/Imagick.php | 7 +- src/WMF/Reader/WMF/Magic.php | 76 ++++++++++++--- src/WMF/Reader/WMF/ReaderInterface.php | 2 +- tests/WMF/Reader/AbstractTestReader.php | 39 ++++++++ tests/WMF/Reader/WMF/GDTest.php | 24 ++++- tests/WMF/Reader/WMF/ImagickTest.php | 24 ++++- tests/WMF/Reader/WMF/MagicGDTest.php | 107 ++++++++++++++++++++++ tests/WMF/Reader/WMF/MagicImagickTest.php | 101 ++++++++++++++++++++ tests/WMF/Reader/WMF/MagicTest.php | 62 ++++--------- 14 files changed, 459 insertions(+), 83 deletions(-) create mode 100644 docs/changes/0.1.2.md create mode 100644 tests/WMF/Reader/WMF/MagicGDTest.php create mode 100644 tests/WMF/Reader/WMF/MagicImagickTest.php diff --git a/.gitignore b/.gitignore index bfa5383..5812d06 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ composer.lock phpDocumentor.phar +build/ public/ vendor/ \ No newline at end of file diff --git a/docs/changes/0.1.2.md b/docs/changes/0.1.2.md new file mode 100644 index 0000000..6009c4e --- /dev/null +++ b/docs/changes/0.1.2.md @@ -0,0 +1,14 @@ +# 0.1.2 + +## Enhancements + +- WMF\Reader\WMF\Magic : Backends sorted by priority in [#6](https://github.com/PHPOffice/WMF/pull/6) by [@Progi1984](https://github/Progi1984) + +## Bug fixes + +- N/A + +## Miscellaneous + +- N/A + \ No newline at end of file diff --git a/docs/usage/wmf.md b/docs/usage/wmf.md index 69d80d1..73687da 100644 --- a/docs/usage/wmf.md +++ b/docs/usage/wmf.md @@ -7,6 +7,9 @@ You can load `.wmf` files. You can one of two current backends : `gd` or `imagick`. If you don't know which one used, you can use the magic one. +By default, the order of the backends is Imagick, followed by GD. +Each backend is tested on different criteria: extension loaded, format support. + ```php load('sample.wmf'); ``` -For next sample, I will use the magic one. +For next samples, I will use the magic one. + +### `getBackends` + +This specific method for `Magic::class` returns backends sorted by priority. + +```php +getBackends()); +``` + +### `setBackends` + +This specific method for `Magic::class` defines backends sorted by priority. + +```php +setBackends([ + GD::class, + Imagick::class, +]); + +var_dump($reader->getBackends()); +``` ## Methods @@ -39,15 +76,14 @@ The `Imagick` backend returns a `Imagick` object. use PhpOffice\WMF\Reader\WMF\Magic; $reader = new Magic(); +$reader->load('sample.wmf'); -$wmf = $reader->load('sample.wmf'); - -var_dump($wmf->getResource()); +var_dump($reader->getResource()); ``` ### `getMediaType` -The method returns the media type for a WMF file +The method returns the media type for a WMF file. ```php load('sample.wmf'); -$isWMF = $reader->isWMF('sample.wmf'); +$isWMF = $reader->isWMF(); echo 'The file sample.wmf ' . ($isWMF ? 'is a WMF file' : 'is not a WMF file'); ``` ### `load` -The method load a WMF file in the object +The method loads a WMF file in the object. +The method returns `true` if the file has been correctly loaded, or `false` if it has not. ```php load('sample.wmf'); +``` -$wmf = $reader->load('sample.wmf'); +### `loadFromString` + +The method loads a WMF file in the object from a string. +The method returns `true` if the file has been correctly loaded, or `false` if it has not. + +```php +loadFromString(file_get_contents('sample.wmf')); ``` ### `save` @@ -101,7 +152,6 @@ The method transforms the loaded WMF file in an another image. use PhpOffice\WMF\Reader\WMF\Magic; $reader = new Magic(); - -$wmf = $reader->load('sample.wmf'); -$wmf->save('sample.png', 'png'); +$reader->load('sample.wmf'); +$reader->save('sample.png', 'png'); ``` diff --git a/mkdocs.yml b/mkdocs.yml index 6cec629..d9b8d8c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -43,7 +43,8 @@ nav: - WMF: 'usage/wmf.md' - Credits: 'credits.md' - Releases: - - '0.1.1 (WIP)': 'changes/0.1.1.md' + - '0.1.2 (WIP)': 'changes/0.1.2.md' + - '0.1.1': 'changes/0.1.1.md' - '0.1.0': 'changes/0.1.0.md' - Developers: - 'Coveralls': 'https://coveralls.io/github/PHPOffice/WMF' diff --git a/src/WMF/Reader/WMF/GD.php b/src/WMF/Reader/WMF/GD.php index 197eda0..18ccf88 100644 --- a/src/WMF/Reader/WMF/GD.php +++ b/src/WMF/Reader/WMF/GD.php @@ -65,9 +65,9 @@ public function __destruct() } } - public function isWMF(string $filename): bool + public function isWMF(): bool { - list(, $key) = unpack('L', substr(file_get_contents($filename), 0, 4)); + list(, $key) = unpack('L', substr($this->content, 0, 4)); return $key == (int) 0x9AC6CDD7; } @@ -91,6 +91,10 @@ public function loadFromString(string $content): bool */ private function loadContent(): bool { + if (!$this->isWMF()) { + return false; + } + $this->pos = 0; $this->gdiObjects = []; $k = 72 / 25.4; diff --git a/src/WMF/Reader/WMF/Imagick.php b/src/WMF/Reader/WMF/Imagick.php index 0fdc113..8aa7e12 100644 --- a/src/WMF/Reader/WMF/Imagick.php +++ b/src/WMF/Reader/WMF/Imagick.php @@ -42,12 +42,9 @@ private function loadContent(string $content, bool $isBlob): bool } } - public function isWMF(string $filename): bool + public function isWMF(): bool { - $im = new ImagickBase(); - $im->readImage($filename); - - return $im->getImageFormat() === 'WMF'; + return $this->im->getImageFormat() === 'WMF'; } public function getResource(): ImagickBase diff --git a/src/WMF/Reader/WMF/Magic.php b/src/WMF/Reader/WMF/Magic.php index 6060b0c..3095891 100644 --- a/src/WMF/Reader/WMF/Magic.php +++ b/src/WMF/Reader/WMF/Magic.php @@ -11,45 +11,70 @@ class Magic extends ReaderAbstract { /** - * @var ReaderInterface + * @var array + */ + protected $backends = [ + ImagickReader::class, + GD::class, + ]; + + /** + * @var ?ReaderInterface */ protected $reader; - public function __construct() + protected function getBackend(): ?ReaderInterface { - $reader = null; - if (extension_loaded('imagick') && in_array('WMF', ImagickBase::queryformats())) { - $reader = new ImagickReader(); + if ($this->reader) { + return $this->reader; } - if (!$reader && extension_loaded('gd')) { - $reader = new GD(); + + $reader = null; + foreach ($this->backends as $backend) { + if ($backend === GD::class) { + if (extension_loaded('gd')) { + $reader = new GD(); + + break; + } + } + if ($backend === ImagickReader::class) { + if (extension_loaded('imagick') && in_array('WMF', ImagickBase::queryformats())) { + $reader = new ImagickReader(); + } + + break; + } } + $this->reader = $reader; + + return $this->reader; } public function load(string $filename): bool { - return $this->reader->load($filename); + return $this->getBackend()->load($filename); } public function loadFromString(string $content): bool { - return $this->reader->loadFromString($content); + return $this->getBackend()->loadFromString($content); } public function save(string $filename, string $format): bool { - return $this->reader->save($filename, $format); + return $this->getBackend()->save($filename, $format); } public function getMediaType(): string { - return $this->reader->getMediaType(); + return $this->getBackend()->getMediaType(); } - public function isWMF(string $filename): bool + public function isWMF(): bool { - return $this->reader->isWMF($filename); + return $this->getBackend()->isWMF(); } /** @@ -59,6 +84,29 @@ public function isWMF(string $filename): bool */ public function getResource() { - return $this->reader->getResource(); + return $this->getBackend()->getResource(); + } + + /** + * @return array + */ + public function getBackends(): array + { + return $this->backends; + } + + /** + * @param array $backends + */ + public function setBackends(array $backends): self + { + $this->backends = []; + foreach ($backends as $backend) { + if (is_a($backend, ReaderInterface::class, true)) { + $this->backends[] = $backend; + } + } + + return $this; } } diff --git a/src/WMF/Reader/WMF/ReaderInterface.php b/src/WMF/Reader/WMF/ReaderInterface.php index 84ace5f..d0a1819 100644 --- a/src/WMF/Reader/WMF/ReaderInterface.php +++ b/src/WMF/Reader/WMF/ReaderInterface.php @@ -6,5 +6,5 @@ interface ReaderInterface extends ReaderInterfaceBase { - public function isWMF(string $filename): bool; + public function isWMF(): bool; } diff --git a/tests/WMF/Reader/AbstractTestReader.php b/tests/WMF/Reader/AbstractTestReader.php index 09cf0d6..1575ac6 100644 --- a/tests/WMF/Reader/AbstractTestReader.php +++ b/tests/WMF/Reader/AbstractTestReader.php @@ -55,4 +55,43 @@ public static function dataProviderFilesWMFNotImplemented(): array ], ]; } + + /** + * @return array> + */ + public static function dataProviderMediaType(): array + { + return [ + [ + 'gif', + 'image/gif', + ], + [ + 'jpg', + 'image/jpeg', + ], + [ + 'jpeg', + 'image/jpeg', + ], + [ + 'png', + 'image/png', + ], + [ + 'webp', + 'image/webp', + ], + [ + 'wbmp', + 'image/vnd.wap.wbmp', + ], + ]; + } + + public function assertMimeType(string $filename, string $expectedMimeType): void + { + $gdInfo = getimagesize($filename); + $this->assertEquals($expectedMimeType, $gdInfo['mime']); + } } diff --git a/tests/WMF/Reader/WMF/GDTest.php b/tests/WMF/Reader/WMF/GDTest.php index ec44952..b70e83e 100644 --- a/tests/WMF/Reader/WMF/GDTest.php +++ b/tests/WMF/Reader/WMF/GDTest.php @@ -61,6 +61,21 @@ public function testOutput(string $file): void @unlink($outputFile); } + /** + * @dataProvider dataProviderMediaType + */ + public function testSave(string $extension, string $mediatype): void + { + $outputFile = $this->getResourceDir() . 'output_save.' . $extension; + + $reader = new GD(); + $reader->load($this->getResourceDir() . 'burger.wmf'); + $reader->save($outputFile, $extension); + $this->assertMimeType($outputFile, $mediatype); + + @unlink($outputFile); + } + public function testSaveWithException(): void { $file = 'vegetable.wmf'; @@ -90,7 +105,14 @@ public function testSaveWithoutException(): void public function testIsWMF(string $file): void { $reader = new GD(); - $this->assertTrue($reader->isWMF($this->getResourceDir() . $file)); + $reader->load($this->getResourceDir() . $file); + $this->assertTrue($reader->isWMF()); + } + + public function testMediaType(): void + { + $reader = new GD(); + $this->assertEquals('image/wmf', $reader->getMediaType()); } /** diff --git a/tests/WMF/Reader/WMF/ImagickTest.php b/tests/WMF/Reader/WMF/ImagickTest.php index 1bbdd40..96a9845 100644 --- a/tests/WMF/Reader/WMF/ImagickTest.php +++ b/tests/WMF/Reader/WMF/ImagickTest.php @@ -56,6 +56,21 @@ public function testOutput(string $file): void @unlink($outputFile); } + /** + * @dataProvider dataProviderMediaType + */ + public function testSave(string $extension, string $mediatype): void + { + $outputFile = $this->getResourceDir() . 'output_save.' . $extension; + + $reader = new ImagickReader(); + $reader->load($this->getResourceDir() . 'burger.wmf'); + $reader->save($outputFile, $extension); + $this->assertMimeType($outputFile, $mediatype); + + @unlink($outputFile); + } + public function testSaveWithException(): void { $file = 'vegetable.wmf'; @@ -85,7 +100,14 @@ public function testSaveWithoutException(): void public function testIsWMF(string $file): void { $reader = new ImagickReader(); - $this->assertTrue($reader->isWMF($this->getResourceDir() . $file)); + $reader->load($this->getResourceDir() . $file); + $this->assertTrue($reader->isWMF()); + } + + public function testMediaType(): void + { + $reader = new ImagickReader(); + $this->assertEquals('image/wmf', $reader->getMediaType()); } /** diff --git a/tests/WMF/Reader/WMF/MagicGDTest.php b/tests/WMF/Reader/WMF/MagicGDTest.php new file mode 100644 index 0000000..a613616 --- /dev/null +++ b/tests/WMF/Reader/WMF/MagicGDTest.php @@ -0,0 +1,107 @@ +setBackends([ + GD::class, + Imagick::class, + ]); + + return $reader; + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testLoad(string $file): void + { + $reader = $this->getReader(); + $this->assertTrue($reader->load($this->getResourceDir() . $file)); + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testLoadFromString(string $file): void + { + $reader = $this->getReader(); + $this->assertTrue($reader->loadFromString(file_get_contents($this->getResourceDir() . $file))); + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testGetResource(string $file): void + { + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . $file); + if (\PHP_VERSION_ID < 80000) { + $this->assertIsResource($reader->getResource()); + } else { + /* @phpstan-ignore-next-line */ + $this->assertInstanceOf(GdImage::class, $reader->getResource()); + } + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testOutput(string $file): void + { + $outputFile = $this->getResourceDir() . 'output_' . pathinfo($file, PATHINFO_FILENAME) . '.png'; + $similarFile = $this->getResourceDir() . pathinfo($file, PATHINFO_FILENAME) . '.png'; + + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . $file); + $reader->save($outputFile, 'png'); + + $this->assertImageCompare($outputFile, $similarFile, 0.02); + + @unlink($outputFile); + } + + /** + * @dataProvider dataProviderMediaType + */ + public function testSave(string $extension, string $mediatype): void + { + $outputFile = $this->getResourceDir() . 'output_save.' . $extension; + + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . 'burger.wmf'); + $reader->save($outputFile, $extension); + $this->assertMimeType($outputFile, $mediatype); + + @unlink($outputFile); + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testIsWMF(string $file): void + { + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . $file); + $this->assertTrue($reader->isWMF()); + } + + public function testMediaType(): void + { + $reader = $this->getReader(); + $this->assertEquals('image/wmf', $reader->getMediaType()); + } +} diff --git a/tests/WMF/Reader/WMF/MagicImagickTest.php b/tests/WMF/Reader/WMF/MagicImagickTest.php new file mode 100644 index 0000000..7fa57f5 --- /dev/null +++ b/tests/WMF/Reader/WMF/MagicImagickTest.php @@ -0,0 +1,101 @@ +setBackends([ + Imagick::class, + GD::class, + ]); + + return $reader; + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testLoad(string $file): void + { + $reader = $this->getReader(); + $this->assertTrue($reader->load($this->getResourceDir() . $file)); + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testLoadFromString(string $file): void + { + $reader = $this->getReader(); + $this->assertTrue($reader->loadFromString(file_get_contents($this->getResourceDir() . $file))); + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testGetResource(string $file): void + { + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . $file); + $this->assertIsObject($reader->getResource()); + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testOutput(string $file): void + { + $outputFile = $this->getResourceDir() . 'output_' . pathinfo($file, PATHINFO_FILENAME) . '.png'; + $similarFile = $this->getResourceDir() . pathinfo($file, PATHINFO_FILENAME) . '.png'; + + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . $file); + $reader->save($outputFile, 'png'); + + $this->assertImageCompare($outputFile, $similarFile, 0.02); + + @unlink($outputFile); + } + + /** + * @dataProvider dataProviderMediaType + */ + public function testSave(string $extension, string $mediatype): void + { + $outputFile = $this->getResourceDir() . 'output_save.' . $extension; + + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . 'burger.wmf'); + $reader->save($outputFile, $extension); + $this->assertMimeType($outputFile, $mediatype); + + @unlink($outputFile); + } + + /** + * @dataProvider dataProviderFilesWMF + */ + public function testIsWMF(string $file): void + { + $reader = $this->getReader(); + $reader->load($this->getResourceDir() . $file); + $this->assertTrue($reader->isWMF()); + } + + public function testMediaType(): void + { + $reader = $this->getReader(); + $this->assertEquals('image/wmf', $reader->getMediaType()); + } +} diff --git a/tests/WMF/Reader/WMF/MagicTest.php b/tests/WMF/Reader/WMF/MagicTest.php index 1c6bdb4..14cd7af 100644 --- a/tests/WMF/Reader/WMF/MagicTest.php +++ b/tests/WMF/Reader/WMF/MagicTest.php @@ -4,62 +4,32 @@ namespace Tests\PhpOffice\WMF\Reader\WMF; +use PhpOffice\WMF\Reader\WMF\GD; +use PhpOffice\WMF\Reader\WMF\Imagick; use PhpOffice\WMF\Reader\WMF\Magic; use Tests\PhpOffice\WMF\Reader\AbstractTestReader; class MagicTest extends AbstractTestReader { - /** - * @dataProvider dataProviderFilesWMF - */ - public function testLoad(string $file): void + public function testGetBackends(): void { $reader = new Magic(); - $this->assertTrue($reader->load($this->getResourceDir() . $file)); + $this->assertEquals([ + Imagick::class, + GD::class, + ], $reader->getBackends()); } - /** - * @dataProvider dataProviderFilesWMF - */ - public function testLoadFromString(string $file): void + public function testSetBackends(): void { $reader = new Magic(); - $this->assertTrue($reader->loadFromString(file_get_contents($this->getResourceDir() . $file))); - } - - /** - * @dataProvider dataProviderFilesWMF - */ - public function testGetResource(string $file): void - { - $reader = new Magic(); - $reader->load($this->getResourceDir() . $file); - $this->assertIsObject($reader->getResource()); - } - - /** - * @dataProvider dataProviderFilesWMF - */ - public function testOutput(string $file): void - { - $outputFile = $this->getResourceDir() . 'output_' . pathinfo($file, PATHINFO_FILENAME) . '.png'; - $similarFile = $this->getResourceDir() . pathinfo($file, PATHINFO_FILENAME) . '.png'; - - $reader = new Magic(); - $reader->load($this->getResourceDir() . $file); - $reader->save($outputFile, 'png'); - - $this->assertImageCompare($outputFile, $similarFile, 0.02); - - @unlink($outputFile); - } - - /** - * @dataProvider dataProviderFilesWMF - */ - public function testIsWMF(string $file): void - { - $reader = new Magic(); - $this->assertTrue($reader->isWMF($this->getResourceDir() . $file)); + $this->assertInstanceOf(Magic::class, $reader->setBackends([ + GD::class, + Imagick::class, + ])); + $this->assertEquals([ + GD::class, + Imagick::class, + ], $reader->getBackends()); } }