From 101a31bc2484e2fa01ccaefea7ed96b197586a6b Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sun, 4 Feb 2024 20:26:29 -0800 Subject: [PATCH] Phpstan Fixes Reduce baseline.neon to a single entry. --- phpstan-baseline.neon | 65 ------------------- .../Calculation/Calculation.php | 6 +- src/PhpSpreadsheet/Chart/DataSeriesValues.php | 5 +- .../Reader/Xlsx/ConditionalStyles.php | 4 +- src/PhpSpreadsheet/Reader/Xlsx/Styles.php | 4 +- src/PhpSpreadsheet/ReferenceHelper.php | 29 ++++++--- src/PhpSpreadsheet/Writer/Xlsx/Chart.php | 22 ++++--- .../Reader/Xlsx/Issue3767Test.php | 2 +- 8 files changed, 47 insertions(+), 90 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 66fa7fe72..c9762340b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,71 +1,6 @@ parameters: ignoreErrors: - - - message: "#^Strict comparison using \\=\\=\\= between mixed and null will always evaluate to false\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/Calculation.php - - message: "#^Binary operation \"/\" between float and array\\|float\\|int\\|string results in an error\\.$#" count: 1 path: src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php - - - - message: "#^Argument of an invalid type array\\|null supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/DataSeriesValues.php - - - - message: "#^Offset 0 does not exist on array\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/DataSeriesValues.php - - - - message: "#^Parameter \\#1 \\$value of function count expects array\\|Countable, array\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Chart/DataSeriesValues.php - - - - message: "#^Argument of an invalid type array\\\\|SimpleXMLElement\\|null supplied for foreach, only iterables are supported\\.$#" - count: 2 - path: src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php - - - - message: "#^Cannot access property \\$color on SimpleXMLElement\\|null\\.$#" - count: 2 - path: src/PhpSpreadsheet/Reader/Xlsx/Styles.php - - - - message: "#^Cannot call method beforeCellAddress\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\CellReferenceHelper\\|null\\.$#" - count: 1 - path: src/PhpSpreadsheet/ReferenceHelper.php - - - - message: "#^Cannot call method cellAddressInDeleteRange\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\CellReferenceHelper\\|null\\.$#" - count: 3 - path: src/PhpSpreadsheet/ReferenceHelper.php - - - - message: "#^Cannot call method updateCellReference\\(\\) on PhpOffice\\\\PhpSpreadsheet\\\\CellReferenceHelper\\|null\\.$#" - count: 4 - path: src/PhpSpreadsheet/ReferenceHelper.php - - - - message: "#^Argument of an invalid type array\\|null supplied for foreach, only iterables are supported\\.$#" - count: 3 - path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Writer\\\\Xlsx\\\\Chart\\:\\:getChartType\\(\\) should return array\\ but returns array\\, string\\|null\\>\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - - message: "#^Parameter \\#2 \\$array of function array_key_exists expects array, array\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Writer/Xlsx/Chart.php - - - - message: "#^Offset 0 does not exist on array\\|null\\.$#" - count: 1 - path: tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3767Test.php diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 27c60dc97..e6e692154 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -4648,10 +4648,12 @@ class Calculation } elseif (!is_numeric($token) && !is_object($token) && isset(self::BINARY_OPERATORS[$token])) { // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack // We must have two operands, error if we don't - if (($operand2Data = $stack->pop()) === null) { + $operand2Data = $stack->pop(); + if ($operand2Data === null) { return $this->raiseFormulaError('Internal error - Operand value missing from stack'); } - if (($operand1Data = $stack->pop()) === null) { + $operand1Data = $stack->pop(); + if ($operand1Data === null) { return $this->raiseFormulaError('Internal error - Operand value missing from stack'); } diff --git a/src/PhpSpreadsheet/Chart/DataSeriesValues.php b/src/PhpSpreadsheet/Chart/DataSeriesValues.php index ae6bf2248..3f105eeca 100644 --- a/src/PhpSpreadsheet/Chart/DataSeriesValues.php +++ b/src/PhpSpreadsheet/Chart/DataSeriesValues.php @@ -380,7 +380,7 @@ class DataSeriesValues extends Properties public function multiLevelCount(): int { $levelCount = 0; - foreach ($this->dataValues as $dataValueSet) { + foreach (($this->dataValues ?? []) as $dataValueSet) { $levelCount = max($levelCount, count($dataValueSet)); } @@ -400,6 +400,9 @@ class DataSeriesValues extends Properties */ public function getDataValue(): mixed { + if ($this->dataValues === null) { + return null; + } $count = count($this->dataValues); if ($count == 0) { return null; diff --git a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php index 5a3ae8a94..a26b9f633 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php @@ -262,7 +262,7 @@ class ConditionalStyles //conditionalFormatValueObjects $cfvoXml = $cfRule->dataBar->cfvo; $cfvoIndex = 0; - foreach ((count($cfvoXml) > 1 ? $cfvoXml : [$cfvoXml]) as $cfvo) { + foreach ((count($cfvoXml) > 1 ? $cfvoXml : [$cfvoXml]) as $cfvo) { //* @phpstan-ignore-line if ($cfvoIndex === 0) { $dataBar->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject((string) $cfvo['type'], (string) $cfvo['val'])); } @@ -320,7 +320,7 @@ class ConditionalStyles { if (isset($cfRule->extLst)) { $ns = $cfRule->extLst->getNamespaces(true); - foreach ((count($cfRule->extLst) > 0 ? $cfRule->extLst->ext : [$cfRule->extLst->ext]) as $ext) { + foreach ((count($cfRule->extLst) > 0 ? $cfRule->extLst->ext : [$cfRule->extLst->ext]) as $ext) { //* @phpstan-ignore-line $extId = (string) $ext->children($ns['x14'])->id; if (isset($conditionalFormattingRuleExtensions[$extId]) && (string) $ext['uri'] === '{B025F937-C7B1-47D3-B67F-A62EFF666E3E}') { $dataBar->setConditionalFormattingRuleExt($conditionalFormattingRuleExtensions[$extId]); diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php index 4646cde23..e35d6f3e8 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Styles.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Styles.php @@ -148,8 +148,8 @@ class Styles extends BaseParserClass } $fillStyle->setRotation((float) ($attr['degree'])); $gradientFill->registerXPathNamespace('sml', Namespaces::MAIN); - $fillStyle->getStartColor()->setARGB($this->readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color)); - $fillStyle->getEndColor()->setARGB($this->readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color)); + $fillStyle->getStartColor()->setARGB($this->readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color)); //* @phpstan-ignore-line + $fillStyle->getEndColor()->setARGB($this->readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color)); //* @phpstan-ignore-line } elseif ($fillStyleXml->patternFill) { $defaultFillStyle = Fill::FILL_NONE; if ($fillStyleXml->patternFill->fgColor) { diff --git a/src/PhpSpreadsheet/ReferenceHelper.php b/src/PhpSpreadsheet/ReferenceHelper.php index 1acedf116..f448473fb 100644 --- a/src/PhpSpreadsheet/ReferenceHelper.php +++ b/src/PhpSpreadsheet/ReferenceHelper.php @@ -131,7 +131,9 @@ class ReferenceHelper : uksort($aBreaks, [self::class, 'cellSort']); foreach ($aBreaks as $cellAddress => $value) { - if ($this->cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === true) { + /** @var CellReferenceHelper */ + $cellReferenceHelper = $this->cellReferenceHelper; + if ($cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === true) { // If we're deleting, then clear any defined breaks that are within the range // of rows/columns that we're deleting $worksheet->setBreak($cellAddress, Worksheet::BREAK_NONE); @@ -159,7 +161,9 @@ class ReferenceHelper foreach ($aComments as $cellAddress => &$value) { // Any comments inside a deleted range will be ignored - if ($this->cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === false) { + /** @var CellReferenceHelper */ + $cellReferenceHelper = $this->cellReferenceHelper; + if ($cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === false) { // Otherwise build a new array of comments indexed by the adjusted cell reference $newReference = $this->updateCellReference($cellAddress); $aNewComments[$newReference] = $value; @@ -185,7 +189,9 @@ class ReferenceHelper foreach ($aHyperlinkCollection as $cellAddress => $value) { $newReference = $this->updateCellReference($cellAddress); - if ($this->cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === true) { + /** @var CellReferenceHelper */ + $cellReferenceHelper = $this->cellReferenceHelper; + if ($cellReferenceHelper->cellAddressInDeleteRange($cellAddress) === true) { $worksheet->setHyperlink($cellAddress, null); } elseif ($cellAddress !== $newReference) { $worksheet->setHyperlink($newReference, $value); @@ -217,9 +223,11 @@ class ReferenceHelper $conditions = $cfRule->getConditions(); foreach ($conditions as &$condition) { if (is_string($condition)) { + /** @var CellReferenceHelper */ + $cellReferenceHelper = $this->cellReferenceHelper; $condition = $this->updateFormulaReferences( $condition, - $this->cellReferenceHelper->beforeCellAddress(), + $cellReferenceHelper->beforeCellAddress(), $numberOfColumns, $numberOfRows, $worksheet->getTitle(), @@ -848,7 +856,10 @@ class ReferenceHelper // Is it a range or a single cell? if (!Coordinate::coordinateIsRange($cellReference)) { // Single cell - return $this->cellReferenceHelper->updateCellReference($cellReference, $includeAbsoluteReferences, $onlyAbsoluteReferences); + /** @var CellReferenceHelper */ + $cellReferenceHelper = $this->cellReferenceHelper; + + return $cellReferenceHelper->updateCellReference($cellReference, $includeAbsoluteReferences, $onlyAbsoluteReferences); } // Range @@ -950,16 +961,18 @@ class ReferenceHelper for ($i = 0; $i < $ic; ++$i) { $jc = count($range[$i]); for ($j = 0; $j < $jc; ++$j) { + /** @var CellReferenceHelper */ + $cellReferenceHelper = $this->cellReferenceHelper; if (ctype_alpha($range[$i][$j])) { $range[$i][$j] = Coordinate::coordinateFromString( - $this->cellReferenceHelper->updateCellReference($range[$i][$j] . '1', $includeAbsoluteReferences, $onlyAbsoluteReferences) + $cellReferenceHelper->updateCellReference($range[$i][$j] . '1', $includeAbsoluteReferences, $onlyAbsoluteReferences) )[0]; } elseif (ctype_digit($range[$i][$j])) { $range[$i][$j] = Coordinate::coordinateFromString( - $this->cellReferenceHelper->updateCellReference('A' . $range[$i][$j], $includeAbsoluteReferences, $onlyAbsoluteReferences) + $cellReferenceHelper->updateCellReference('A' . $range[$i][$j], $includeAbsoluteReferences, $onlyAbsoluteReferences) )[1]; } else { - $range[$i][$j] = $this->cellReferenceHelper->updateCellReference($range[$i][$j], $includeAbsoluteReferences, $onlyAbsoluteReferences); + $range[$i][$j] = $cellReferenceHelper->updateCellReference($range[$i][$j], $includeAbsoluteReferences, $onlyAbsoluteReferences); } } } diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index cd26fdf9f..ca16557a8 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -1064,16 +1064,20 @@ class Chart extends WriterPart $groupCount = $plotArea->getPlotGroupCount(); if ($groupCount == 1) { - $chartType = [$plotArea->getPlotGroupByIndex(0)->getPlotType()]; + $plotType = $plotArea->getPlotGroupByIndex(0)->getPlotType(); + $chartType = ($plotType === null) ? [] : [$plotType]; } else { $chartTypes = []; for ($i = 0; $i < $groupCount; ++$i) { - $chartTypes[] = $plotArea->getPlotGroupByIndex($i)->getPlotType(); + $plotType = $plotArea->getPlotGroupByIndex($i)->getPlotType(); + if ($plotType !== null) { + $chartTypes[] = $plotType; + } } $chartType = array_unique($chartTypes); - if (count($chartTypes) == 0) { - throw new WriterException('Chart is not yet implemented'); - } + } + if (count($chartType) == 0) { + throw new WriterException('Chart is not yet implemented'); } return $chartType; @@ -1171,7 +1175,7 @@ class Chart extends WriterPart if ($plotSeriesValues !== false && in_array($groupType, self::CUSTOM_COLOR_TYPES, true)) { $fillColorValues = $plotSeriesValues->getFillColorObject(); if ($fillColorValues !== null && is_array($fillColorValues)) { - foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) { + foreach (($plotSeriesValues->getDataValues() ?? []) as $dataKey => $dataValue) { $this->writePlotSeriesValuesElement($objWriter, $dataKey, $fillColorValues[$dataKey] ?? null); } } @@ -1435,7 +1439,7 @@ class Chart extends WriterPart $objWriter->writeAttribute('val', (string) $plotSeriesLabel->getPointCount()); $objWriter->endElement(); - foreach ($plotSeriesLabel->getDataValues() as $plotLabelKey => $plotLabelValue) { + foreach (($plotSeriesLabel->getDataValues() ?? []) as $plotLabelKey => $plotLabelValue) { $objWriter->startElement('c:pt'); $objWriter->writeAttribute('idx', $plotLabelKey); @@ -1477,7 +1481,7 @@ class Chart extends WriterPart for ($level = 0; $level < $levelCount; ++$level) { $objWriter->startElement('c:lvl'); - foreach ($plotSeriesValues->getDataValues() as $plotSeriesKey => $plotSeriesValue) { + foreach (($plotSeriesValues->getDataValues() ?? []) as $plotSeriesKey => $plotSeriesValue) { if (isset($plotSeriesValue[$level])) { $objWriter->startElement('c:pt'); $objWriter->writeAttribute('idx', $plotSeriesKey); @@ -1505,7 +1509,7 @@ class Chart extends WriterPart $count = $plotSeriesValues->getPointCount(); $source = $plotSeriesValues->getDataSource(); $values = $plotSeriesValues->getDataValues(); - if ($count > 1 || ($count === 1 && array_key_exists(0, $values) && "=$source" !== (string) $values[0])) { + if ($count > 1 || ($count === 1 && is_array($values) && array_key_exists(0, $values) && "=$source" !== (string) $values[0])) { $objWriter->startElement('c:' . $dataType . 'Cache'); if (($groupType != DataSeries::TYPE_PIECHART) && ($groupType != DataSeries::TYPE_PIECHART_3D) && ($groupType != DataSeries::TYPE_DONUTCHART)) { diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3767Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3767Test.php index 9f8c3266c..ae6edfe41 100644 --- a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3767Test.php +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue3767Test.php @@ -82,7 +82,7 @@ class Issue3767Test extends AbstractFunctional // I can't find that anywhere in the Xml. self::assertSame('', $charts[0]?->getTitle()?->getCaptionText()); // Just test anything on the chart. - self::assertSame($sheet->getCell('B2')->getValue(), $charts[0]->getPlotArea()?->getPlotGroup()[0]->getPlotValues()[0]->getDataValues()[0]); + self::assertSame($sheet->getCell('B2')->getValue(), $charts[0]->getPlotArea()?->getPlotGroup()[0]?->getPlotValues()[0]?->getDataValues()[0] ?? null); $reloadedSpreadsheet->disconnectWorksheets(); } }