From 93782f04d35eb02ed309aa39b41d8b13d82cd110 Mon Sep 17 00:00:00 2001 From: Burkov Sergey Date: Mon, 13 Dec 2021 19:13:20 +0300 Subject: [PATCH] Test fixes, convertion for comment sizes from px to pt, fix for setting image sizes from zip, set image type --- src/PhpSpreadsheet/Comment.php | 17 ++++-- src/PhpSpreadsheet/Reader/Xlsx.php | 3 +- src/PhpSpreadsheet/Worksheet/BaseDrawing.php | 30 +++++++++++ src/PhpSpreadsheet/Worksheet/Drawing.php | 25 ++++----- .../Writer/Xlsx/DrawingsTest.php | 53 ++++++++++++++++++- 5 files changed, 108 insertions(+), 20 deletions(-) diff --git a/src/PhpSpreadsheet/Comment.php b/src/PhpSpreadsheet/Comment.php index c4bb3da735..62579a99d8 100644 --- a/src/PhpSpreadsheet/Comment.php +++ b/src/PhpSpreadsheet/Comment.php @@ -2,11 +2,13 @@ namespace PhpOffice\PhpSpreadsheet; +use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; use PhpOffice\PhpSpreadsheet\Helper\Size; use PhpOffice\PhpSpreadsheet\RichText\RichText; use PhpOffice\PhpSpreadsheet\Style\Alignment; use PhpOffice\PhpSpreadsheet\Style\Color; use PhpOffice\PhpSpreadsheet\Worksheet\Drawing; +use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing; class Comment implements IComparable { @@ -315,7 +317,13 @@ public function __toString(): string */ public function hasBackgroundImage(): bool { - return file_exists($this->backgroundImage->getPath()); + $path = $this->backgroundImage->getPath(); + + if (empty($path)) { + return false; + } + + return getimagesize($path) !== false; } /** @@ -331,6 +339,9 @@ public function getBackgroundImage(): Drawing */ public function setBackgroundImage(Drawing $objDrawing): self { + if (!array_key_exists($objDrawing->getType(),Drawing::IMAGE_TYPES_CONVERTION_MAP)) { + throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.'); + } $this->backgroundImage = $objDrawing; return $this; @@ -342,8 +353,8 @@ public function setBackgroundImage(Drawing $objDrawing): self public function setSizeAsBackgroundImage(): self { if ($this->hasBackgroundImage()) { - $this->setWidth((string) $this->backgroundImage->getWidth()); - $this->setHeight((string) $this->backgroundImage->getHeight()); + $this->setWidth(SharedDrawing::pixelsToPoints($this->backgroundImage->getWidth()) . 'pt'); + $this->setHeight(SharedDrawing::pixelsToPoints($this->backgroundImage->getHeight()) . 'pt'); } return $this; diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index a3a26ed3c6..6b2c2fd6e7 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -1054,7 +1054,8 @@ public function load(string $filename, int $flags = 0): Spreadsheet $imagePath = str_replace('../', 'xl/', $drowingImages[$fillImageRelId]); $objDrawing->setPath( 'zip://' . File::realpath($filename) . '#' . $imagePath, - false + true, + $zip ); $comment->setBackgroundImage($objDrawing); } diff --git a/src/PhpSpreadsheet/Worksheet/BaseDrawing.php b/src/PhpSpreadsheet/Worksheet/BaseDrawing.php index b8cfb017de..a4fef93e4b 100644 --- a/src/PhpSpreadsheet/Worksheet/BaseDrawing.php +++ b/src/PhpSpreadsheet/Worksheet/BaseDrawing.php @@ -106,6 +106,13 @@ class BaseDrawing implements IComparable */ private $hyperlink; + /** + * Image type. + * + * @var int + */ + protected $type; + /** * Create a new BaseDrawing. */ @@ -123,6 +130,7 @@ public function __construct() $this->resizeProportional = true; $this->rotation = 0; $this->shadow = new Drawing\Shadow(); + $this->type = IMAGETYPE_UNKNOWN; // Set image index ++self::$imageCounter; @@ -526,4 +534,26 @@ public function getHyperlink() { return $this->hyperlink; } + + /** + * Set Fact Sizes and Type of Image. + */ + protected function setSizesAndType(string $path) + { + if ($this->width == 0 && $this->height == 0 && $this->type == IMAGETYPE_UNKNOWN) { + if ($imageData = getimagesize($path)) { + $this->width = $imageData[0]; + $this->height = $imageData[1]; + $this->type = $imageData[2]; + } + } + } + + /** + * Get Image Type. + */ + public function getType(): int + { + return $this->type; + } } diff --git a/src/PhpSpreadsheet/Worksheet/Drawing.php b/src/PhpSpreadsheet/Worksheet/Drawing.php index 55d44a716e..feba986ad6 100644 --- a/src/PhpSpreadsheet/Worksheet/Drawing.php +++ b/src/PhpSpreadsheet/Worksheet/Drawing.php @@ -80,15 +80,11 @@ public function getExtension() */ public function getMediaFilename() { - $imageData = getimagesize($this->getPath()); - - if ($imageData === false) { - throw new PhpSpreadsheetException('Unable to get image data of ' . $this->getPath()); - } elseif (!array_key_exists($imageData[2], self::IMAGE_TYPES_CONVERTION_MAP)) { + if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) { throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.'); } - $newImageType = self::IMAGE_TYPES_CONVERTION_MAP[$imageData[2]]; + $newImageType = self::IMAGE_TYPES_CONVERTION_MAP[$this->type]; return sprintf('image%d%s', $this->getImageIndex(), image_type_to_extension($newImageType)); } @@ -108,10 +104,11 @@ public function getPath() * * @param string $path File path * @param bool $verifyFile Verify file + * @param \ZipArchive $zip Zip archive instance * * @return $this */ - public function setPath($path, $verifyFile = true) + public function setPath($path, $verifyFile = true, $zip = null) { if ($verifyFile) { // Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979 @@ -124,18 +121,18 @@ public function setPath($path, $verifyFile = true) if ($filePath) { file_put_contents($filePath, $imageContents); if (file_exists($filePath)) { - if ($this->width == 0 && $this->height == 0) { - // Get width/height - [$this->width, $this->height] = getimagesize($filePath); - } + $this->setSizesAndType($filePath); unlink($filePath); } } } elseif (file_exists($path)) { $this->path = $path; - if ($this->width == 0 && $this->height == 0) { - // Get width/height - [$this->width, $this->height] = getimagesize($path); + $this->setSizesAndType($path); + } elseif ($zip instanceof \ZipArchive) { + $zipPath = explode('#', $path)[1]; + if ($zip->locateName($zipPath) !== false) { + $this->path = $path; + $this->setSizesAndType($path); } } else { throw new PhpSpreadsheetException("File $path not found!"); diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/DrawingsTest.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/DrawingsTest.php index eff4e321de..266a428316 100644 --- a/tests/PhpSpreadsheetTests/Writer/Xlsx/DrawingsTest.php +++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/DrawingsTest.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx; +use PhpOffice\PhpSpreadsheet\Comment; +use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Reader\Xlsx; use PhpOffice\PhpSpreadsheet\Shared\File; @@ -77,13 +79,19 @@ public function testSaveLoadWithDrawingInComment(): void $reader = new Xlsx(); $spreadsheet = $reader->load($tempFileName); + $sheet = $spreadsheet->getActiveSheet(); + $comment = $sheet->getComment('A1'); + + self::assertTrue($comment->hasBackgroundImage()); + self::assertEquals($comment->getBackgroundImage()->getWidth(), 178); + self::assertEquals($comment->getBackgroundImage()->getHeight(), 140); + $writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); $writer->save($tempFileName); $reloadedSpreadsheet = $reader->load($tempFileName); unlink($tempFileName); - // Fake assert. The only thing we need is to ensure the file is loaded without exception self::assertNotNull($reloadedSpreadsheet); } @@ -101,54 +109,96 @@ public function testBuildWithDifferentImageFormats(): void $drawing = new Drawing(); $drawing->setName('Blue Square'); $drawing->setPath('tests/data/Writer/XLSX/blue_square.png'); + self::assertEquals($drawing->getWidth(), 100); + self::assertEquals($drawing->getHeight(), 100); $comment = $sheet->getComment('A1'); $comment->setBackgroundImage($drawing); $comment->setSizeAsBackgroundImage(); + self::assertEquals($comment->getWidth(), '75pt'); + self::assertEquals($comment->getHeight(), '75pt'); + + $comment = $sheet->getComment('A1'); + self::assertTrue($comment instanceof Comment); + self::assertTrue($comment->hasBackgroundImage()); + self::assertTrue($comment->getBackgroundImage() instanceof Drawing); // Add gif image to comment background $sheet->setCellValue('A2', '.gif'); $drawing = new Drawing(); $drawing->setName('Green Square'); $drawing->setPath('tests/data/Writer/XLSX/green_square.gif'); + self::assertEquals($drawing->getWidth(), 150); + self::assertEquals($drawing->getHeight(), 150); $comment = $sheet->getComment('A2'); $comment->setBackgroundImage($drawing); $comment->setSizeAsBackgroundImage(); + self::assertEquals($comment->getWidth(), '112.5pt'); + self::assertEquals($comment->getHeight(), '112.5pt'); // Add jpeg image to comment background $sheet->setCellValue('A3', '.jpeg'); $drawing = new Drawing(); $drawing->setName('Red Square'); $drawing->setPath('tests/data/Writer/XLSX/red_square.jpeg'); + self::assertEquals($drawing->getWidth(), 50); + self::assertEquals($drawing->getHeight(), 50); $comment = $sheet->getComment('A3'); $comment->setBackgroundImage($drawing); $comment->setSizeAsBackgroundImage(); + self::assertEquals($comment->getWidth(), '37.5pt'); + self::assertEquals($comment->getHeight(), '37.5pt'); // Add bmp image to comment background $sheet->setCellValue('A4', '.bmp 16 colors'); $drawing = new Drawing(); $drawing->setName('Yellow Square'); $drawing->setPath('tests/data/Writer/XLSX/yellow_square_16.bmp'); + self::assertEquals($drawing->getWidth(), 70); + self::assertEquals($drawing->getHeight(), 70); $comment = $sheet->getComment('A4'); $comment->setBackgroundImage($drawing); $comment->setSizeAsBackgroundImage(); + self::assertEquals($comment->getWidth(), '52.5pt'); + self::assertEquals($comment->getHeight(), '52.5pt'); // Add bmp image to comment background $sheet->setCellValue('A5', '.bmp 256 colors'); $drawing = new Drawing(); $drawing->setName('Brown Square'); $drawing->setPath('tests/data/Writer/XLSX/brown_square_256.bmp'); + self::assertEquals($drawing->getWidth(), 70); + self::assertEquals($drawing->getHeight(), 70); $comment = $sheet->getComment('A5'); $comment->setBackgroundImage($drawing); $comment->setSizeAsBackgroundImage(); + self::assertEquals($comment->getWidth(), '52.5pt'); + self::assertEquals($comment->getHeight(), '52.5pt'); // Add bmp image to comment background $sheet->setCellValue('A6', '.bmp 24 bit'); $drawing = new Drawing(); $drawing->setName('Orange Square'); $drawing->setPath('tests/data/Writer/XLSX/orange_square_24_bit.bmp'); + self::assertEquals($drawing->getWidth(), 70); + self::assertEquals($drawing->getHeight(), 70); $comment = $sheet->getComment('A6'); $comment->setBackgroundImage($drawing); $comment->setSizeAsBackgroundImage(); + self::assertEquals($comment->getWidth(), '52.5pt'); + self::assertEquals($comment->getHeight(), '52.5pt'); + + // Add unsupported tiff image to comment background + $sheet->setCellValue('A7', '.tiff'); + $drawing = new Drawing(); + $drawing->setName('Purple Square'); + $drawing->setPath('tests/data/Writer/XLSX/purple_square.tiff'); + $comment = $sheet->getComment('A7'); + try { + $comment->setBackgroundImage($drawing); + } catch (PhpSpreadsheetException $e) { + self::assertTrue($e instanceof PhpSpreadsheetException); + self::assertEquals($e->getMessage(), 'Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.'); + } // Write file $writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); @@ -159,7 +209,6 @@ public function testBuildWithDifferentImageFormats(): void $reloadedSpreadsheet = $reader->load($tempFileName); unlink($tempFileName); - // Fake assert. The only thing we need is to ensure the file is loaded without exception self::assertNotNull($reloadedSpreadsheet); } }