@@ -75,22 +75,21 @@ public function testWithoutReaderPassThroughShapesAreLost(): void
7575 {
7676 // First, verify that the original file contains a shape
7777 // Load WITH pass-through to check file contents
78- $ verifyReader = new XlsxReader ();
79- $ verifyReader ->setEnableDrawingPassThrough (true );
80- $ verifySpreadsheet = $ verifyReader ->load (self ::TEMPLATE );
81- $ verifyUnparsedData = $ verifySpreadsheet ->getUnparsedLoadedData ();
82- $ verifyCodeName = $ verifySpreadsheet ->getActiveSheet ()->getCodeName ();
83- self ::assertIsArray ($ verifyUnparsedData ['sheets ' ]);
84- self ::assertArrayHasKey ($ verifyCodeName , $ verifyUnparsedData ['sheets ' ]);
85- self ::assertIsArray ($ verifyUnparsedData ['sheets ' ][$ verifyCodeName ]);
86- self ::assertArrayHasKey ('Drawings ' , $ verifyUnparsedData ['sheets ' ][$ verifyCodeName ], 'Original file should have drawings ' );
87- self ::assertIsArray ($ verifyUnparsedData ['sheets ' ][$ verifyCodeName ]['Drawings ' ]);
88- $ verifyDrawings = $ verifyUnparsedData ['sheets ' ][$ verifyCodeName ]['Drawings ' ];
89- $ verifyDrawingXml = reset ($ verifyDrawings );
90- self ::assertIsString ($ verifyDrawingXml );
91- self ::assertStringContainsString ('<xdr:sp ' , $ verifyDrawingXml , 'Original file should contain a shape ' );
92- self ::assertStringContainsString ('<xdr:txBody> ' , $ verifyDrawingXml , 'Original file should contain a textbox ' );
93- $ verifySpreadsheet ->disconnectWorksheets ();
78+ $ reader = new XlsxReader ();
79+ $ reader ->setEnableDrawingPassThrough (true );
80+ $ spreadsheet = $ reader ->load (self ::TEMPLATE );
81+ $ unparsedData = $ spreadsheet ->getUnparsedLoadedData ();
82+ $ codeName = $ spreadsheet ->getActiveSheet ()->getCodeName ();
83+ self ::assertIsArray ($ unparsedData ['sheets ' ]);
84+ self ::assertArrayHasKey ($ codeName , $ unparsedData ['sheets ' ]);
85+ self ::assertIsArray ($ unparsedData ['sheets ' ][$ codeName ]);
86+ self ::assertArrayHasKey ('Drawings ' , $ unparsedData ['sheets ' ][$ codeName ], 'Original file should have drawings ' );
87+ self ::assertIsArray ($ unparsedData ['sheets ' ][$ codeName ]['Drawings ' ]);
88+ $ drawings = $ unparsedData ['sheets ' ][$ codeName ]['Drawings ' ];
89+ $ drawingXml = reset ($ drawings );
90+ self ::assertIsString ($ drawingXml );
91+ self ::assertStringContainsString ('<xdr:sp ' , $ drawingXml , 'Original file should contain shape ' );
92+ $ spreadsheet ->disconnectWorksheets ();
9493
9594 // Now test: Load WITHOUT Reader pass-through (XML not stored)
9695 $ reader = new XlsxReader ();
@@ -440,4 +439,61 @@ public function testDrawingPassThroughEnabledFlagIsSetCorrectly(): void
440439
441440 $ spreadsheet2 ->disconnectWorksheets ();
442441 }
442+
443+ /**
444+ * Test that VML drawings (used by comments) and DrawingML (used by shapes/images)
445+ * coexist without interference when pass-through is enabled.
446+ * This addresses the concern that comments use the drawings folder with VML files.
447+ * The template file already contains a comment in D1, so this test verifies that
448+ * existing comments are preserved AND new comments can be added.
449+ */
450+ public function testCommentsAndPassThroughCoexist (): void
451+ {
452+ // Load file with drawings (image + shape) and enable pass-through
453+ // Note: The template already contains a comment in D1
454+ $ reader = new XlsxReader ();
455+ $ reader ->setEnableDrawingPassThrough (true );
456+ $ spreadsheet = $ reader ->load (self ::TEMPLATE );
457+
458+ $ sheet = $ spreadsheet ->getActiveSheet ();
459+
460+ // Verify the existing comment is loaded
461+ $ existingComment = $ sheet ->getComment ('D1 ' );
462+ $ existingCommentText = $ existingComment ->getText ()->getPlainText ();
463+ self ::assertNotEmpty ($ existingCommentText , 'Template should contain a comment in D1 ' );
464+
465+ // Add a new comment to the sheet
466+ $ sheet ->getComment ('A1 ' )->getText ()->createText ('Test comment with pass-through ' );
467+ $ sheet ->getComment ('A1 ' )->setAuthor ('Test Author ' );
468+
469+ // Save the file
470+ $ tempFile = File::temporaryFilename ();
471+ $ writer = new XlsxWriter ($ spreadsheet );
472+ $ writer ->save ($ tempFile );
473+ $ spreadsheet ->disconnectWorksheets ();
474+
475+ // Verify the file structure contains both VML (for comments) and DrawingML (for shapes)
476+ $ zip = new ZipArchive ();
477+ $ zip ->open ($ tempFile );
478+
479+ // Check for VML drawing (used by comments)
480+ $ vmlDrawing = $ zip ->getFromName ('xl/drawings/vmlDrawing1.vml ' );
481+ self ::assertNotFalse ($ vmlDrawing , 'VML drawing for comments should exist ' );
482+ self ::assertStringContainsString ('urn:schemas-microsoft-com:vml ' , $ vmlDrawing , 'VML should contain VML namespace ' );
483+
484+ // Check for DrawingML (used by shapes/images)
485+ $ drawingXml = $ zip ->getFromName ('xl/drawings/drawing1.xml ' );
486+ self ::assertNotFalse ($ drawingXml , 'DrawingML for shapes/images should exist ' );
487+ self ::assertStringContainsString ('<xdr:sp ' , $ drawingXml , 'DrawingML should contain shape (preserved by pass-through) ' );
488+ self ::assertStringContainsString ('<xdr:pic ' , $ drawingXml , 'DrawingML should contain image ' );
489+
490+ // Check for comments XML (should contain both existing and new comments)
491+ $ commentsXml = $ zip ->getFromName ('xl/comments1.xml ' );
492+ self ::assertNotFalse ($ commentsXml , 'Comments XML should exist ' );
493+ self ::assertStringContainsString ('Test comment with pass-through ' , $ commentsXml , 'New comment (A1) should be in comments XML ' );
494+ self ::assertStringContainsString ($ existingCommentText , $ commentsXml , 'Existing comment (D1) should be preserved in comments XML ' );
495+
496+ $ zip ->close ();
497+ unlink ($ tempFile );
498+ }
443499}
0 commit comments