@@ -440,4 +440,94 @@ public function testDrawingPassThroughEnabledFlagIsSetCorrectly(): void
440440
441441 $ spreadsheet2 ->disconnectWorksheets ();
442442 }
443+
444+ /**
445+ * Test that VML drawings (used by comments) and DrawingML (used by shapes/images)
446+ * coexist without interference when pass-through is enabled.
447+ * This addresses the concern that comments use the drawings folder with VML files.
448+ * The template file already contains a comment in D1, so this test verifies that
449+ * existing comments are preserved AND new comments can be added.
450+ */
451+ public function testCommentsAndPassThroughCoexist (): void
452+ {
453+ // Load file with drawings (image + shape) and enable pass-through
454+ // Note: The template already contains a comment in D1
455+ $ reader = new XlsxReader ();
456+ $ reader ->setEnableDrawingPassThrough (true );
457+ $ spreadsheet = $ reader ->load (self ::TEMPLATE );
458+
459+ $ sheet = $ spreadsheet ->getActiveSheet ();
460+
461+ // Verify the existing comment is loaded
462+ $ existingComment = $ sheet ->getComment ('D1 ' );
463+ $ existingCommentText = $ existingComment ->getText ()->getPlainText ();
464+ self ::assertNotEmpty ($ existingCommentText , 'Template should contain a comment in D1 ' );
465+
466+ // Add a new comment to the sheet
467+ $ sheet ->getComment ('A1 ' )->getText ()->createText ('Test comment with pass-through ' );
468+ $ sheet ->getComment ('A1 ' )->setAuthor ('Test Author ' );
469+
470+ // Save the file
471+ $ tempFile = File::temporaryFilename ();
472+ $ writer = new XlsxWriter ($ spreadsheet );
473+ $ writer ->save ($ tempFile );
474+ $ spreadsheet ->disconnectWorksheets ();
475+
476+ // Verify the file structure contains both VML (for comments) and DrawingML (for shapes)
477+ $ zip = new ZipArchive ();
478+ $ zip ->open ($ tempFile );
479+
480+ // Check for VML drawing (used by comments)
481+ $ vmlDrawing = $ zip ->getFromName ('xl/drawings/vmlDrawing1.vml ' );
482+ self ::assertNotFalse ($ vmlDrawing , 'VML drawing for comments should exist ' );
483+ self ::assertStringContainsString ('urn:schemas-microsoft-com:vml ' , $ vmlDrawing , 'VML should contain VML namespace ' );
484+
485+ // Check for DrawingML (used by shapes/images)
486+ $ drawingXml = $ zip ->getFromName ('xl/drawings/drawing1.xml ' );
487+ self ::assertNotFalse ($ drawingXml , 'DrawingML for shapes/images should exist ' );
488+ self ::assertStringContainsString ('<xdr:sp ' , $ drawingXml , 'DrawingML should contain shape (preserved by pass-through) ' );
489+ self ::assertStringContainsString ('<xdr:pic ' , $ drawingXml , 'DrawingML should contain image ' );
490+
491+ // Check for comments XML (should contain both existing and new comments)
492+ $ commentsXml = $ zip ->getFromName ('xl/comments1.xml ' );
493+ self ::assertNotFalse ($ commentsXml , 'Comments XML should exist ' );
494+ self ::assertStringContainsString ('Test comment with pass-through ' , $ commentsXml , 'New comment (A1) should be in comments XML ' );
495+ self ::assertStringContainsString ($ existingCommentText , $ commentsXml , 'Existing comment (D1) should be preserved in comments XML ' );
496+
497+ $ zip ->close ();
498+
499+ // Reload and verify everything is still intact
500+ $ reader2 = new XlsxReader ();
501+ $ reader2 ->setEnableDrawingPassThrough (true );
502+ $ spreadsheet2 = $ reader2 ->load ($ tempFile );
503+ $ sheet2 = $ spreadsheet2 ->getActiveSheet ();
504+
505+ // Verify both comments are preserved (existing and new)
506+ $ existingCommentReloaded = $ sheet2 ->getComment ('D1 ' );
507+ self ::assertSame ($ existingCommentText , $ existingCommentReloaded ->getText ()->getPlainText (), 'Existing comment (D1) should be preserved after reload ' );
508+
509+ $ newComment = $ sheet2 ->getComment ('A1 ' );
510+ self ::assertSame ('Test comment with pass-through ' , $ newComment ->getText ()->getPlainText (), 'New comment (A1) should be preserved after reload ' );
511+
512+ // Verify drawings are still in collection (image only, shape is in pass-through XML)
513+ $ drawings = $ sheet2 ->getDrawingCollection ();
514+ self ::assertCount (1 , $ drawings , 'Drawing collection should contain the image ' );
515+
516+ // Verify pass-through data still contains shapes
517+ $ unparsedData = $ spreadsheet2 ->getUnparsedLoadedData ();
518+ $ codeName = $ sheet2 ->getCodeName ();
519+ self ::assertArrayHasKey ('sheets ' , $ unparsedData );
520+ self ::assertIsArray ($ unparsedData ['sheets ' ]);
521+ self ::assertArrayHasKey ($ codeName , $ unparsedData ['sheets ' ]);
522+ self ::assertIsArray ($ unparsedData ['sheets ' ][$ codeName ]);
523+ self ::assertArrayHasKey ('Drawings ' , $ unparsedData ['sheets ' ][$ codeName ]);
524+ $ drawings = $ unparsedData ['sheets ' ][$ codeName ]['Drawings ' ];
525+ self ::assertIsArray ($ drawings );
526+ $ drawingXmlFromData = reset ($ drawings );
527+ self ::assertIsString ($ drawingXmlFromData );
528+ self ::assertStringContainsString ('<xdr:sp ' , $ drawingXmlFromData , 'Pass-through XML should still contain shapes ' );
529+
530+ $ spreadsheet2 ->disconnectWorksheets ();
531+ unlink ($ tempFile );
532+ }
443533}
0 commit comments