From db1aba6554b053e45facc06c4869ffbc76e34de0 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Thu, 9 Oct 2025 08:19:12 -0700 Subject: [PATCH] Better Sample File --- .php-cs-fixer.dist.php | 3 +- src/PhpSpreadsheet/Reader/Xlsx.php | 8 ++- .../Reader/Xlsx/Issue4505Test.php | 65 ++++-------------- .../Reader/XLSX/issue.4505.namespace.xlsx | Bin 0 -> 11579 bytes tests/data/Reader/XLSX/issue.4505.xlsx | Bin 6417 -> 0 bytes 5 files changed, 20 insertions(+), 56 deletions(-) create mode 100644 tests/data/Reader/XLSX/issue.4505.namespace.xlsx delete mode 100644 tests/data/Reader/XLSX/issue.4505.xlsx diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 562e7fe81..7c870e1ed 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -84,6 +84,8 @@ $config 'method_chaining_indentation' => true, 'modernize_strpos' => true, 'modernize_types_casting' => true, + 'modifier_keywords' => ['elements' => ['property', 'method']], // not const + 'multiline_comment_opening_closing' => true, 'multiline_whitespace_before_semicolons' => true, 'native_constant_invocation' => false, // Micro optimization that look messy @@ -236,7 +238,6 @@ $config 'types_spaces' => true, 'unary_operator_spaces' => true, 'use_arrow_functions' => true, - 'visibility_required' => ['elements' => ['property', 'method']], // not const 'void_return' => true, 'whitespace_after_comma_in_array' => true, 'yoda_style' => false, diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index 53bb7ed75..44685c474 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -1205,9 +1205,10 @@ class Xlsx extends BaseReader $shapes = self::xpathNoFalse($vmlCommentsFile, '//v:shape'); foreach ($shapes as $shape) { /** @var SimpleXMLElement $shape */ - $shape->registerXPathNamespace('v', Namespaces::URN_VML); - $shape->registerXPathNamespace('x', Namespaces::URN_VML); - $shape->registerXPathNamespace('o', Namespaces::URN_MSOFFICE); + $vmlNamespaces = $shape->getNamespaces(); + $shape->registerXPathNamespace('v', $vmlNamespaces['v'] ?? Namespaces::URN_VML); + $shape->registerXPathNamespace('x', $vmlNamespaces['x'] ?? Namespaces::URN_EXCEL); + $shape->registerXPathNamespace('o', $vmlNamespaces['o'] ?? Namespaces::URN_MSOFFICE); if (isset($shape['style'])) { $style = (string) $shape['style']; @@ -1232,6 +1233,7 @@ class Xlsx extends BaseReader $clientData = $clientData[0]; if (isset($clientData['ObjectType']) && (string) $clientData['ObjectType'] == 'Note') { + $clientData->registerXPathNamespace('x', $vmlNamespaces['x'] ?? Namespaces::URN_EXCEL); $temp = $clientData->xpath('.//x:Row'); if (is_array($temp)) { $row = $temp[0]; diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4505Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4505Test.php index fc859bf57..51ca078fb 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4505Test.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4505Test.php @@ -5,13 +5,11 @@ declare(strict_types=1); namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx; use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader; -use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces as XlsxNamespaces; use PHPUnit\Framework\TestCase; -use SimpleXMLElement; class Issue4505Test extends TestCase { - private static string $file = 'tests/data/Reader/XLSX/issue.4505.xlsx'; + private static string $file = 'tests/data/Reader/XLSX/issue.4505.namespace.xlsx'; public function testVmlProcessingWithXAndONamespaces(): void { @@ -20,61 +18,24 @@ class Issue4505Test extends TestCase $sheet = $spreadsheet->getActiveSheet(); $comments = $sheet->getComments(); - self::assertSame('Sheet1', $sheet->getTitle()); - - if (!empty($comments)) { - $comment = reset($comments); - $comment->getText(); - } - + self::assertArrayHasKey('A1', $comments); + self::assertSame('right', $comments['A1']->getAlignment()); + self::assertSame("Some User:\nHello", (string) $comments['A1']->getText()); $spreadsheet->disconnectWorksheets(); } public function testVmlFileContainsRequiredNamespaces(): void { $file = 'zip://' . self::$file . '#xl/drawings/vmlDrawing1.vml'; - $data = file_get_contents($file); + $data = (string) file_get_contents($file); - if ($data === false) { - self::markTestSkipped('Test file issue.4505.xlsx not found or VML file missing.'); - } - - self::assertStringContainsString('registerXPathNamespace('v', XlsxNamespaces::URN_VML); - $shape->registerXPathNamespace('x', XlsxNamespaces::URN_VML); - $shape->registerXPathNamespace('o', XlsxNamespaces::URN_MSOFFICE); - - $clientData = $shape->xpath('.//x:ClientData'); - self::assertNotEmpty($clientData, 'XPath with x: prefix works with namespace registration'); - - $relid = $shape->xpath('.//v:fill/@o:relid'); - self::assertNotEmpty($relid, 'XPath with o: prefix works with namespace registration'); - - $row = $clientData[0]->xpath('.//x:Row'); - self::assertNotEmpty($row, 'Can access nested x: elements'); - self::assertEquals('5', (string) $row[0], 'Row value is correct'); - - self::assertEquals('rId1', (string) $relid[0], 'RelId value is correct'); + self::assertStringContainsString('', $data); // usually o:shapelayout v:ext + self::assertStringContainsString('', $data); // usually x:ClientData + self::assertStringContainsString('ns3:insetmode', $data); // usually o:insetmode + self::assertStringContainsString( + 'Right', // usually x:TextHAlign + $data + ); } } diff --git a/tests/data/Reader/XLSX/issue.4505.namespace.xlsx b/tests/data/Reader/XLSX/issue.4505.namespace.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..043f9eaa7de8af2cfd36bc124ad793826b2d4918 GIT binary patch literal 11579 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 ZPv0Xa1qI?^0RUvs=MZFz+|)n5{U7BDD)s;X literal 0 HcmV?d00001 diff --git a/tests/data/Reader/XLSX/issue.4505.xlsx b/tests/data/Reader/XLSX/issue.4505.xlsx deleted file mode 100644 index 9b0a417b59a666fceb30ba0bb18d7efb198e48c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6417 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 X`dYV;(eO*fA^^A{)vQ$VUvK{dXMOWd