Skip to content

Commit f17e166

Browse files
authored
Break Some More Circular References (#3716)
* Break Some More Circular References After identifying a circular reference between Worksheet and Table, which could lead to memory leaks, I identified several other similar relationships. I have added a destructor, or added added code to an existing destructor, for those possibilities. This didn't actually lead to any lowering of the memory usage of the unit test suite, so maybe there's no practical benefit, but it does seem like it should be theoretically useful. I am not aware of any practical way to unit test a destructor, although the added code will be exercised many times in most of our unit tests. The only change here not involving a destructor is to `Worksheet::addChart` (it came to my attention because Worksheet and Chart have a circular reference). It is currently defined with two arguments, the second allowing you to place the chart in a specific location in the containing ArrayObject. However, as Phpstan and Scrutinizer both warn, the code to support this option will fail if it is ever executed (can't use array_splice on an ArrayObject); needless to say, this possibility is not exercised when executing the test suite. It could be made to work, but I really can't see any kind of use case to support this parameter. So I'm removing the second parameter. In theory, this is a breaking change, but, since the code can never work, in practice it won't be. * Update Worksheet.php * Update Worksheet.php
1 parent 72b7702 commit f17e166

File tree

11 files changed

+42
-15
lines changed

11 files changed

+42
-15
lines changed

src/PhpSpreadsheet/Cell/CellAddress.php

+5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public function __construct(string $cellAddress, ?Worksheet $worksheet = null)
2525
$this->worksheet = $worksheet;
2626
}
2727

28+
public function __destruct()
29+
{
30+
$this->worksheet = null;
31+
}
32+
2833
private static function validateColumnAndRow(mixed $columnId, mixed $rowId): void
2934
{
3035
if (!is_numeric($columnId) || $columnId <= 0 || !is_numeric($rowId) || $rowId <= 0) {

src/PhpSpreadsheet/Cell/ColumnRange.php

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ public function __construct(string $from, ?string $to = null, ?Worksheet $worksh
2222
$this->worksheet = $worksheet;
2323
}
2424

25+
public function __destruct()
26+
{
27+
$this->worksheet = null;
28+
}
29+
2530
public static function fromColumnIndexes(int $from, int $to, ?Worksheet $worksheet = null): self
2631
{
2732
return new self(Coordinate::stringFromColumnIndex($from), Coordinate::stringFromColumnIndex($to), $worksheet);

src/PhpSpreadsheet/Cell/RowRange.php

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ public function __construct(int $from, ?int $to = null, ?Worksheet $worksheet =
1919
$this->worksheet = $worksheet;
2020
}
2121

22+
public function __destruct()
23+
{
24+
$this->worksheet = null;
25+
}
26+
2227
public static function fromArray(array $array, ?Worksheet $worksheet = null): self
2328
{
2429
[$from, $to] = $array;

src/PhpSpreadsheet/Chart/Chart.php

+5
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ public function __construct(mixed $name, ?Title $title = null, ?Legend $legend =
160160
$this->borderLines = new GridLines();
161161
}
162162

163+
public function __destruct()
164+
{
165+
$this->worksheet = null;
166+
}
167+
163168
/**
164169
* Get Name.
165170
*

src/PhpSpreadsheet/Collection/Cells.php

+1
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ public function unsetWorksheetCells(): void
453453
public function __destruct()
454454
{
455455
$this->cache->deleteMultiple($this->getAllCacheKeys());
456+
$this->parent = null;
456457
}
457458

458459
/**

src/PhpSpreadsheet/DefinedName.php

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ public function __construct(
6666
$this->isFormula = self::testIfFormula($this->value);
6767
}
6868

69+
public function __destruct()
70+
{
71+
$this->worksheet = null;
72+
$this->scope = null;
73+
}
74+
6975
/**
7076
* Create a new defined name, either a range or a formula.
7177
*/

src/PhpSpreadsheet/Spreadsheet.php

+1
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ public function __destruct()
500500
$this->calculationEngine = null;
501501
$this->cellXfCollection = [];
502502
$this->cellStyleXfCollection = [];
503+
$this->definedNames = [];
503504
}
504505

505506
/**

src/PhpSpreadsheet/Worksheet/AutoFilter.php

+5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ public function __construct($range = '', ?Worksheet $worksheet = null)
6464
$this->workSheet = $worksheet;
6565
}
6666

67+
public function __destruct()
68+
{
69+
$this->workSheet = null;
70+
}
71+
6772
/**
6873
* Get AutoFilter Parent Worksheet.
6974
*

src/PhpSpreadsheet/Worksheet/BaseDrawing.php

+5
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ public function __construct()
164164
$this->imageIndex = self::$imageCounter;
165165
}
166166

167+
public function __destruct()
168+
{
169+
$this->worksheet = null;
170+
}
171+
167172
public function getImageIndex(): int
168173
{
169174
return $this->imageIndex;

src/PhpSpreadsheet/Worksheet/MemoryDrawing.php

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public function __destruct()
6666
@imagedestroy($this->imageResource);
6767
$this->imageResource = null;
6868
}
69+
$this->worksheet = null;
6970
}
7071

7172
public function __clone()

src/PhpSpreadsheet/Worksheet/Worksheet.php

+3-15
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,7 @@ public function __destruct()
423423
Calculation::getInstance($this->parent)->clearCalculationCacheForWorksheet($this->title);
424424

425425
$this->disconnectCells();
426-
$this->rowDimensions = [];
427-
$this->tableCollection = new ArrayObject();
426+
unset($this->rowDimensions, $this->columnDimensions, $this->tableCollection, $this->drawingCollection, $this->chartCollection, $this->autoFilter);
428427
}
429428

430429
/**
@@ -589,21 +588,10 @@ public function getChartCollection()
589588
return $this->chartCollection;
590589
}
591590

592-
/**
593-
* Add chart.
594-
*
595-
* @param null|int $chartIndex Index where chart should go (0,1,..., or null for last)
596-
*/
597-
public function addChart(Chart $chart, $chartIndex = null): Chart
591+
public function addChart(Chart $chart): Chart
598592
{
599593
$chart->setWorksheet($this);
600-
if ($chartIndex === null) {
601-
$this->chartCollection[] = $chart;
602-
} else {
603-
// Insert the chart at the requested index
604-
// @phpstan-ignore-next-line
605-
array_splice(/** @scrutinizer ignore-type */ $this->chartCollection, $chartIndex, 0, [$chart]);
606-
}
594+
$this->chartCollection[] = $chart;
607595

608596
return $chart;
609597
}

0 commit comments

Comments
 (0)