From 393299ae21153f042f48b185f2adeb4b157d1d93 Mon Sep 17 00:00:00 2001 From: Rik van der Heijden Date: Fri, 26 Jul 2024 07:48:04 +0200 Subject: [PATCH] fix stylemanager with escaper and also escape functions and errors, fixes #261 (#263) --- src/Writer/XLSX/Manager/Style/StyleManager.php | 9 +++++++-- src/Writer/XLSX/Manager/WorksheetManager.php | 4 ++-- src/Writer/XLSX/Writer.php | 9 +++++++-- .../XLSX/Manager/Style/StyleManagerTest.php | 15 ++++++++++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/Writer/XLSX/Manager/Style/StyleManager.php b/src/Writer/XLSX/Manager/Style/StyleManager.php index a6dead56..c39a9ed4 100644 --- a/src/Writer/XLSX/Manager/Style/StyleManager.php +++ b/src/Writer/XLSX/Manager/Style/StyleManager.php @@ -7,6 +7,7 @@ use OpenSpout\Common\Entity\Style\BorderPart; use OpenSpout\Common\Entity\Style\Color; use OpenSpout\Common\Entity\Style\Style; +use OpenSpout\Common\Helper\Escaper\XLSX as XLSXEscaper; use OpenSpout\Writer\Common\Manager\Style\AbstractStyleManager as CommonStyleManager; use OpenSpout\Writer\XLSX\Helper\BorderHelper; @@ -17,9 +18,13 @@ */ final class StyleManager extends CommonStyleManager { - public function __construct(StyleRegistry $styleRegistry) + /** @var XLSXEscaper Strings escaper */ + private readonly XLSXEscaper $stringsEscaper; + + public function __construct(StyleRegistry $styleRegistry, XLSXEscaper $stringsEscaper) { parent::__construct($styleRegistry); + $this->stringsEscaper = $stringsEscaper; } /** @@ -91,7 +96,7 @@ private function getFormatsSectionContent(): string /** @var Style $style */ $style = $this->styleRegistry->getStyleFromStyleId($styleId); $format = $style->getFormat(); - $tags[] = ''; + $tags[] = ''; } $content = ''; $content .= implode('', $tags); diff --git a/src/Writer/XLSX/Manager/WorksheetManager.php b/src/Writer/XLSX/Manager/WorksheetManager.php index 94ca09c8..aab9d510 100644 --- a/src/Writer/XLSX/Manager/WorksheetManager.php +++ b/src/Writer/XLSX/Manager/WorksheetManager.php @@ -198,14 +198,14 @@ private function getCellXML(int $rowIndexOneBased, int $columnIndexZeroBased, Ce } elseif ($cell instanceof Cell\NumericCell) { $cellXML .= '>'.$cell->getValue().''; } elseif ($cell instanceof Cell\FormulaCell) { - $cellXML .= '>'.substr($cell->getValue(), 1).''; + $cellXML .= '>'.$this->stringsEscaper->escape(substr($cell->getValue(), 1)).''; } elseif ($cell instanceof Cell\DateTimeCell) { $cellXML .= '>'.DateHelper::toExcel($cell->getValue()).''; } elseif ($cell instanceof Cell\DateIntervalCell) { $cellXML .= '>'.DateIntervalHelper::toExcel($cell->getValue()).''; } elseif ($cell instanceof Cell\ErrorCell) { // only writes the error value if it's a string - $cellXML .= ' t="e">'.$cell->getRawValue().''; + $cellXML .= ' t="e">'.$this->stringsEscaper->escape($cell->getRawValue()).''; } elseif ($cell instanceof Cell\EmptyCell) { if ($this->styleManager->shouldApplyStyleOnEmptyCell($styleId)) { $cellXML .= '/>'; diff --git a/src/Writer/XLSX/Writer.php b/src/Writer/XLSX/Writer.php index cab0676a..73cfa513 100644 --- a/src/Writer/XLSX/Writer.php +++ b/src/Writer/XLSX/Writer.php @@ -51,7 +51,12 @@ protected function createWorkbookManager(): WorkbookManager $sharedStringsManager = new SharedStringsManager($xlFolder, new XLSX()); $styleMerger = new StyleMerger(); - $styleManager = new StyleManager(new StyleRegistry($this->options->DEFAULT_ROW_STYLE)); + $escaper = new XLSX(); + + $styleManager = new StyleManager( + new StyleRegistry($this->options->DEFAULT_ROW_STYLE), + $escaper + ); $commentsManager = new CommentsManager($xlFolder, new XLSX()); @@ -61,7 +66,7 @@ protected function createWorkbookManager(): WorkbookManager $styleMerger, $commentsManager, $sharedStringsManager, - new XLSX(), + $escaper, StringHelper::factory() ); diff --git a/tests/Writer/XLSX/Manager/Style/StyleManagerTest.php b/tests/Writer/XLSX/Manager/Style/StyleManagerTest.php index 903e2f0e..fbec7fb9 100644 --- a/tests/Writer/XLSX/Manager/Style/StyleManagerTest.php +++ b/tests/Writer/XLSX/Manager/Style/StyleManagerTest.php @@ -4,6 +4,8 @@ namespace OpenSpout\Writer\XLSX\Manager\Style; +use OpenSpout\Common\Entity\Style\Style; +use OpenSpout\Common\Helper\Escaper\XLSX as XLSXEscaper; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -47,9 +49,20 @@ public function testShouldApplyStyleOnEmptyCell(?int $fillId, ?int $borderId, bo ->willReturn($borderId) ; - $styleManager = new StyleManager($styleRegistryMock); + $styleManager = new StyleManager($styleRegistryMock, new XLSXEscaper()); $shouldApply = $styleManager->shouldApplyStyleOnEmptyCell(99); self::assertSame($expectedResult, $shouldApply); } + + public function testFormatCodeEscapeInSectionContent(): void + { + $registry = new StyleRegistry(new Style()); + + $registry->registerStyle((new Style())->setId(1)->setFormat('"€"* #,##0.00_-')); + + $styleManager = new StyleManager($registry, new XLSXEscaper()); + $output = $styleManager->getStylesXMLFileContent(); + self::assertStringContainsString('formatCode=""€"* #,##0.00_-"', $output); + } }