Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
<?php

namespace PhpOffice\PhpSpreadsheet\Reader\Xlsx;

< use PhpOffice\PhpSpreadsheet\Calculation\Functions;
> use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError; > use PhpOffice\PhpSpreadsheet\Chart\Axis; > use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;
> use PhpOffice\PhpSpreadsheet\Chart\GridLines;
use PhpOffice\PhpSpreadsheet\Chart\Layout; use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
> use PhpOffice\PhpSpreadsheet\Chart\Properties as ChartProperties;
use PhpOffice\PhpSpreadsheet\Chart\Title;
> use PhpOffice\PhpSpreadsheet\Chart\TrendLine; use PhpOffice\PhpSpreadsheet\RichText\RichText; > use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
< use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Font; use SimpleXMLElement; class Chart {
> /** @var string */ /** > private $cNamespace; * @param string $name > * @param string $format > /** @var string */ * > private $aNamespace; * @return null|bool|float|int|string > */ > public function __construct(string $cNamespace = Namespaces::CHART, string $aNamespace = Namespaces::DRAWINGML) private static function getAttribute(SimpleXMLElement $component, $name, $format) > { { > $this->cNamespace = $cNamespace; $attributes = $component->attributes(); > $this->aNamespace = $aNamespace; if (isset($attributes[$name])) { > } if ($format == 'string') { >
< if (isset($attributes[$name])) {
> if (@isset($attributes[$name])) {
} elseif ($format == 'integer') { return (int) $attributes[$name]; } elseif ($format == 'boolean') {
< return (bool) ($attributes[$name] === '0' || $attributes[$name] !== 'true') ? false : true;
> $value = (string) $attributes[$name]; > > return $value === 'true' || $value === '1';
} return (float) $attributes[$name]; } return null; }
< private static function readColor($color, $background = false) < { < if (isset($color['rgb'])) { < return (string) $color['rgb']; < } elseif (isset($color['indexed'])) { < return Color::indexedColor($color['indexed'] - 7, $background)->getARGB(); < } < } <
/** * @param string $chartName * * @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;
<
> $plotArea = null; > $rotX = $rotY = $rAngAx = $perspective = null; > $xAxis = new Axis(); > $yAxis = new Axis(); > $autoTitleDeleted = null; > $chartNoFill = false; > $gradientArray = []; > $gradientLin = null; > $roundedCorners = false;
foreach ($chartElementsC as $chartElementKey => $chartElement) { switch ($chartElementKey) {
> case 'spPr': case 'chart': > $possibleNoFill = $chartElementsC->spPr->children($this->aNamespace); foreach ($chartElement as $chartDetailsKey => $chartDetails) { > if (isset($possibleNoFill->noFill)) { $chartDetailsC = $chartDetails->children($namespacesChartMeta['c']); > $chartNoFill = true; switch ($chartDetailsKey) { > } case 'plotArea': > $plotAreaLayout = $XaxisLable = $YaxisLable = null; > break; $plotSeries = $plotAttributes = []; > case 'roundedCorners': foreach ($chartDetails as $chartDetailKey => $chartDetail) { > /** @var bool */ switch ($chartDetailKey) { > $roundedCorners = self::getAttribute($chartElementsC->roundedCorners, 'val', 'boolean'); case 'layout': > $plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta); > break;
< $chartDetailsC = $chartDetails->children($namespacesChartMeta['c']);
> $chartDetails = Xlsx::testSimpleXml($chartDetails);
break;
> case 'autoTitleDeleted': case 'catAx': > /** @var bool */ if (isset($chartDetail->title)) { > $autoTitleDeleted = self::getAttribute($chartElementsC->chart->autoTitleDeleted, 'val', 'boolean'); $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta); > } > break; > case 'view3D': break; > $rotX = self::getAttribute($chartDetails->rotX, 'val', 'integer'); case 'dateAx': > $rotY = self::getAttribute($chartDetails->rotY, 'val', 'integer'); if (isset($chartDetail->title)) { > $rAngAx = self::getAttribute($chartDetails->rAngAx, 'val', 'integer'); $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta); > $perspective = self::getAttribute($chartDetails->perspective, 'val', 'integer'); } > > break;
< $plotAreaLayout = $XaxisLable = $YaxisLable = null;
> $plotAreaLayout = $XaxisLabel = $YaxisLabel = null;
case 'valAx':
> $catAxRead = false; if (isset($chartDetail->title)) { > $plotNoFill = false;
$YaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
> $chartDetail = Xlsx::testSimpleXml($chartDetail);
}
> case 'spPr': > $possibleNoFill = $chartDetails->spPr->children($this->aNamespace); break; > if (isset($possibleNoFill->noFill)) { case 'barChart': > $plotNoFill = true; case 'bar3DChart': > } $barDirection = self::getAttribute($chartDetail->barDir, 'val', 'string'); > if (isset($possibleNoFill->gradFill->gsLst)) { $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > foreach ($possibleNoFill->gradFill->gsLst->gs as $gradient) { $plotSer->setPlotDirection($barDirection); > $gradient = Xlsx::testSimpleXml($gradient); $plotSeries[] = $plotSer; > /** @var float */ $plotAttributes = self::readChartAttributes($chartDetail); > $pos = self::getAttribute($gradient, 'pos', 'float'); > $gradientArray[] = [ break; > $pos / ChartProperties::PERCENTAGE_MULTIPLIER, case 'lineChart': > new ChartColor($this->readColor($gradient)), case 'line3DChart': > ]; $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > } $plotAttributes = self::readChartAttributes($chartDetail); > } > if (isset($possibleNoFill->gradFill->lin)) { break; > $gradientLin = ChartProperties::XmlToAngle((string) self::getAttribute($possibleNoFill->gradFill->lin, 'ang', 'string')); case 'areaChart': > } case 'area3DChart': > $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > break;
< $plotAreaLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);
> $plotAreaLayout = $this->chartLayoutDetails($chartDetail);
< case 'catAx':
> case Axis::AXIS_TYPE_CATEGORY: > case Axis::AXIS_TYPE_DATE: > $catAxRead = true;
< $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
> $XaxisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace));
case 'doughnutChart':
> $xAxis->setAxisType($chartDetailKey); case 'pieChart': > $this->readEffects($chartDetail, $xAxis); case 'pie3DChart': > $this->readLineStyle($chartDetail, $xAxis); $explosion = isset($chartDetail->ser->explosion); > if (isset($chartDetail->spPr)) { $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $sppr = $chartDetail->spPr->children($this->aNamespace); $plotSer->setPlotStyle($explosion); > if (isset($sppr->solidFill)) { $plotSeries[] = $plotSer; > $axisColorArray = $this->readColor($sppr->solidFill); $plotAttributes = self::readChartAttributes($chartDetail); > $xAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); > } break; > } case 'scatterChart': > if (isset($chartDetail->majorGridlines)) { $scatterStyle = self::getAttribute($chartDetail->scatterStyle, 'val', 'string'); > $majorGridlines = new GridLines(); $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > if (isset($chartDetail->majorGridlines->spPr)) { $plotSer->setPlotStyle($scatterStyle); > $this->readEffects($chartDetail->majorGridlines, $majorGridlines); $plotSeries[] = $plotSer; > $this->readLineStyle($chartDetail->majorGridlines, $majorGridlines); $plotAttributes = self::readChartAttributes($chartDetail); > } > $xAxis->setMajorGridlines($majorGridlines); break; > } case 'bubbleChart': > if (isset($chartDetail->minorGridlines)) { $bubbleScale = self::getAttribute($chartDetail->bubbleScale, 'val', 'integer'); > $minorGridlines = new GridLines(); $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $minorGridlines->activateObject(); $plotSer->setPlotStyle($bubbleScale); > if (isset($chartDetail->minorGridlines->spPr)) { $plotSeries[] = $plotSer; > $this->readEffects($chartDetail->minorGridlines, $minorGridlines); $plotAttributes = self::readChartAttributes($chartDetail); > $this->readLineStyle($chartDetail->minorGridlines, $minorGridlines); > } break; > $xAxis->setMinorGridlines($minorGridlines); case 'radarChart': > } $radarStyle = self::getAttribute($chartDetail->radarStyle, 'val', 'string'); > $this->setAxisProperties($chartDetail, $xAxis); $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $plotSer->setPlotStyle($radarStyle); > break; $plotSeries[] = $plotSer; > case Axis::AXIS_TYPE_VALUE: $plotAttributes = self::readChartAttributes($chartDetail); > $whichAxis = null; > $axPos = null; break; > if (isset($chartDetail->axPos)) { case 'surfaceChart': > $axPos = self::getAttribute($chartDetail->axPos, 'val', 'string'); case 'surface3DChart': > } $wireFrame = self::getAttribute($chartDetail->wireframe, 'val', 'boolean'); > if ($catAxRead) { $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $whichAxis = $yAxis; $plotSer->setPlotStyle($wireFrame); > $yAxis->setAxisType($chartDetailKey); $plotSeries[] = $plotSer; > } elseif (!empty($axPos)) { $plotAttributes = self::readChartAttributes($chartDetail); > switch ($axPos) { > case 't': break; > case 'b': case 'stockChart': > $whichAxis = $xAxis; $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); > $xAxis->setAxisType($chartDetailKey); $plotAttributes = self::readChartAttributes($plotAreaLayout); > > break; break; > case 'r': } > case 'l': } > $whichAxis = $yAxis; if ($plotAreaLayout == null) { > $yAxis->setAxisType($chartDetailKey);
< case 'dateAx': < if (isset($chartDetail->title)) { < $XaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
self::setChartAttributes($plotAreaLayout, $plotAttributes);
> } > if (isset($chartDetail->title)) { break; > $axisLabel = $this->chartTitle($chartDetail->title->children($this->cNamespace)); case 'plotVisOnly': > $plotVisOnly = self::getAttribute($chartDetails, 'val', 'string'); > switch ($axPos) { > case 't': break; > case 'b': case 'dispBlanksAs': > $XaxisLabel = $axisLabel;
< case 'valAx': < if (isset($chartDetail->title)) { < $YaxisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
> case 'r': > case 'l': > $YaxisLabel = $axisLabel; > > break; > } > } > $this->readEffects($chartDetail, $whichAxis); > $this->readLineStyle($chartDetail, $whichAxis); > if ($whichAxis !== null && isset($chartDetail->spPr)) { > $sppr = $chartDetail->spPr->children($this->aNamespace); > if (isset($sppr->solidFill)) { > $axisColorArray = $this->readColor($sppr->solidFill); > $whichAxis->setFillParameters($axisColorArray['value'], $axisColorArray['alpha'], $axisColorArray['type']); > } > } > if ($whichAxis !== null && isset($chartDetail->majorGridlines)) { > $majorGridlines = new GridLines(); > if (isset($chartDetail->majorGridlines->spPr)) { > $this->readEffects($chartDetail->majorGridlines, $majorGridlines); > $this->readLineStyle($chartDetail->majorGridlines, $majorGridlines); > } > $whichAxis->setMajorGridlines($majorGridlines); > } > if ($whichAxis !== null && isset($chartDetail->minorGridlines)) { > $minorGridlines = new GridLines(); > $minorGridlines->activateObject(); > if (isset($chartDetail->minorGridlines->spPr)) { > $this->readEffects($chartDetail->minorGridlines, $minorGridlines); > $this->readLineStyle($chartDetail->minorGridlines, $minorGridlines);
case 'title':
> $whichAxis->setMinorGridlines($minorGridlines); $title = self::chartTitle($chartDetails, $namespacesChartMeta); > } > $this->setAxisProperties($chartDetail, $whichAxis);
< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotDirection($barDirection);
> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotDirection("$barDirection");
< $plotAttributes = self::readChartAttributes($chartDetail);
> $plotAttributes = $this->readChartAttributes($chartDetail);
< $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotAttributes = self::readChartAttributes($chartDetail);
> $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotAttributes = $this->readChartAttributes($chartDetail);
< $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotAttributes = self::readChartAttributes($chartDetail);
> $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotAttributes = $this->readChartAttributes($chartDetail);
< $explosion = isset($chartDetail->ser->explosion); < $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotStyle($explosion);
> $explosion = self::getAttribute($chartDetail->ser->explosion, 'val', 'string'); > $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotStyle("$explosion");
< $plotAttributes = self::readChartAttributes($chartDetail);
> $plotAttributes = $this->readChartAttributes($chartDetail);
case 'overlay':
> /** @var string */
< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
< $plotAttributes = self::readChartAttributes($chartDetail);
> $plotAttributes = $this->readChartAttributes($chartDetail);
< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotStyle($bubbleScale);
> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotStyle("$bubbleScale");
< $plotAttributes = self::readChartAttributes($chartDetail);
> $plotAttributes = $this->readChartAttributes($chartDetail);
> /** @var string */
< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey);
> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey);
< $plotAttributes = self::readChartAttributes($chartDetail);
> $plotAttributes = $this->readChartAttributes($chartDetail);
< $plotSer = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotSer->setPlotStyle($wireFrame);
> $plotSer = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotSer->setPlotStyle("$wireFrame");
< $plotAttributes = self::readChartAttributes($chartDetail);
> $plotAttributes = $this->readChartAttributes($chartDetail);
< $plotSeries[] = self::chartDataSeries($chartDetail, $namespacesChartMeta, $chartDetailKey); < $plotAttributes = self::readChartAttributes($plotAreaLayout);
> $plotSeries[] = $this->chartDataSeries($chartDetail, $chartDetailKey); > $plotAttributes = $this->readChartAttributes($chartDetail);
< self::setChartAttributes($plotAreaLayout, $plotAttributes);
> $this->setChartAttributes($plotAreaLayout, $plotAttributes); > if ($plotNoFill) { > $plotArea->setNoFill(true); > } > if (!empty($gradientArray)) { > $plotArea->setGradientFillProperties($gradientArray, $gradientLin); > }
< $title = self::chartTitle($chartDetails, $namespacesChartMeta);
> $title = $this->chartTitle($chartDetails);
}
> $chartDetail = Xlsx::testSimpleXml($chartDetail);
< $legendLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);
> $legendLayout = $this->chartLayoutDetails($chartDetail);
< $legend = new Legend($legendPos, $legendLayout, $legendOverlay);
> $legend = new Legend("$legendPos", $legendLayout, (bool) $legendOverlay);
< $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, $xAxis, $yAxis); > if ($chartNoFill) { > $chart->setNoFill(true); > } > $chart->setRoundedCorners($roundedCorners); > if (is_bool($autoTitleDeleted)) { > $chart->setAutoTitleDeleted($autoTitleDeleted); > } > if (is_int($rotX)) { > $chart->setRotX($rotX); > } > if (is_int($rotY)) { > $chart->setRotY($rotY); > } > if (is_int($rAngAx)) { > $chart->setRAngAx($rAngAx); > } > if (is_int($perspective)) { > $chart->setPerspective($perspective); > }
}
< private static function chartTitle(SimpleXMLElement $titleDetails, array $namespacesChartMeta)
> private function chartTitle(SimpleXMLElement $titleDetails): Title
{ $caption = []; $titleLayout = null;
> $titleOverlay = false;
foreach ($titleDetails as $titleDetailKey => $chartDetail) {
> $chartDetail = Xlsx::testSimpleXml($chartDetail);
switch ($titleDetailKey) { case 'tx':
< $titleDetails = $chartDetail->rich->children($namespacesChartMeta['a']);
> if (isset($chartDetail->rich)) { > $titleDetails = $chartDetail->rich->children($this->aNamespace);
foreach ($titleDetails as $titleKey => $titleDetail) {
> $titleDetail = Xlsx::testSimpleXml($titleDetail);
switch ($titleKey) { case 'p':
< $titleDetailPart = $titleDetail->children($namespacesChartMeta['a']); < $caption[] = self::parseRichText($titleDetailPart);
> $titleDetailPart = $titleDetail->children($this->aNamespace); > $caption[] = $this->parseRichText($titleDetailPart); > }
}
> } elseif (isset($chartDetail->strRef->strCache)) { } > foreach ($chartDetail->strRef->strCache->pt as $pt) { > if (isset($pt->v)) { break; > $caption[] = (string) $pt->v;
case 'layout':
> } $titleLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta); > } > break; > break; } > case 'overlay': } > $titleOverlay = self::getAttribute($chartDetail, 'val', 'boolean');
< $titleLayout = self::chartLayoutDetails($chartDetail, $namespacesChartMeta);
> $titleLayout = $this->chartLayoutDetails($chartDetail);
< return new Title($caption, $titleLayout);
> return new Title($caption, $titleLayout, (bool) $titleOverlay);
}
< 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; } $layout = []; foreach ($details as $detailKey => $detail) {
> $detail = Xlsx::testSimpleXml($detail);
$layout[$detailKey] = self::getAttribute($detail, 'val', 'string'); } 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 = [];
> $seriesLabel = $seriesCategory = $seriesValues = $plotOrder = $seriesBubbles = [];
< $seriesDetailSet = $chartDetail->children($namespacesChartMeta['c']);
> $seriesDetailSet = $chartDetail->children($this->cNamespace);
foreach ($seriesDetailSet as $seriesDetailKey => $seriesDetails) { switch ($seriesDetailKey) { case 'grouping': $multiSeriesType = self::getAttribute($chartDetail->grouping, 'val', 'string'); break; case 'ser': $marker = null; $seriesIndex = '';
> $fillColor = null; foreach ($seriesDetails as $seriesKey => $seriesDetail) { > $pointSize = null; switch ($seriesKey) { > $noFill = false; case 'idx': > $bubble3D = false; $seriesIndex = self::getAttribute($seriesDetail, 'val', 'integer'); > $dptColors = []; > $markerFillColor = null; break; > $markerBorderColor = null; case 'order': > $lineStyle = null; $seriesOrder = self::getAttribute($seriesDetail, 'val', 'integer'); > $labelLayout = null; $plotOrder[$seriesIndex] = $seriesOrder; > $trendLines = [];
> $seriesDetail = Xlsx::testSimpleXml($seriesDetail);
break; case 'tx':
< $seriesLabel[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
> $seriesLabel[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail); > > break; > case 'spPr': > $children = $seriesDetail->children($this->aNamespace); > if (isset($children->ln)) { > $ln = $children->ln; > if (is_countable($ln->noFill) && count($ln->noFill) === 1) { > $noFill = true; > } > $lineStyle = new GridLines(); > $this->readLineStyle($seriesDetails, $lineStyle); > } > if (isset($children->effectLst)) { > if ($lineStyle === null) { > $lineStyle = new GridLines(); > } > $this->readEffects($seriesDetails, $lineStyle); > } > if (isset($children->solidFill)) { > $fillColor = new ChartColor($this->readColor($children->solidFill)); > } > > break; > case 'dPt': > $dptIdx = (int) self::getAttribute($seriesDetail->idx, 'val', 'string'); > if (isset($seriesDetail->spPr)) { > $children = $seriesDetail->spPr->children($this->aNamespace); > if (isset($children->solidFill)) { > $arrayColors = $this->readColor($children->solidFill); > $dptColors[$dptIdx] = new ChartColor($arrayColors); > } > } > > break; > case 'trendline': > $trendLine = new TrendLine(); > $this->readLineStyle($seriesDetail, $trendLine); > /** @var ?string */ > $trendLineType = self::getAttribute($seriesDetail->trendlineType, 'val', 'string'); > /** @var ?bool */ > $dispRSqr = self::getAttribute($seriesDetail->dispRSqr, 'val', 'boolean'); > /** @var ?bool */ > $dispEq = self::getAttribute($seriesDetail->dispEq, 'val', 'boolean'); > /** @var ?int */ > $order = self::getAttribute($seriesDetail->order, 'val', 'integer'); > /** @var ?int */ > $period = self::getAttribute($seriesDetail->period, 'val', 'integer'); > /** @var ?float */ > $forward = self::getAttribute($seriesDetail->forward, 'val', 'float'); > /** @var ?float */ > $backward = self::getAttribute($seriesDetail->backward, 'val', 'float'); > /** @var ?float */ > $intercept = self::getAttribute($seriesDetail->intercept, 'val', 'float'); > /** @var ?string */ > $name = (string) $seriesDetail->name; > $trendLine->setTrendLineProperties( > $trendLineType, > $order, > $period, > $dispRSqr, > $dispEq, > $backward, > $forward, > $intercept, > $name > ); > $trendLines[] = $trendLine;
break; case 'marker': $marker = self::getAttribute($seriesDetail->symbol, 'val', 'string');
> $pointSize = self::getAttribute($seriesDetail->size, 'val', 'string'); > $pointSize = is_numeric($pointSize) ? ((int) $pointSize) : null; break; > if (isset($seriesDetail->spPr)) { case 'smooth': > $children = $seriesDetail->spPr->children($this->aNamespace); $smoothLine = self::getAttribute($seriesDetail, 'val', 'boolean'); > if (isset($children->solidFill)) { > $markerFillColor = $this->readColor($children->solidFill); break; > } case 'cat': > if (isset($children->ln->solidFill)) { $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta); > $markerBorderColor = $this->readColor($children->ln->solidFill); > } break; > }
< $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta);
> $seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail);
< $seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
> $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
break; case 'xVal':
< $seriesCategory[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
> $seriesCategory[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize");
break; case 'yVal':
< $seriesValues[$seriesIndex] = self::chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker);
> $seriesValues[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize"); > > break; > case 'bubbleSize': > $seriesBubbles[$seriesIndex] = $this->chartDataSeriesValueSet($seriesDetail, "$marker", $fillColor, "$pointSize"); > > break; > case 'bubble3D': > $bubble3D = self::getAttribute($seriesDetail, 'val', 'boolean'); > > break; > case 'dLbls': > $labelLayout = new Layout($this->readChartAttributes($seriesDetails));
break; } }
> if ($labelLayout) { } > if (isset($seriesLabel[$seriesIndex])) { } > $seriesLabel[$seriesIndex]->setLabelLayout($labelLayout); > } return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine); > if (isset($seriesCategory[$seriesIndex])) { } > $seriesCategory[$seriesIndex]->setLabelLayout($labelLayout); > } private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null) > if (isset($seriesValues[$seriesIndex])) { { > $seriesValues[$seriesIndex]->setLabelLayout($labelLayout); if (isset($seriesDetail->strRef)) { > } $seriesSource = (string) $seriesDetail->strRef->f; > } $seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's'); > if ($noFill) { > if (isset($seriesLabel[$seriesIndex])) { return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > $seriesLabel[$seriesIndex]->setScatterLines(false); } elseif (isset($seriesDetail->numRef)) { > } $seriesSource = (string) $seriesDetail->numRef->f; > if (isset($seriesCategory[$seriesIndex])) { $seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c'])); > $seriesCategory[$seriesIndex]->setScatterLines(false); > } return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > if (isset($seriesValues[$seriesIndex])) { } elseif (isset($seriesDetail->multiLvlStrRef)) { > $seriesValues[$seriesIndex]->setScatterLines(false); $seriesSource = (string) $seriesDetail->multiLvlStrRef->f; > } $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's'); > } $seriesData['pointCount'] = count($seriesData['dataValues']); > if ($lineStyle !== null) { > if (isset($seriesLabel[$seriesIndex])) { return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > $seriesLabel[$seriesIndex]->copyLineStyles($lineStyle); } elseif (isset($seriesDetail->multiLvlNumRef)) { > } $seriesSource = (string) $seriesDetail->multiLvlNumRef->f; > if (isset($seriesCategory[$seriesIndex])) { $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's'); > $seriesCategory[$seriesIndex]->copyLineStyles($lineStyle); $seriesData['pointCount'] = count($seriesData['dataValues']); > } > if (isset($seriesValues[$seriesIndex])) { return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker); > $seriesValues[$seriesIndex]->copyLineStyles($lineStyle); } > } > } return null; > if ($bubble3D) { } > if (isset($seriesLabel[$seriesIndex])) { > $seriesLabel[$seriesIndex]->setBubble3D($bubble3D); private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n') > } { > if (isset($seriesCategory[$seriesIndex])) { $seriesVal = []; > $seriesCategory[$seriesIndex]->setBubble3D($bubble3D);
$formatCode = '';
> if (isset($seriesValues[$seriesIndex])) { $pointCount = 0; > $seriesValues[$seriesIndex]->setBubble3D($bubble3D);
> } foreach ($seriesValueSet as $seriesValueIdx => $seriesValue) { > if (!empty($dptColors)) { switch ($seriesValueIdx) { > if (isset($seriesLabel[$seriesIndex])) { case 'ptCount': > $seriesLabel[$seriesIndex]->setFillColor($dptColors); $pointCount = self::getAttribute($seriesValue, 'val', 'integer'); > } > if (isset($seriesCategory[$seriesIndex])) { break; > $seriesCategory[$seriesIndex]->setFillColor($dptColors); case 'formatCode': > } $formatCode = (string) $seriesValue; > if (isset($seriesValues[$seriesIndex])) { > $seriesValues[$seriesIndex]->setFillColor($dptColors); break; > } case 'pt': > } $pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); > if ($markerFillColor !== null) { if ($dataType == 's') { > if (isset($seriesLabel[$seriesIndex])) { $seriesVal[$pointVal] = (string) $seriesValue->v; > $seriesLabel[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor); } elseif ($seriesValue->v === Functions::NA()) { > } $seriesVal[$pointVal] = null; > if (isset($seriesCategory[$seriesIndex])) { } else { > $seriesCategory[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor); $seriesVal[$pointVal] = (float) $seriesValue->v; > } } > if (isset($seriesValues[$seriesIndex])) { > $seriesValues[$seriesIndex]->getMarkerFillColor()->setColorPropertiesArray($markerFillColor); break; > } } > } } > if ($markerBorderColor !== null) { > if (isset($seriesLabel[$seriesIndex])) { return [ > $seriesLabel[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor); 'formatCode' => $formatCode, > } 'pointCount' => $pointCount, > if (isset($seriesCategory[$seriesIndex])) { 'dataValues' => $seriesVal, > $seriesCategory[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor); ]; > } } > if (isset($seriesValues[$seriesIndex])) { > $seriesValues[$seriesIndex]->getMarkerBorderColor()->setColorPropertiesArray($markerBorderColor); private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n') > } { > } $seriesVal = []; > if ($smoothLine) { $formatCode = ''; > if (isset($seriesLabel[$seriesIndex])) { $pointCount = 0; > $seriesLabel[$seriesIndex]->setSmoothLine(true); > } foreach ($seriesValueSet->lvl as $seriesLevelIdx => $seriesLevel) { > if (isset($seriesCategory[$seriesIndex])) { foreach ($seriesLevel as $seriesValueIdx => $seriesValue) { > $seriesCategory[$seriesIndex]->setSmoothLine(true); switch ($seriesValueIdx) { > } case 'ptCount': > if (isset($seriesValues[$seriesIndex])) { $pointCount = self::getAttribute($seriesValue, 'val', 'integer'); > $seriesValues[$seriesIndex]->setSmoothLine(true); > } break; > } case 'formatCode': > if (!empty($trendLines)) { $formatCode = (string) $seriesValue; > if (isset($seriesLabel[$seriesIndex])) { > $seriesLabel[$seriesIndex]->setTrendLines($trendLines); break; > } case 'pt': > if (isset($seriesCategory[$seriesIndex])) { $pointVal = self::getAttribute($seriesValue, 'idx', 'integer'); > $seriesCategory[$seriesIndex]->setTrendLines($trendLines); if ($dataType == 's') { > } $seriesVal[$pointVal][] = (string) $seriesValue->v; > if (isset($seriesValues[$seriesIndex])) { } elseif ($seriesValue->v === Functions::NA()) { > $seriesValues[$seriesIndex]->setTrendLines($trendLines); $seriesVal[$pointVal] = null; > } } else { > } $seriesVal[$pointVal][] = (float) $seriesValue->v; > } } > } > /** @phpstan-ignore-next-line */ break; > $series = new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine); } > $series->setPlotBubbleSizes($seriesBubbles);
< return new DataSeries($plotType, $multiSeriesType, $plotOrder, $seriesLabel, $seriesCategory, $seriesValues, $smoothLine);
> return $series;
< private static function chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null)
> /** > * @return mixed > */ > private function chartDataSeriesValueSet(SimpleXMLElement $seriesDetail, ?string $marker = null, ?ChartColor $fillColor = null, ?string $pointSize = null)
< $seriesData = self::chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']), 's');
> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize"); > > if (isset($seriesDetail->strRef->strCache)) { > $seriesData = $this->chartDataSeriesValues($seriesDetail->strRef->strCache->children($this->cNamespace), 's'); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > }
< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);
> return $seriesValues;
< $seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c']));
> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize"); > if (isset($seriesDetail->numRef->numCache)) { > $seriesData = $this->chartDataSeriesValues($seriesDetail->numRef->numCache->children($this->cNamespace)); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > }
< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);
> return $seriesValues;
< $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']), 's'); < $seriesData['pointCount'] = count($seriesData['dataValues']);
> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize"); > > if (isset($seriesDetail->multiLvlStrRef->multiLvlStrCache)) { > $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($this->cNamespace), 's'); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > }
< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);
> return $seriesValues;
< $seriesData = self::chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']), 's'); < $seriesData['pointCount'] = count($seriesData['dataValues']);
> $seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, null, 0, null, $marker, $fillColor, "$pointSize");
< return new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, $seriesSource, $seriesData['formatCode'], $seriesData['pointCount'], $seriesData['dataValues'], $marker);
> if (isset($seriesDetail->multiLvlNumRef->multiLvlNumCache)) { > $seriesData = $this->chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($this->cNamespace), 's'); > $seriesValues > ->setFormatCode($seriesData['formatCode']) > ->setDataValues($seriesData['dataValues']); > } > > return $seriesValues; > } > > if (isset($seriesDetail->v)) { > return new DataSeriesValues( > DataSeriesValues::DATASERIES_TYPE_STRING, > null, > null, > 1, > [(string) $seriesDetail->v] > );
< private static function chartDataSeriesValues($seriesValueSet, $dataType = 'n')
> private function chartDataSeriesValues(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array
$objText = null;
> $seriesValue = Xlsx::testSimpleXml($seriesValue);
< } elseif ($seriesValue->v === Functions::NA()) {
> } elseif ((string) $seriesValue->v === ExcelError::NA()) {
< private static function chartDataSeriesValuesMultiLevel($seriesValueSet, $dataType = 'n')
> private function chartDataSeriesValuesMultiLevel(SimpleXMLElement $seriesValueSet, string $dataType = 'n'): array
$objText = $value->createTextRun((string) $titleDetailElement->t);
> $seriesValue = Xlsx::testSimpleXml($seriesValue);
< } elseif ($seriesValue->v === Functions::NA()) {
> } elseif ((string) $seriesValue->v === ExcelError::NA()) {
< private static function parseRichText(SimpleXMLElement $titleDetailPart)
> private function parseRichText(SimpleXMLElement $titleDetailPart): RichText
< $objText = null;
> $defaultFontSize = null; > $defaultBold = null; > $defaultItalic = null; > $defaultUnderscore = null; > $defaultStrikethrough = null; > $defaultBaseline = null; > $defaultFontName = null; > $defaultLatin = null; > $defaultEastAsian = null; > $defaultComplexScript = null; > $defaultFontColor = null; > if (isset($titleDetailPart->pPr->defRPr)) { > /** @var ?int */ > $defaultFontSize = self::getAttribute($titleDetailPart->pPr->defRPr, 'sz', 'integer'); > /** @var ?bool */ > $defaultBold = self::getAttribute($titleDetailPart->pPr->defRPr, 'b', 'boolean'); > /** @var ?bool */ > $defaultItalic = self::getAttribute($titleDetailPart->pPr->defRPr, 'i', 'boolean'); > /** @var ?string */ > $defaultUnderscore = self::getAttribute($titleDetailPart->pPr->defRPr, 'u', 'string'); > /** @var ?string */ > $defaultStrikethrough = self::getAttribute($titleDetailPart->pPr->defRPr, 'strike', 'string'); > /** @var ?int */ > $defaultBaseline = self::getAttribute($titleDetailPart->pPr->defRPr, 'baseline', 'integer'); > if (isset($titleDetailPart->defRPr->rFont['val'])) { > $defaultFontName = (string) $titleDetailPart->defRPr->rFont['val']; > } > if (isset($titleDetailPart->pPr->defRPr->latin)) { > /** @var ?string */ > $defaultLatin = self::getAttribute($titleDetailPart->pPr->defRPr->latin, 'typeface', 'string'); > } > if (isset($titleDetailPart->pPr->defRPr->ea)) { > /** @var ?string */ > $defaultEastAsian = self::getAttribute($titleDetailPart->pPr->defRPr->ea, 'typeface', 'string'); > } > if (isset($titleDetailPart->pPr->defRPr->cs)) { > /** @var ?string */ > $defaultComplexScript = self::getAttribute($titleDetailPart->pPr->defRPr->cs, 'typeface', 'string'); > } > if (isset($titleDetailPart->pPr->defRPr->solidFill)) { > $defaultFontColor = $this->readColor($titleDetailPart->pPr->defRPr->solidFill); > } > }
< if (isset($titleDetailElement->t)) { < $objText = $value->createTextRun((string) $titleDetailElement->t);
> if ( > (string) $titleDetailElementKey !== 'r' > || !isset($titleDetailElement->t) > ) { > continue;
> $objText = $value->createTextRun((string) $titleDetailElement->t); $fontSize = (self::getAttribute($titleDetailElement->rPr, 'sz', 'integer')); > if ($objText->getFont() === null) { if ($fontSize !== null) { > // @codeCoverageIgnoreStart $objText->getFont()->setSize(floor($fontSize / 100)); > continue; } > // @codeCoverageIgnoreEnd > } $fontColor = (self::getAttribute($titleDetailElement->rPr, 'color', 'string')); > $fontSize = null; if ($fontColor !== null) { > $bold = null; $objText->getFont()->setColor(new Color(self::readColor($fontColor))); > $italic = null; } > $underscore = null; > $strikethrough = null; $bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean'); > $baseline = null; if ($bold !== null) { > $fontName = null; $objText->getFont()->setBold($bold); > $latinName = null; } > $eastAsian = null; > $complexScript = null; $italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean'); > $fontColor = null; if ($italic !== null) { > $underlineColor = null;
$objText->getFont()->setItalic($italic);
> // not used now, not sure it ever was, grandfathering
< $objText->getFont()->setName((string) $titleDetailElement->rPr->rFont['val']);
> // @codeCoverageIgnoreStart > $fontName = (string) $titleDetailElement->rPr->rFont['val']; > // @codeCoverageIgnoreEnd > } > if (isset($titleDetailElement->rPr->latin)) { > /** @var ?string */ > $latinName = self::getAttribute($titleDetailElement->rPr->latin, 'typeface', 'string'); > } > if (isset($titleDetailElement->rPr->ea)) { > /** @var ?string */ > $eastAsian = self::getAttribute($titleDetailElement->rPr->ea, 'typeface', 'string'); > } > if (isset($titleDetailElement->rPr->cs)) { > /** @var ?string */ > $complexScript = self::getAttribute($titleDetailElement->rPr->cs, 'typeface', 'string'); > } > /** @var ?int */ > $fontSize = self::getAttribute($titleDetailElement->rPr, 'sz', 'integer'); > > // not used now, not sure it ever was, grandfathering > if (isset($titleDetailElement->rPr->solidFill)) { > $fontColor = $this->readColor($titleDetailElement->rPr->solidFill);
< $fontSize = (self::getAttribute($titleDetailElement->rPr, 'sz', 'integer')); < if ($fontSize !== null) {
> /** @var ?bool */ > $bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean'); > > /** @var ?bool */ > $italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean'); > > /** @var ?int */ > $baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer'); > > /** @var ?string */ > $underscore = self::getAttribute($titleDetailElement->rPr, 'u', 'string'); > if (isset($titleDetailElement->rPr->uFill->solidFill)) { > $underlineColor = $this->readColor($titleDetailElement->rPr->uFill->solidFill); > } > > /** @var ?string */ > $strikethrough = self::getAttribute($titleDetailElement->rPr, 'strike', 'string'); > } > > $fontFound = false; > $latinName = $latinName ?? $defaultLatin; > if ($latinName !== null) { > $objText->getFont()->setLatin($latinName); > $fontFound = true; > } > $eastAsian = $eastAsian ?? $defaultEastAsian; > if ($eastAsian !== null) { > $objText->getFont()->setEastAsian($eastAsian); > $fontFound = true; > } > $complexScript = $complexScript ?? $defaultComplexScript; > if ($complexScript !== null) { > $objText->getFont()->setComplexScript($complexScript); > $fontFound = true; > } > $fontName = $fontName ?? $defaultFontName; > if ($fontName !== null) { > // @codeCoverageIgnoreStart > $objText->getFont()->setName($fontName); > $fontFound = true; > // @codeCoverageIgnoreEnd > } > > $fontSize = $fontSize ?? $defaultFontSize; > if (is_int($fontSize)) {
if ($baseline !== null) {
> $fontFound = true; if ($baseline > 0) { > } else { $objText->getFont()->setSuperscript(true); > $objText->getFont()->setSize(null, true);
< $fontColor = (self::getAttribute($titleDetailElement->rPr, 'color', 'string')); < if ($fontColor !== null) { < $objText->getFont()->setColor(new Color(self::readColor($fontColor)));
> $fontColor = $fontColor ?? $defaultFontColor; > if (!empty($fontColor)) { > $objText->getFont()->setChartColor($fontColor); > $fontFound = true;
< $bold = self::getAttribute($titleDetailElement->rPr, 'b', 'boolean');
> $bold = $bold ?? $defaultBold;
> $fontFound = true;
< $italic = self::getAttribute($titleDetailElement->rPr, 'i', 'boolean');
> $italic = $italic ?? $defaultItalic;
if ($underscore !== null) {
> $fontFound = true;
< $baseline = self::getAttribute($titleDetailElement->rPr, 'baseline', 'integer');
> $baseline = $baseline ?? $defaultBaseline;
$objText->getFont()->setUnderline(Font::UNDERLINE_SINGLE);
> $objText->getFont()->setBaseLine($baseline);
} elseif ($underscore == 'dbl') {
> $fontFound = true;
< $underscore = (self::getAttribute($titleDetailElement->rPr, 'u', 'string'));
> $underscore = $underscore ?? $defaultUnderscore;
} else {
> } elseif ($underscore !== '') { $objText->getFont()->setUnderline(Font::UNDERLINE_NONE); > $objText->getFont()->setUnderline($underscore);
}
> $fontFound = true; } > if ($underlineColor) { > $objText->getFont()->setUnderlineColor($underlineColor); $strikethrough = (self::getAttribute($titleDetailElement->rPr, 's', 'string')); > }
< $strikethrough = (self::getAttribute($titleDetailElement->rPr, 's', 'string'));
> $strikethrough = $strikethrough ?? $defaultStrikethrough;
if ($strikethrough == 'noStrike') {
> $objText->getFont()->setStrikeType($strikethrough);
$objText->getFont()->setStrikethrough(false); } else { $objText->getFont()->setStrikethrough(true); }
> $fontFound = true;
}
> if ($fontFound === false) { } > $objText->setFont(null);
} return $value; }
< private static function readChartAttributes($chartDetail)
> /** > * @param ?SimpleXMLElement $chartDetail > */ > private function readChartAttributes($chartDetail): array
{ $plotAttributes = []; if (isset($chartDetail->dLbls)) {
< if (isset($chartDetail->dLbls->howLegendKey)) {
> if (isset($chartDetail->dLbls->dLblPos)) { > $plotAttributes['dLblPos'] = self::getAttribute($chartDetail->dLbls->dLblPos, 'val', 'string'); > } > if (isset($chartDetail->dLbls->numFmt)) { > $plotAttributes['numFmtCode'] = self::getAttribute($chartDetail->dLbls->numFmt, 'formatCode', 'string'); > $plotAttributes['numFmtLinked'] = self::getAttribute($chartDetail->dLbls->numFmt, 'sourceLinked', 'boolean'); > } > if (isset($chartDetail->dLbls->showLegendKey)) {
$plotAttributes['showLegendKey'] = self::getAttribute($chartDetail->dLbls->showLegendKey, 'val', 'string'); } if (isset($chartDetail->dLbls->showVal)) { $plotAttributes['showVal'] = self::getAttribute($chartDetail->dLbls->showVal, 'val', 'string'); } if (isset($chartDetail->dLbls->showCatName)) { $plotAttributes['showCatName'] = self::getAttribute($chartDetail->dLbls->showCatName, 'val', 'string'); } if (isset($chartDetail->dLbls->showSerName)) { $plotAttributes['showSerName'] = self::getAttribute($chartDetail->dLbls->showSerName, 'val', 'string'); } if (isset($chartDetail->dLbls->showPercent)) { $plotAttributes['showPercent'] = self::getAttribute($chartDetail->dLbls->showPercent, 'val', 'string'); } if (isset($chartDetail->dLbls->showBubbleSize)) { $plotAttributes['showBubbleSize'] = self::getAttribute($chartDetail->dLbls->showBubbleSize, 'val', 'string'); } if (isset($chartDetail->dLbls->showLeaderLines)) { $plotAttributes['showLeaderLines'] = self::getAttribute($chartDetail->dLbls->showLeaderLines, 'val', 'string'); }
> if (isset($chartDetail->dLbls->spPr)) { } > $sppr = $chartDetail->dLbls->spPr->children($this->aNamespace); > if (isset($sppr->solidFill)) { return $plotAttributes; > $plotAttributes['labelFillColor'] = new ChartColor($this->readColor($sppr->solidFill)); } > } > if (isset($sppr->ln->solidFill)) { /** > $plotAttributes['labelBorderColor'] = new ChartColor($this->readColor($sppr->ln->solidFill)); * @param mixed $plotAttributes > } */ > } private static function setChartAttributes(Layout $plotArea, $plotAttributes): void > if (isset($chartDetail->dLbls->txPr)) { { > $txpr = $chartDetail->dLbls->txPr->children($this->aNamespace); foreach ($plotAttributes as $plotAttributeKey => $plotAttributeValue) { > if (isset($txpr->p->pPr->defRPr->solidFill)) { switch ($plotAttributeKey) { > $plotAttributes['labelFontColor'] = new ChartColor($this->readColor($txpr->p->pPr->defRPr->solidFill)); case 'showLegendKey': > } $plotArea->setShowLegendKey($plotAttributeValue); > }
< private static function setChartAttributes(Layout $plotArea, $plotAttributes): void
> private function setChartAttributes(Layout $plotArea, $plotAttributes): void
break; case 'showVal': $plotArea->setShowVal($plotAttributeValue); break; case 'showCatName': $plotArea->setShowCatName($plotAttributeValue); break; case 'showSerName': $plotArea->setShowSerName($plotAttributeValue); break; case 'showPercent': $plotArea->setShowPercent($plotAttributeValue); break; case 'showBubbleSize': $plotArea->setShowBubbleSize($plotAttributeValue); break; case 'showLeaderLines': $plotArea->setShowLeaderLines($plotAttributeValue); break;
> } } > } } > } } > } > private function readEffects(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void > { > if (!isset($chartObject, $chartDetail->spPr)) { > return; > } > $sppr = $chartDetail->spPr->children($this->aNamespace); > > if (isset($sppr->effectLst->glow)) { > $axisGlowSize = (float) self::getAttribute($sppr->effectLst->glow, 'rad', 'integer') / ChartProperties::POINTS_WIDTH_MULTIPLIER; > if ($axisGlowSize != 0.0) { > $colorArray = $this->readColor($sppr->effectLst->glow); > $chartObject->setGlowProperties($axisGlowSize, $colorArray['value'], $colorArray['alpha'], $colorArray['type']); > } > } > > if (isset($sppr->effectLst->softEdge)) { > /** @var string */ > $softEdgeSize = self::getAttribute($sppr->effectLst->softEdge, 'rad', 'string'); > if (is_numeric($softEdgeSize)) { > $chartObject->setSoftEdges((float) ChartProperties::xmlToPoints($softEdgeSize)); > } > } > > $type = ''; > foreach (self::SHADOW_TYPES as $shadowType) { > if (isset($sppr->effectLst->$shadowType)) { > $type = $shadowType; > > break; > } > } > if ($type !== '') { > /** @var string */ > $blur = self::getAttribute($sppr->effectLst->$type, 'blurRad', 'string'); > $blur = is_numeric($blur) ? ChartProperties::xmlToPoints($blur) : null; > /** @var string */ > $dist = self::getAttribute($sppr->effectLst->$type, 'dist', 'string'); > $dist = is_numeric($dist) ? ChartProperties::xmlToPoints($dist) : null; > /** @var string */ > $direction = self::getAttribute($sppr->effectLst->$type, 'dir', 'string'); > $direction = is_numeric($direction) ? ChartProperties::xmlToAngle($direction) : null; > $algn = self::getAttribute($sppr->effectLst->$type, 'algn', 'string'); > $rot = self::getAttribute($sppr->effectLst->$type, 'rotWithShape', 'string'); > $size = []; > foreach (['sx', 'sy'] as $sizeType) { > $sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string'); > if (is_numeric($sizeValue)) { > $size[$sizeType] = ChartProperties::xmlToTenthOfPercent((string) $sizeValue); > } else { > $size[$sizeType] = null; > } > } > foreach (['kx', 'ky'] as $sizeType) { > $sizeValue = self::getAttribute($sppr->effectLst->$type, $sizeType, 'string'); > if (is_numeric($sizeValue)) { > $size[$sizeType] = ChartProperties::xmlToAngle((string) $sizeValue); > } else { > $size[$sizeType] = null; > } > } > $colorArray = $this->readColor($sppr->effectLst->$type); > $chartObject > ->setShadowProperty('effect', $type) > ->setShadowProperty('blur', $blur) > ->setShadowProperty('direction', $direction) > ->setShadowProperty('distance', $dist) > ->setShadowProperty('algn', $algn) > ->setShadowProperty('rotWithShape', $rot) > ->setShadowProperty('size', $size) > ->setShadowProperty('color', $colorArray); > } > } > > private const SHADOW_TYPES = [ > 'outerShdw', > 'innerShdw', > ]; > > private function readColor(SimpleXMLElement $colorXml): array > { > $result = [ > 'type' => null, > 'value' => null, > 'alpha' => null, > 'brightness' => null, > ]; > foreach (ChartColor::EXCEL_COLOR_TYPES as $type) { > if (isset($colorXml->$type)) { > $result['type'] = $type; > $result['value'] = self::getAttribute($colorXml->$type, 'val', 'string'); > if (isset($colorXml->$type->alpha)) { > /** @var string */ > $alpha = self::getAttribute($colorXml->$type->alpha, 'val', 'string'); > if (is_numeric($alpha)) { > $result['alpha'] = ChartColor::alphaFromXml($alpha); > } > } > if (isset($colorXml->$type->lumMod)) { > /** @var string */ > $brightness = self::getAttribute($colorXml->$type->lumMod, 'val', 'string'); > if (is_numeric($brightness)) { > $result['brightness'] = ChartColor::alphaFromXml($brightness); > } > } > > break; > } > } > > return $result; > } > > private function readLineStyle(SimpleXMLElement $chartDetail, ?ChartProperties $chartObject): void > { > if (!isset($chartObject, $chartDetail->spPr)) { > return; > } > $sppr = $chartDetail->spPr->children($this->aNamespace); > > if (!isset($sppr->ln)) { > return; > } > $lineWidth = null; > /** @var string */ > $lineWidthTemp = self::getAttribute($sppr->ln, 'w', 'string'); > if (is_numeric($lineWidthTemp)) { > $lineWidth = ChartProperties::xmlToPoints($lineWidthTemp); > } > /** @var string */ > $compoundType = self::getAttribute($sppr->ln, 'cmpd', 'string'); > /** @var string */ > $dashType = self::getAttribute($sppr->ln->prstDash, 'val', 'string'); > /** @var string */ > $capType = self::getAttribute($sppr->ln, 'cap', 'string'); > if (isset($sppr->ln->miter)) { > $joinType = ChartProperties::LINE_STYLE_JOIN_MITER; > } elseif (isset($sppr->ln->bevel)) { > $joinType = ChartProperties::LINE_STYLE_JOIN_BEVEL; > } else { > $joinType = ''; > } > $headArrowSize = ''; > $endArrowSize = ''; > /** @var string */ > $headArrowType = self::getAttribute($sppr->ln->headEnd, 'type', 'string'); > /** @var string */ > $headArrowWidth = self::getAttribute($sppr->ln->headEnd, 'w', 'string'); > /** @var string */ > $headArrowLength = self::getAttribute($sppr->ln->headEnd, 'len', 'string'); > /** @var string */ > $endArrowType = self::getAttribute($sppr->ln->tailEnd, 'type', 'string'); > /** @var string */ > $endArrowWidth = self::getAttribute($sppr->ln->tailEnd, 'w', 'string'); > /** @var string */ > $endArrowLength = self::getAttribute($sppr->ln->tailEnd, 'len', 'string'); > $chartObject->setLineStyleProperties( > $lineWidth, > $compoundType, > $dashType, > $capType, > $joinType, > $headArrowType, > $headArrowSize, > $endArrowType, > $endArrowSize, > $headArrowWidth, > $headArrowLength, > $endArrowWidth, > $endArrowLength > ); > $colorArray = $this->readColor($sppr->ln->solidFill); > $chartObject->getLineColor()->setColorPropertiesArray($colorArray); > } > > private function setAxisProperties(SimpleXMLElement $chartDetail, ?Axis $whichAxis): void > { > if (!isset($whichAxis)) { > return; > } > if (isset($chartDetail->delete)) { > $whichAxis->setAxisOption('hidden', (string) self::getAttribute($chartDetail->delete, 'val', 'string')); > } > if (isset($chartDetail->numFmt)) { > $whichAxis->setAxisNumberProperties( > (string) self::getAttribute($chartDetail->numFmt, 'formatCode', 'string'), > null, > (int) self::getAttribute($chartDetail->numFmt, 'sourceLinked', 'int') > ); > } > if (isset($chartDetail->crossBetween)) { > $whichAxis->setCrossBetween((string) self::getAttribute($chartDetail->crossBetween, 'val', 'string')); > } > if (isset($chartDetail->majorTickMark)) { > $whichAxis->setAxisOption('major_tick_mark', (string) self::getAttribute($chartDetail->majorTickMark, 'val', 'string')); > } > if (isset($chartDetail->minorTickMark)) { > $whichAxis->setAxisOption('minor_tick_mark', (string) self::getAttribute($chartDetail->minorTickMark, 'val', 'string')); > } > if (isset($chartDetail->tickLblPos)) { > $whichAxis->setAxisOption('axis_labels', (string) self::getAttribute($chartDetail->tickLblPos, 'val', 'string')); > } > if (isset($chartDetail->crosses)) { > $whichAxis->setAxisOption('horizontal_crosses', (string) self::getAttribute($chartDetail->crosses, 'val', 'string')); > } > if (isset($chartDetail->crossesAt)) { > $whichAxis->setAxisOption('horizontal_crosses_value', (string) self::getAttribute($chartDetail->crossesAt, 'val', 'string')); > } > if (isset($chartDetail->scaling->orientation)) { > $whichAxis->setAxisOption('orientation', (string) self::getAttribute($chartDetail->scaling->orientation, 'val', 'string')); > } > if (isset($chartDetail->scaling->max)) { > $whichAxis->setAxisOption('maximum', (string) self::getAttribute($chartDetail->scaling->max, 'val', 'string')); > } > if (isset($chartDetail->scaling->min)) { > $whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string')); > } > if (isset($chartDetail->scaling->min)) { > $whichAxis->setAxisOption('minimum', (string) self::getAttribute($chartDetail->scaling->min, 'val', 'string')); > } > if (isset($chartDetail->majorUnit)) { > $whichAxis->setAxisOption('major_unit', (string) self::getAttribute($chartDetail->majorUnit, 'val', 'string')); > } > if (isset($chartDetail->minorUnit)) { > $whichAxis->setAxisOption('minor_unit', (string) self::getAttribute($chartDetail->minorUnit, 'val', 'string')); > } > if (isset($chartDetail->baseTimeUnit)) { > $whichAxis->setAxisOption('baseTimeUnit', (string) self::getAttribute($chartDetail->baseTimeUnit, 'val', 'string')); > } > if (isset($chartDetail->majorTimeUnit)) { > $whichAxis->setAxisOption('majorTimeUnit', (string) self::getAttribute($chartDetail->majorTimeUnit, 'val', 'string')); > } > if (isset($chartDetail->minorTimeUnit)) { > $whichAxis->setAxisOption('minorTimeUnit', (string) self::getAttribute($chartDetail->minorTimeUnit, 'val', 'string')); > } > if (isset($chartDetail->txPr)) { > $children = $chartDetail->txPr->children($this->aNamespace); > if (isset($children->bodyPr)) { > /** @var string */ > $textRotation = self::getAttribute($children->bodyPr, 'rot', 'string'); > if (is_numeric($textRotation)) { > $whichAxis->setAxisOption('textRotation', (string) ChartProperties::xmlToAngle($textRotation)); > }