Skip to content

Commit 96f2fd7

Browse files
committed
add fix and test
1 parent 30c1a96 commit 96f2fd7

File tree

2 files changed

+127
-3
lines changed

2 files changed

+127
-3
lines changed

src/PhpSpreadsheet/Writer/Xlsx/Drawing.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,21 @@ class Drawing extends WriterPart
2424
public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, bool $includeCharts = false): string
2525
{
2626
// Check if we have stored drawing XML (pass-through for unsupported elements)
27-
$unparsedLoadedData = $worksheet->getParentOrThrow()->getUnparsedLoadedData();
28-
if (isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['Drawings'])) {
29-
return reset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['Drawings']);
27+
// Only use pass-through if no drawings have been added/modified programmatically
28+
$drawingCollection = $worksheet->getDrawingCollection();
29+
if (count($drawingCollection) === 0) {
30+
$unparsedLoadedData = $worksheet->getParentOrThrow()->getUnparsedLoadedData();
31+
$codeName = $worksheet->getCodeName();
32+
if (
33+
isset($unparsedLoadedData['sheets'], $unparsedLoadedData['sheets'][$codeName], $unparsedLoadedData['sheets'][$codeName]['Drawings']) &&
34+
is_array($unparsedLoadedData['sheets'][$codeName]['Drawings'])
35+
) {
36+
$drawings = $unparsedLoadedData['sheets'][$codeName]['Drawings'];
37+
$firstDrawing = reset($drawings);
38+
if (is_string($firstDrawing)) {
39+
return $firstDrawing;
40+
}
41+
}
3042
}
3143

3244
// Create XML writer
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
6+
7+
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
8+
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
9+
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
10+
11+
class DrawingPassThroughTest extends AbstractFunctional
12+
{
13+
private const DIRECTORY = 'tests/data/Writer/XLSX/';
14+
private const TEMPLATE = self::DIRECTORY . 'issue.3843a.template.xlsx';
15+
private const IMAGE = self::DIRECTORY . 'issue.3843a.jpg';
16+
17+
/**
18+
* Test that unsupported drawing elements (shapes, textboxes) are preserved
19+
* when pass-through is enabled and no drawings are modified.
20+
*/
21+
public function testDrawingPassThroughPreservesUnsupportedElements(): void
22+
{
23+
// Load with pass-through enabled
24+
$reader = new XlsxReader();
25+
$reader->setEnableDrawingPassThrough(true);
26+
$spreadsheet = $reader->load(self::TEMPLATE);
27+
28+
$sheet = $spreadsheet->getActiveSheet();
29+
30+
// Verify that drawing collection is empty (unsupported elements not parsed)
31+
$drawings = $sheet->getDrawingCollection();
32+
self::assertCount(0, $drawings, 'Drawing collection should be empty for unsupported elements');
33+
34+
// Verify that unparsed data contains the original drawing XML
35+
$unparsedData = $spreadsheet->getUnparsedLoadedData();
36+
$codeName = $sheet->getCodeName();
37+
self::assertArrayHasKey('sheets', $unparsedData);
38+
self::assertIsArray($unparsedData['sheets']);
39+
self::assertArrayHasKey($codeName, $unparsedData['sheets']);
40+
self::assertIsArray($unparsedData['sheets'][$codeName]);
41+
self::assertArrayHasKey('Drawings', $unparsedData['sheets'][$codeName]);
42+
43+
// Save and reload
44+
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
45+
$spreadsheet->disconnectWorksheets();
46+
47+
// Verify that the drawing XML is still present after reload
48+
$reloadedUnparsedData = $reloadedSpreadsheet->getUnparsedLoadedData();
49+
$reloadedCodeName = $reloadedSpreadsheet->getActiveSheet()->getCodeName();
50+
self::assertArrayHasKey('sheets', $reloadedUnparsedData);
51+
self::assertIsArray($reloadedUnparsedData['sheets']);
52+
self::assertArrayHasKey($reloadedCodeName, $reloadedUnparsedData['sheets']);
53+
self::assertIsArray($reloadedUnparsedData['sheets'][$reloadedCodeName]);
54+
self::assertArrayHasKey('Drawings', $reloadedUnparsedData['sheets'][$reloadedCodeName]);
55+
56+
$reloadedSpreadsheet->disconnectWorksheets();
57+
}
58+
59+
/**
60+
* Test that pass-through is NOT used when drawings are added programmatically.
61+
*/
62+
public function testDrawingPassThroughDisabledWhenDrawingsAdded(): void
63+
{
64+
// Load without pass-through (doesn't matter since we add drawings)
65+
$reader = new XlsxReader();
66+
$reader->setEnableDrawingPassThrough(false);
67+
$spreadsheet = $reader->load(self::TEMPLATE);
68+
69+
$sheet = $spreadsheet->getActiveSheet();
70+
71+
// Add a drawing programmatically
72+
$drawing = new Drawing();
73+
$drawing->setName('TestDrawing');
74+
$drawing->setPath(self::IMAGE);
75+
$drawing->setCoordinates('A1');
76+
$drawing->setWorksheet($sheet);
77+
78+
// Verify that drawing collection now has 1 element
79+
$drawings = $sheet->getDrawingCollection();
80+
self::assertCount(1, $drawings, 'Drawing collection should contain the added drawing');
81+
82+
// Save and reload
83+
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
84+
$spreadsheet->disconnectWorksheets();
85+
86+
// Verify that the new drawing is present after reload
87+
$reloadedDrawings = $reloadedSpreadsheet->getActiveSheet()->getDrawingCollection();
88+
self::assertCount(1, $reloadedDrawings, 'Reloaded spreadsheet should contain the added drawing');
89+
$firstDrawing = $reloadedDrawings[0] ?? null;
90+
self::assertNotNull($firstDrawing);
91+
self::assertSame('TestDrawing', $firstDrawing->getName());
92+
93+
$reloadedSpreadsheet->disconnectWorksheets();
94+
}
95+
96+
public function testDrawingPassThroughGetterSetter(): void
97+
{
98+
$reader = new XlsxReader();
99+
100+
// Default should be false
101+
self::assertFalse($reader->getEnableDrawingPassThrough());
102+
103+
// Enable pass-through
104+
$result = $reader->setEnableDrawingPassThrough(true);
105+
self::assertInstanceOf(XlsxReader::class, $result);
106+
self::assertTrue($reader->getEnableDrawingPassThrough());
107+
108+
// Disable pass-through
109+
$reader->setEnableDrawingPassThrough(false);
110+
self::assertFalse($reader->getEnableDrawingPassThrough());
111+
}
112+
}

0 commit comments

Comments
 (0)