diff --git a/CHANGELOG.md b/CHANGELOG.md index fe190f74..290474a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,13 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org). ### Added -- Add point size option for scatter charts +- Add point size option for scatter charts [Issue #2298](https://github.com/PHPOffice/PhpSpreadsheet/issues/2298) [PR #2801](https://github.com/PHPOffice/PhpSpreadsheet/pull/2801) - Basic support for Xlsx reading/writing Chart Sheets [PR #2830](https://github.com/PHPOffice/PhpSpreadsheet/pull/2830) Note that a ChartSheet is still only written as a normal Worksheet containing a single chart, not as an actual ChartSheet. - Added Worksheet visibility in Ods Reader [PR #2851](https://github.com/PHPOffice/PhpSpreadsheet/pull/2851) and Gnumeric Reader [PR #2853](https://github.com/PHPOffice/PhpSpreadsheet/pull/2853) - Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850) +- Allow Csv Reader to treat string as contents of file [Issue #1285](https://github.com/PHPOffice/PhpSpreadsheet/issues/1285) [PR #2792](https://github.com/PHPOffice/PhpSpreadsheet/pull/2792) +- Allow Csv Reader to store null string rather than leave cell empty [Issue #2840](https://github.com/PHPOffice/PhpSpreadsheet/issues/2840) [PR #2842](https://github.com/PHPOffice/PhpSpreadsheet/pull/2842) ### Changed @@ -36,6 +38,10 @@ and this project adheres to [Semantic Versioning](https://semver.org). - Xls Reader resolving absolute named ranges to relative ranges [Issue #2826](https://github.com/PHPOffice/PhpSpreadsheet/issues/2826) [PR #2827](https://github.com/PHPOffice/PhpSpreadsheet/pull/2827) - Null value handling in the Excel Math/Trig PRODUCT() function [Issue #2833](https://github.com/PHPOffice/PhpSpreadsheet/issues/2833) [PR #2834](https://github.com/PHPOffice/PhpSpreadsheet/pull/2834) - Invalid Print Area defined in Xlsx corrupts internal storage of print area [Issue #2848](https://github.com/PHPOffice/PhpSpreadsheet/issues/2848) [PR #2849](https://github.com/PHPOffice/PhpSpreadsheet/pull/2849) +- Time interval formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772) +- Copy from Xls(x) to Html/Pdf loses drawings [PR #2788](https://github.com/PHPOffice/PhpSpreadsheet/pull/2788) +- Html Reader converting cell containing 0 to null string [Issue #2810](https://github.com/PHPOffice/PhpSpreadsheet/issues/2810) [PR #2813](https://github.com/PHPOffice/PhpSpreadsheet/pull/2813) +- Many fixes for Charts, especially, but not limited to, Scatter, Bubble, and Surface charts. [Issue #2762](https://github.com/PHPOffice/PhpSpreadsheet/issues/2762) [Issue #2299](https://github.com/PHPOffice/PhpSpreadsheet/issues/2299) [Issue #2700](https://github.com/PHPOffice/PhpSpreadsheet/issues/2700) [Issue #2817](https://github.com/PHPOffice/PhpSpreadsheet/issues/2817) [Issue #2763](https://github.com/PHPOffice/PhpSpreadsheet/issues/2763) [PR #2828](https://github.com/PHPOffice/PhpSpreadsheet/pull/2828) [PR #2841](https://github.com/PHPOffice/PhpSpreadsheet/pull/2841) [PR #2846](https://github.com/PHPOffice/PhpSpreadsheet/pull/2846) [PR #2852](https://github.com/PHPOffice/PhpSpreadsheet/pull/2852) ## 1.23.0 - 2022-04-24 diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f031bfe6..a8da7936 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -2515,136 +2515,6 @@ parameters: count: 1 path: src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has parameter \\$chartDetail with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has parameter \\$namespacesChartMeta with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeries\\(\\) has parameter \\$plotType with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has parameter \\$namespacesChartMeta with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValueSet\\(\\) has parameter \\$seriesDetail with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValues\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValues\\(\\) has parameter \\$dataType with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValues\\(\\) has parameter \\$seriesValueSet with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValuesMultiLevel\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValuesMultiLevel\\(\\) has parameter \\$dataType with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartDataSeriesValuesMultiLevel\\(\\) has parameter \\$seriesValueSet with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartLayoutDetails\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartLayoutDetails\\(\\) has parameter \\$chartDetail with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartLayoutDetails\\(\\) has parameter \\$namespacesChartMeta with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:chartTitle\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:parseRichText\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readChartAttributes\\(\\) has no return type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\Chart\\:\\:readChartAttributes\\(\\) has parameter \\$chartDetail with no type specified\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Parameter \\#1 \\$position of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend constructor expects string, bool\\|float\\|int\\|string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Parameter \\#3 \\$overlay of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Legend constructor expects bool, bool\\|float\\|int\\|string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Parameter \\#3 \\$plotOrder of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeries constructor expects array\\, array\\ given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Parameter \\#4 \\$pointCount of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeriesValues constructor expects int, null given\\.$#" - count: 4 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Parameter \\#6 \\$displayBlanksAs of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\Chart constructor expects string, bool\\|float\\|int\\|string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - - - message: "#^Parameter \\#7 \\$plotDirection of class PhpOffice\\\\PhpSpreadsheet\\\\Chart\\\\DataSeries constructor expects string\\|null, bool\\|float\\|int\\|string\\|null given\\.$#" - count: 1 - path: src/PhpSpreadsheet/Reader/Xlsx/Chart.php - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\Xlsx\\\\ColumnAndRowAttributes\\:\\:isFilteredColumn\\(\\) has no return type specified\\.$#" count: 1 diff --git a/src/PhpSpreadsheet/Reader/Xlsx.php b/src/PhpSpreadsheet/Reader/Xlsx.php index 8eadb39c..df2b36c1 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/src/PhpSpreadsheet/Reader/Xlsx.php @@ -1645,7 +1645,8 @@ class Xlsx extends BaseReader if ($this->includeCharts) { $chartEntryRef = ltrim((string) $contentType['PartName'], '/'); $chartElements = $this->loadZip($chartEntryRef); - $objChart = Chart::readChart($chartElements, basename($chartEntryRef, '.xml')); + $chartReader = new Chart(); + $objChart = $chartReader->readChart($chartElements, basename($chartEntryRef, '.xml')); if (isset($charts[$chartEntryRef])) { $chartPositionRef = $charts[$chartEntryRef]['sheet'] . '!' . $charts[$chartEntryRef]['id']; if (isset($chartDetails[$chartPositionRef])) { diff --git a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php index e3498e20..f6b1edd5 100644 --- a/src/PhpSpreadsheet/Reader/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Reader/Xlsx/Chart.php @@ -16,6 +16,18 @@ use SimpleXMLElement; class Chart { + /** @var string */ + private $cNamespace; + + /** @var string */ + private $aNamespace; + + public function __construct(string $cNamespace = Namespaces::CHART, string $aNamespace = Namespaces::DRAWINGML) + { + $this->cNamespace = $cNamespace; + $this->aNamespace = $aNamespace; + } + /** * @param string $name * @param string $format @@ -47,10 +59,9 @@ class Chart * * @return \PhpOffice\PhpSpreadsheet\Chart\Chart */ - public static function readChart(SimpleXMLElement $chartElements, $chartName) + public function readChart(SimpleXMLElement $chartElements, $chartName) { - $namespacesChartMeta = $chartElements->getNamespaces(true); - $chartElementsC = $chartElements->children($namespacesChartMeta['c']); + $chartElementsC = $chartElements->children($this->cNamespace); $XaxisLabel = $YaxisLabel = $legend = $title = null; $dispBlanksAs = $plotVisOnly = null; @@ -60,7 +71,7 @@ class Chart switch ($chartElementKey) { case 'chart': foreach ($chartElement as $chartDetailsKey => $chartDetails) { - $chartDetailsC = $chartDetails->children($namespacesChartMeta['c']); + $chartDetailsC = $chartDetails->children($this->cNamespace); switch ($chartDetailsKey) { case 'view3D': $rotX = self::getAttribute($chartDetails->rotX, 'val', 'integer'); @@ -75,24 +86,24 @@ class Chart foreach ($chartDetails as $chartDetailKey => $chartDetail) { switch ($chartDetailKey) { case 'layout': - $plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta); + $plotAreaLayout = $this->chartLayoutDetails($chartDetail); break; case 'catAx': if (isset($chartDetail->title)) { - $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta); + $XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); } break; case 'dateAx': if (isset($chartDetail->title)) { - $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta); + $XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); } break; case 'valAx': if (isset($chartDetail->title, $chartDetail->axPos)) { - $axisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta); + $axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); $axPos = self::getAttribute($chartDetail->axPos, 'val', 'string'); switch ($axPos) { @@ -113,70 +124,72 @@ class Chart case 'barChart': case 'bar3DChart': $barDirection = self::getAttribute($chartDetail->barDir, 'val', 'string'); - $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); - $plotSer->setPlotDirection($barDirection); + $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); + $plotSer->setPlotDirection("$barDirection"); $plotSeries[] = $plotSer; - $plotAttributes = self::readChartAttributes($chartDetail); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'lineChart': case 'line3DChart': - $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); - $plotAttributes = self::readChartAttributes($chartDetail); + $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'areaChart': case 'area3DChart': - $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); - $plotAttributes = self::readChartAttributes($chartDetail); + $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'doughnutChart': case 'pieChart': case 'pie3DChart': $explosion = isset($chartDetail->ser->explosion); - $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); - $plotSer->setPlotStyle($explosion); + $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); + $plotSer->setPlotStyle("$explosion"); $plotSeries[] = $plotSer; - $plotAttributes = self::readChartAttributes($chartDetail); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'scatterChart': + /** @var string */ $scatterStyle = self::getAttribute($chartDetail->scatterStyle, 'val', 'string'); - $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); + $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); $plotSer->setPlotStyle($scatterStyle); $plotSeries[] = $plotSer; - $plotAttributes = self::readChartAttributes($chartDetail); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'bubbleChart': $bubbleScale = self::getAttribute($chartDetail->bubbleScale, 'val', 'integer'); - $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); - $plotSer->setPlotStyle($bubbleScale); + $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); + $plotSer->setPlotStyle("$bubbleScale"); $plotSeries[] = $plotSer; - $plotAttributes = self::readChartAttributes($chartDetail); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'radarChart': + /** @var string */ $radarStyle = self::getAttribute($chartDetail->radarStyle, 'val', 'string'); - $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); + $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); $plotSer->setPlotStyle($radarStyle); $plotSeries[] = $plotSer; - $plotAttributes = self::readChartAttributes($chartDetail); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'surfaceChart': case 'surface3DChart': $wireFrame = self::getAttribute($chartDetail->wireframe, 'val', 'boolean'); - $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); - $plotSer->setPlotStyle($wireFrame); + $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); + $plotSer->setPlotStyle("$wireFrame"); $plotSeries[] = $plotSer; - $plotAttributes = self::readChartAttributes($chartDetail); + $plotAttributes = $this->readChartAttributes($chartDetail); break; case 'stockChart': - $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); - $plotAttributes = self::readChartAttributes($plotAreaLayout); + $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); + $plotAttributes = $this->readChartAttributes($plotAreaLayout); break; } @@ -185,7 +198,7 @@ class Chart $plotAreaLayout = new Layout(); } $plotArea = new PlotArea($plotAreaLayout, $plotSeries); - self::setChartAttributes($plotAreaLayout, $plotAttributes); + $this->setChartAttributes($plotAreaLayout, $plotAttributes); break; case 'plotVisOnly': @@ -197,7 +210,7 @@ class Chart break; case 'title': - $title = self::chartTitle($chartDetails, $namespacesChartMeta); + $title = $this->chartTitle($chartDetails); break; case 'legend': @@ -215,19 +228,19 @@ class Chart break; case 'layout': - $legendLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta); + $legendLayout = $this->chartLayoutDetails($chartDetail); break; } } - $legend = new Legend($legendPos, $legendLayout, $legendOverlay); + $legend = new Legend("$legendPos", $legendLayout, (bool) $legendOverlay); break; } } } } - $chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, $dispBlanksAs, $XaxisLabel, $YaxisLabel); + $chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart($chartName, $title, $legend, $plotArea, $plotVisOnly, (string) $dispBlanksAs, $XaxisLabel, $YaxisLabel); if (is_int($rotX)) { $chart->setRotX($rotX); } @@ -244,25 +257,25 @@ class Chart return $chart; } - private static function chartTitle(SimpleXMLElement $titleDetails, array $namespacesChartMeta) + private function chartTitle(SimpleXMLElement $titleDetails): Title { $caption = []; $titleLayout = null; foreach ($titleDetails as $titleDetailKey => $chartDetail) { switch ($titleDetailKey) { case 'tx': - $titleDetails = $chartDetail->rich->children($namespacesChartMeta['a']); + $titleDetails = $chartDetail->rich->children($this->aNamespace); foreach ($titleDetails as $titleKey => $titleDetail) { switch ($titleKey) { case 'p': - $titleDetailPart = $titleDetail->children($namespacesChartMeta['a']); - $caption[] = self::parseRichText($titleDetailPart); + $titleDetailPart = $titleDetail->children($this->aNamespace); + $caption[] = $this->parseRichText($titleDetailPart); } } break; case 'layout': - $titleLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta); + $titleLayout = $this->chartLayoutDetails($chartDetail); break; } @@ -271,12 +284,12 @@ class Chart return new Title($caption, $titleLayout); } - private static function chartLayoutDetails($chartDetail, $namespacesChartMeta) + private function chartLayoutDetails(SimpleXMLElement $chartDetail): ?Layout { if (!isset($chartDetail->manualLayout)) { return null; } - $details = $chartDetail->manualLayout->children($namespacesChartMeta['c']); + $details = $chartDetail->manualLayout->children($this->cNamespace); if ($details === null) { return null; } @@ -288,13 +301,13 @@ class Chart return new Layout($layout); } - private static function chartDataSeries($chartDetail, $namespacesChartMeta, $plotType) + private function chartDataSeries(SimpleXMLElement $chartDetail, string $plotType): DataSeries { $multiSeriesType = null; $smoothLine = false; $seriesLabel = $seriesCategory = $seriesValues = $plotOrder = []; - $seriesDetailSet = $chartDetail->children($namespacesChartMeta['c']); + $seriesDetailSet = $chartDetail->children($this->cNamespace); foreach ($seriesDetailSet as $seriesDetailKey => $seriesDetails) { switch ($seriesDetailKey) { case 'grouping': @@ -322,11 +335,11 @@ class Chart break; case 'tx': - $seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta); + $seriesLabel[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail); break; case 'spPr': - $children = $seriesDetail->children($namespacesChartMeta['a']); + $children = $seriesDetail->children($this->aNamespace); $ln = $children->ln; $lineWidth = self::getAttribute($ln, 'w', 'string'); if (is_countable($ln->noFill) && count($ln->noFill) === 1) { @@ -343,9 +356,9 @@ class Chart $pointSize = self::getAttribute($seriesDetail->size, 'val', 'string'); $pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null; if (count($seriesDetail->spPr) === 1) { - $ln = $seriesDetail->spPr->children($namespacesChartMeta['a']); + $ln = $seriesDetail->spPr->children($this->aNamespace); if (count($ln->solidFill) === 1) { - $srgbClr = self::getattribute($ln->solidFill->srgbClr, 'val', 'string'); + $srgbClr = self::getAttribute($ln->solidFill->srgbClr, 'val', 'string'); } } @@ -355,19 +368,19 @@ class Chart break; case 'cat': - $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta); + $seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail); break; case 'val': - $seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize"); + $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize"); break; case 'xVal': - $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize"); + $seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize"); break; case 'yVal': - $seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, "$marker", "$srgbClr", "$pointSize"); + $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", "$srgbClr", "$pointSize"); break; case 'bubble3D': @@ -423,17 +436,21 @@ class Chart } } + /** @phpstan-ignore-next-line */ return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine); } - private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, ?string $marker = null, ?string $srgbClr = null, ?string $pointSize = null) + /** + * @return mixed + */ + private function chartDataSeriesValueSet(SimpleXMLElement $seriesDetail, ?string $marker = null, ?string $srgbClr = null, ?string $pointSize = null) { if (isset($seriesDetail->strRef)) { $seriesSource = (string) $seriesDetail->strRef->f; - $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize"); + $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize"); if (isset($seriesDetail->strRef->strCache)) { - $seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's'); + $seriesData = $this->chartDataSeriesValues($seriesDetail->strRef->strCache->children($this->cNamespace), 's'); $seriesValues ->setFormatCode($seriesData['formatCode']) ->setDataValues($seriesData['dataValues']); @@ -442,9 +459,9 @@ class Chart return $seriesValues; } elseif (isset($seriesDetail->numRef)) { $seriesSource = (string) $seriesDetail->numRef->f; - $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize"); + $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize"); if (isset($seriesDetail->numRef->numCache)) { - $seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c'])); + $seriesData = $this->chartDataSeriesValues($seriesDetail->numRef->numCache->children($this->cNamespace)); $seriesValues ->setFormatCode($seriesData['formatCode']) ->setDataValues($seriesData['dataValues']); @@ -453,10 +470,10 @@ class Chart return $seriesValues; } elseif (isset($seriesDetail->multiLvlStrRef)) { $seriesSource = (string) $seriesDetail->multiLvlStrRef->f; - $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize"); + $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize"); if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) { - $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's'); + $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($this->cNamespace), 's'); $seriesValues ->setFormatCode($seriesData['formatCode']) ->setDataValues($seriesData['dataValues']); @@ -465,10 +482,10 @@ class Chart return $seriesValues; } elseif (isset($seriesDetail->multiLvlNumRef)) { $seriesSource = (string) $seriesDetail->multiLvlNumRef->f; - $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, null, null, $marker, $srgbClr, "$pointSize"); + $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $srgbClr, "$pointSize"); if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) { - $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's'); + $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($this->cNamespace), 's'); $seriesValues ->setFormatCode($seriesData['formatCode']) ->setDataValues($seriesData['dataValues']); @@ -480,7 +497,7 @@ class Chart return null; } - private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n') + private function chartDataSeriesValues(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array { $seriesVal = []; $formatCode = ''; @@ -500,7 +517,7 @@ class Chart $pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); if ($dataType == 's') { $seriesVal[$pointVal] = (string) $seriesValue->v; - } elseif ($seriesValue->v === ExcelError::NA()) { + } elseif ((string) $seriesValue->v === ExcelError::NA()) { $seriesVal[$pointVal] = null; } else { $seriesVal[$pointVal] = (float) $seriesValue->v; @@ -517,7 +534,7 @@ class Chart ]; } - private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n') + private function chartDataSeriesValuesMultiLevel(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array { $seriesVal = []; $formatCode = ''; @@ -538,7 +555,7 @@ class Chart $pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); if ($dataType == 's') { $seriesVal[$pointVal][] = (string) $seriesValue->v; - } elseif ($seriesValue->v === ExcelError::NA()) { + } elseif ((string) $seriesValue->v === ExcelError::NA()) { $seriesVal[$pointVal] = null; } else { $seriesVal[$pointVal][] = (float) $seriesValue->v; @@ -556,7 +573,7 @@ class Chart ]; } - private static function parseRichText(SimpleXMLElement $titleDetailPart) + private function parseRichText(SimpleXMLElement $titleDetailPart): RichText { $value = new RichText(); $objText = null; @@ -773,7 +790,10 @@ class Chart return $value; } - private static function readChartAttributes($chartDetail) + /** + * @param null|Layout|SimpleXMLElement $chartDetail + */ + private function readChartAttributes($chartDetail): array { $plotAttributes = []; if (isset($chartDetail->dLbls)) { @@ -806,7 +826,7 @@ class Chart /** * @param mixed $plotAttributes */ - private static function setChartAttributes(Layout $plotArea, $plotAttributes): void + private function setChartAttributes(Layout $plotArea, $plotAttributes): void { foreach ($plotAttributes as $plotAttributeKey => $plotAttributeValue) { switch ($plotAttributeKey) { diff --git a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index 77cbb872..4ea26438 100644 --- a/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -963,7 +963,7 @@ class Chart extends WriterPart if ($id1 !== '0') { $objWriter->startElement('c:crossAx'); - $objWriter->writeAttribute('val', $id2); + $objWriter->writeAttribute('val', $id1); $objWriter->endElement(); if ($xAxis->getAxisOptionsProperty('horizontal_crosses_value') !== null) {