package and depencies
This commit is contained in:
@@ -10,20 +10,52 @@ namespace PhpOffice\PhpSpreadsheet\Chart;
|
||||
*/
|
||||
class Axis extends Properties
|
||||
{
|
||||
const AXIS_TYPE_CATEGORY = 'catAx';
|
||||
const AXIS_TYPE_DATE = 'dateAx';
|
||||
const AXIS_TYPE_VALUE = 'valAx';
|
||||
|
||||
const TIME_UNIT_DAYS = 'days';
|
||||
const TIME_UNIT_MONTHS = 'months';
|
||||
const TIME_UNIT_YEARS = 'years';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->fillColor = new ChartColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Chart Major Gridlines as.
|
||||
*
|
||||
* @var ?GridLines
|
||||
*/
|
||||
private $majorGridlines;
|
||||
|
||||
/**
|
||||
* Chart Minor Gridlines as.
|
||||
*
|
||||
* @var ?GridLines
|
||||
*/
|
||||
private $minorGridlines;
|
||||
|
||||
/**
|
||||
* Axis Number.
|
||||
*
|
||||
* @var array of mixed
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $axisNumber = [
|
||||
'format' => self::FORMAT_CODE_GENERAL,
|
||||
'source_linked' => 1,
|
||||
'numeric' => null,
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
private $axisType = '';
|
||||
|
||||
/**
|
||||
* Axis Options.
|
||||
*
|
||||
* @var array of mixed
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $axisOptions = [
|
||||
'minimum' => null,
|
||||
@@ -36,112 +68,41 @@ class Axis extends Properties
|
||||
'axis_labels' => self::AXIS_LABELS_NEXT_TO,
|
||||
'horizontal_crosses' => self::HORIZONTAL_CROSSES_AUTOZERO,
|
||||
'horizontal_crosses_value' => null,
|
||||
'textRotation' => null,
|
||||
'hidden' => null,
|
||||
'majorTimeUnit' => self::TIME_UNIT_YEARS,
|
||||
'minorTimeUnit' => self::TIME_UNIT_MONTHS,
|
||||
'baseTimeUnit' => self::TIME_UNIT_DAYS,
|
||||
];
|
||||
|
||||
/**
|
||||
* Fill Properties.
|
||||
*
|
||||
* @var array of mixed
|
||||
* @var ChartColor
|
||||
*/
|
||||
private $fillProperties = [
|
||||
'type' => self::EXCEL_COLOR_TYPE_ARGB,
|
||||
'value' => null,
|
||||
'alpha' => 0,
|
||||
];
|
||||
private $fillColor;
|
||||
|
||||
/**
|
||||
* Line Properties.
|
||||
*
|
||||
* @var array of mixed
|
||||
*/
|
||||
private $lineProperties = [
|
||||
'type' => self::EXCEL_COLOR_TYPE_ARGB,
|
||||
'value' => null,
|
||||
'alpha' => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* Line Style Properties.
|
||||
*
|
||||
* @var array of mixed
|
||||
*/
|
||||
private $lineStyleProperties = [
|
||||
'width' => '9525',
|
||||
'compound' => self::LINE_STYLE_COMPOUND_SIMPLE,
|
||||
'dash' => self::LINE_STYLE_DASH_SOLID,
|
||||
'cap' => self::LINE_STYLE_CAP_FLAT,
|
||||
'join' => self::LINE_STYLE_JOIN_BEVEL,
|
||||
'arrow' => [
|
||||
'head' => [
|
||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
||||
'size' => self::LINE_STYLE_ARROW_SIZE_5,
|
||||
],
|
||||
'end' => [
|
||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
||||
'size' => self::LINE_STYLE_ARROW_SIZE_8,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Shadow Properties.
|
||||
*
|
||||
* @var array of mixed
|
||||
*/
|
||||
private $shadowProperties = [
|
||||
'presets' => self::SHADOW_PRESETS_NOSHADOW,
|
||||
'effect' => null,
|
||||
'color' => [
|
||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
||||
'value' => 'black',
|
||||
'alpha' => 40,
|
||||
],
|
||||
'size' => [
|
||||
'sx' => null,
|
||||
'sy' => null,
|
||||
'kx' => null,
|
||||
],
|
||||
'blur' => null,
|
||||
'direction' => null,
|
||||
'distance' => null,
|
||||
'algn' => null,
|
||||
'rotWithShape' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
* Glow Properties.
|
||||
*
|
||||
* @var array of mixed
|
||||
*/
|
||||
private $glowProperties = [
|
||||
'size' => null,
|
||||
'color' => [
|
||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
||||
'value' => 'black',
|
||||
'alpha' => 40,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Soft Edge Properties.
|
||||
*
|
||||
* @var array of mixed
|
||||
*/
|
||||
private $softEdges = [
|
||||
'size' => null,
|
||||
private const NUMERIC_FORMAT = [
|
||||
Properties::FORMAT_CODE_NUMBER,
|
||||
Properties::FORMAT_CODE_DATE,
|
||||
Properties::FORMAT_CODE_DATE_ISO8601,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get Series Data Type.
|
||||
*
|
||||
* @param mixed $format_code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function setAxisNumberProperties($format_code)
|
||||
public function setAxisNumberProperties($format_code, ?bool $numeric = null, int $sourceLinked = 0): void
|
||||
{
|
||||
$this->axisNumber['format'] = (string) $format_code;
|
||||
$this->axisNumber['source_linked'] = 0;
|
||||
$format = (string) $format_code;
|
||||
$this->axisNumber['format'] = $format;
|
||||
$this->axisNumber['source_linked'] = $sourceLinked;
|
||||
if (is_bool($numeric)) {
|
||||
$this->axisNumber['numeric'] = $numeric;
|
||||
} elseif (in_array($format, self::NUMERIC_FORMAT, true)) {
|
||||
$this->axisNumber['numeric'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,33 +125,53 @@ class Axis extends Properties
|
||||
return (string) $this->axisNumber['source_linked'];
|
||||
}
|
||||
|
||||
public function getAxisIsNumericFormat(): bool
|
||||
{
|
||||
return $this->axisType === self::AXIS_TYPE_DATE || (bool) $this->axisNumber['numeric'];
|
||||
}
|
||||
|
||||
public function setAxisOption(string $key, ?string $value): void
|
||||
{
|
||||
if ($value !== null && $value !== '') {
|
||||
$this->axisOptions[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Axis Options Properties.
|
||||
*
|
||||
* @param string $axis_labels
|
||||
* @param string $horizontal_crosses_value
|
||||
* @param string $horizontal_crosses
|
||||
* @param string $axis_orientation
|
||||
* @param string $major_tmt
|
||||
* @param string $minor_tmt
|
||||
* @param string $minimum
|
||||
* @param string $maximum
|
||||
* @param string $major_unit
|
||||
* @param string $minor_unit
|
||||
*/
|
||||
public function setAxisOptionsProperties($axis_labels, $horizontal_crosses_value = null, $horizontal_crosses = null, $axis_orientation = null, $major_tmt = null, $minor_tmt = null, $minimum = null, $maximum = null, $major_unit = null, $minor_unit = null): void
|
||||
{
|
||||
$this->axisOptions['axis_labels'] = (string) $axis_labels;
|
||||
($horizontal_crosses_value !== null) ? $this->axisOptions['horizontal_crosses_value'] = (string) $horizontal_crosses_value : null;
|
||||
($horizontal_crosses !== null) ? $this->axisOptions['horizontal_crosses'] = (string) $horizontal_crosses : null;
|
||||
($axis_orientation !== null) ? $this->axisOptions['orientation'] = (string) $axis_orientation : null;
|
||||
($major_tmt !== null) ? $this->axisOptions['major_tick_mark'] = (string) $major_tmt : null;
|
||||
($minor_tmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minor_tmt : null;
|
||||
($minor_tmt !== null) ? $this->axisOptions['minor_tick_mark'] = (string) $minor_tmt : null;
|
||||
($minimum !== null) ? $this->axisOptions['minimum'] = (string) $minimum : null;
|
||||
($maximum !== null) ? $this->axisOptions['maximum'] = (string) $maximum : null;
|
||||
($major_unit !== null) ? $this->axisOptions['major_unit'] = (string) $major_unit : null;
|
||||
($minor_unit !== null) ? $this->axisOptions['minor_unit'] = (string) $minor_unit : null;
|
||||
public function setAxisOptionsProperties(
|
||||
string $axisLabels,
|
||||
?string $horizontalCrossesValue = null,
|
||||
?string $horizontalCrosses = null,
|
||||
?string $axisOrientation = null,
|
||||
?string $majorTmt = null,
|
||||
?string $minorTmt = null,
|
||||
?string $minimum = null,
|
||||
?string $maximum = null,
|
||||
?string $majorUnit = null,
|
||||
?string $minorUnit = null,
|
||||
?string $textRotation = null,
|
||||
?string $hidden = null,
|
||||
?string $baseTimeUnit = null,
|
||||
?string $majorTimeUnit = null,
|
||||
?string $minorTimeUnit = null
|
||||
): void {
|
||||
$this->axisOptions['axis_labels'] = $axisLabels;
|
||||
$this->setAxisOption('horizontal_crosses_value', $horizontalCrossesValue);
|
||||
$this->setAxisOption('horizontal_crosses', $horizontalCrosses);
|
||||
$this->setAxisOption('orientation', $axisOrientation);
|
||||
$this->setAxisOption('major_tick_mark', $majorTmt);
|
||||
$this->setAxisOption('minor_tick_mark', $minorTmt);
|
||||
$this->setAxisOption('minimum', $minimum);
|
||||
$this->setAxisOption('maximum', $maximum);
|
||||
$this->setAxisOption('major_unit', $majorUnit);
|
||||
$this->setAxisOption('minor_unit', $minorUnit);
|
||||
$this->setAxisOption('textRotation', $textRotation);
|
||||
$this->setAxisOption('hidden', $hidden);
|
||||
$this->setAxisOption('baseTimeUnit', $baseTimeUnit);
|
||||
$this->setAxisOption('majorTimeUnit', $majorTimeUnit);
|
||||
$this->setAxisOption('minorTimeUnit', $minorTimeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +179,7 @@ class Axis extends Properties
|
||||
*
|
||||
* @param string $property
|
||||
*
|
||||
* @return string
|
||||
* @return ?string
|
||||
*/
|
||||
public function getAxisOptionsProperty($property)
|
||||
{
|
||||
@@ -215,28 +196,32 @@ class Axis extends Properties
|
||||
$this->axisOptions['orientation'] = (string) $orientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Fill Property.
|
||||
*
|
||||
* @param string $color
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*/
|
||||
public function setFillParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB): void
|
||||
public function getAxisType(): string
|
||||
{
|
||||
$this->fillProperties = $this->setColorProperties($color, $alpha, $type);
|
||||
return $this->axisType;
|
||||
}
|
||||
|
||||
public function setAxisType(string $type): self
|
||||
{
|
||||
if ($type === self::AXIS_TYPE_CATEGORY || $type === self::AXIS_TYPE_VALUE || $type === self::AXIS_TYPE_DATE) {
|
||||
$this->axisType = $type;
|
||||
} else {
|
||||
$this->axisType = '';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Line Property.
|
||||
* Set Fill Property.
|
||||
*
|
||||
* @param string $color
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
* @param ?string $color
|
||||
* @param ?int $alpha
|
||||
* @param ?string $AlphaType
|
||||
*/
|
||||
public function setLineParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB): void
|
||||
public function setFillParameters($color, $alpha = null, $AlphaType = ChartColor::EXCEL_COLOR_TYPE_RGB): void
|
||||
{
|
||||
$this->lineProperties = $this->setColorProperties($color, $alpha, $type);
|
||||
$this->fillColor->setColorProperties($color, $alpha, $AlphaType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,309 +233,66 @@ class Axis extends Properties
|
||||
*/
|
||||
public function getFillProperty($property)
|
||||
{
|
||||
return $this->fillProperties[$property];
|
||||
return (string) $this->fillColor->getColorProperty($property);
|
||||
}
|
||||
|
||||
public function getFillColorObject(): ChartColor
|
||||
{
|
||||
return $this->fillColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Line Property.
|
||||
* Get Line Color Property.
|
||||
*
|
||||
* @param string $property
|
||||
* @deprecated 1.24.0
|
||||
* Use the getLineColor property in the Properties class instead
|
||||
* @see Properties::getLineColorProperty()
|
||||
*
|
||||
* @return string
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return null|int|string
|
||||
*/
|
||||
public function getLineProperty($property)
|
||||
public function getLineProperty($propertyName)
|
||||
{
|
||||
return $this->lineProperties[$property];
|
||||
return $this->getLineColorProperty($propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Line Style Properties.
|
||||
*
|
||||
* @param float $line_width
|
||||
* @param string $compound_type
|
||||
* @param string $dash_type
|
||||
* @param string $cap_type
|
||||
* @param string $join_type
|
||||
* @param string $head_arrow_type
|
||||
* @param string $head_arrow_size
|
||||
* @param string $end_arrow_type
|
||||
* @param string $end_arrow_size
|
||||
*/
|
||||
public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null): void
|
||||
{
|
||||
($line_width !== null) ? $this->lineStyleProperties['width'] = $this->getExcelPointsWidth((float) $line_width) : null;
|
||||
($compound_type !== null) ? $this->lineStyleProperties['compound'] = (string) $compound_type : null;
|
||||
($dash_type !== null) ? $this->lineStyleProperties['dash'] = (string) $dash_type : null;
|
||||
($cap_type !== null) ? $this->lineStyleProperties['cap'] = (string) $cap_type : null;
|
||||
($join_type !== null) ? $this->lineStyleProperties['join'] = (string) $join_type : null;
|
||||
($head_arrow_type !== null) ? $this->lineStyleProperties['arrow']['head']['type'] = (string) $head_arrow_type : null;
|
||||
($head_arrow_size !== null) ? $this->lineStyleProperties['arrow']['head']['size'] = (string) $head_arrow_size : null;
|
||||
($end_arrow_type !== null) ? $this->lineStyleProperties['arrow']['end']['type'] = (string) $end_arrow_type : null;
|
||||
($end_arrow_size !== null) ? $this->lineStyleProperties['arrow']['end']['size'] = (string) $end_arrow_size : null;
|
||||
}
|
||||
/** @var string */
|
||||
private $crossBetween = ''; // 'between' or 'midCat' might be better
|
||||
|
||||
/**
|
||||
* Get Line Style Property.
|
||||
*
|
||||
* @param array|string $elements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLineStyleProperty($elements)
|
||||
public function setCrossBetween(string $crossBetween): self
|
||||
{
|
||||
return $this->getArrayElementsValue($this->lineStyleProperties, $elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Line Style Arrow Excel Width.
|
||||
*
|
||||
* @param string $arrow
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLineStyleArrowWidth($arrow)
|
||||
{
|
||||
return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'w');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Line Style Arrow Excel Length.
|
||||
*
|
||||
* @param string $arrow
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLineStyleArrowLength($arrow)
|
||||
{
|
||||
return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrow]['size'], 'len');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Properties.
|
||||
*
|
||||
* @param int $sh_presets
|
||||
* @param string $sh_color_value
|
||||
* @param string $sh_color_type
|
||||
* @param string $sh_color_alpha
|
||||
* @param float $sh_blur
|
||||
* @param int $sh_angle
|
||||
* @param float $sh_distance
|
||||
*/
|
||||
public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null): void
|
||||
{
|
||||
$this->setShadowPresetsProperties((int) $sh_presets)
|
||||
->setShadowColor(
|
||||
$sh_color_value === null ? $this->shadowProperties['color']['value'] : $sh_color_value,
|
||||
$sh_color_alpha === null ? (int) $this->shadowProperties['color']['alpha'] : $sh_color_alpha,
|
||||
$sh_color_type === null ? $this->shadowProperties['color']['type'] : $sh_color_type
|
||||
)
|
||||
->setShadowBlur($sh_blur)
|
||||
->setShadowAngle($sh_angle)
|
||||
->setShadowDistance($sh_distance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Color.
|
||||
*
|
||||
* @param int $shadow_presets
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowPresetsProperties($shadow_presets)
|
||||
{
|
||||
$this->shadowProperties['presets'] = $shadow_presets;
|
||||
$this->setShadowProperiesMapValues($this->getShadowPresetsMap($shadow_presets));
|
||||
$this->crossBetween = $crossBetween;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Properties from Mapped Values.
|
||||
*
|
||||
* @param mixed &$reference
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowProperiesMapValues(array $properties_map, &$reference = null)
|
||||
public function getCrossBetween(): string
|
||||
{
|
||||
$base_reference = $reference;
|
||||
foreach ($properties_map as $property_key => $property_val) {
|
||||
if (is_array($property_val)) {
|
||||
if ($reference === null) {
|
||||
$reference = &$this->shadowProperties[$property_key];
|
||||
} else {
|
||||
$reference = &$reference[$property_key];
|
||||
}
|
||||
$this->setShadowProperiesMapValues($property_val, $reference);
|
||||
} else {
|
||||
if ($base_reference === null) {
|
||||
$this->shadowProperties[$property_key] = $property_val;
|
||||
} else {
|
||||
$reference[$property_key] = $property_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->crossBetween;
|
||||
}
|
||||
|
||||
public function getMajorGridlines(): ?GridLines
|
||||
{
|
||||
return $this->majorGridlines;
|
||||
}
|
||||
|
||||
public function getMinorGridlines(): ?GridLines
|
||||
{
|
||||
return $this->minorGridlines;
|
||||
}
|
||||
|
||||
public function setMajorGridlines(?GridLines $gridlines): self
|
||||
{
|
||||
$this->majorGridlines = $gridlines;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Color.
|
||||
*
|
||||
* @param string $color
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowColor($color, $alpha, $type)
|
||||
public function setMinorGridlines(?GridLines $gridlines): self
|
||||
{
|
||||
$this->shadowProperties['color'] = $this->setColorProperties($color, $alpha, $type);
|
||||
$this->minorGridlines = $gridlines;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Blur.
|
||||
*
|
||||
* @param float $blur
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowBlur($blur)
|
||||
{
|
||||
if ($blur !== null) {
|
||||
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Angle.
|
||||
*
|
||||
* @param int $angle
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowAngle($angle)
|
||||
{
|
||||
if ($angle !== null) {
|
||||
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Distance.
|
||||
*
|
||||
* @param float $distance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowDistance($distance)
|
||||
{
|
||||
if ($distance !== null) {
|
||||
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Shadow Property.
|
||||
*
|
||||
* @param string|string[] $elements
|
||||
*
|
||||
* @return null|array|int|string
|
||||
*/
|
||||
public function getShadowProperty($elements)
|
||||
{
|
||||
return $this->getArrayElementsValue($this->shadowProperties, $elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Glow Properties.
|
||||
*
|
||||
* @param float $size
|
||||
* @param string $color_value
|
||||
* @param int $color_alpha
|
||||
* @param string $color_type
|
||||
*/
|
||||
public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null): void
|
||||
{
|
||||
$this->setGlowSize($size)
|
||||
->setGlowColor(
|
||||
$color_value === null ? $this->glowProperties['color']['value'] : $color_value,
|
||||
$color_alpha === null ? (int) $this->glowProperties['color']['alpha'] : $color_alpha,
|
||||
$color_type === null ? $this->glowProperties['color']['type'] : $color_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Glow Property.
|
||||
*
|
||||
* @param array|string $property
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGlowProperty($property)
|
||||
{
|
||||
return $this->getArrayElementsValue($this->glowProperties, $property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Glow Color.
|
||||
*
|
||||
* @param float $size
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowSize($size)
|
||||
{
|
||||
if ($size !== null) {
|
||||
$this->glowProperties['size'] = $this->getExcelPointsWidth($size);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Glow Color.
|
||||
*
|
||||
* @param string $color
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowColor($color, $alpha, $type)
|
||||
{
|
||||
$this->glowProperties['color'] = $this->setColorProperties($color, $alpha, $type);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Soft Edges Size.
|
||||
*
|
||||
* @param float $size
|
||||
*/
|
||||
public function setSoftEdges($size): void
|
||||
{
|
||||
if ($size !== null) {
|
||||
$softEdges['size'] = (string) $this->getExcelPointsWidth($size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Soft Edges Size.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSoftEdgesSize()
|
||||
{
|
||||
return $this->softEdges['size'];
|
||||
}
|
||||
}
|
||||
|
@@ -17,42 +17,42 @@ class Chart
|
||||
/**
|
||||
* Worksheet.
|
||||
*
|
||||
* @var Worksheet
|
||||
* @var ?Worksheet
|
||||
*/
|
||||
private $worksheet;
|
||||
|
||||
/**
|
||||
* Chart Title.
|
||||
*
|
||||
* @var Title
|
||||
* @var ?Title
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* Chart Legend.
|
||||
*
|
||||
* @var Legend
|
||||
* @var ?Legend
|
||||
*/
|
||||
private $legend;
|
||||
|
||||
/**
|
||||
* X-Axis Label.
|
||||
*
|
||||
* @var Title
|
||||
* @var ?Title
|
||||
*/
|
||||
private $xAxisLabel;
|
||||
|
||||
/**
|
||||
* Y-Axis Label.
|
||||
*
|
||||
* @var Title
|
||||
* @var ?Title
|
||||
*/
|
||||
private $yAxisLabel;
|
||||
|
||||
/**
|
||||
* Chart Plot Area.
|
||||
*
|
||||
* @var PlotArea
|
||||
* @var ?PlotArea
|
||||
*/
|
||||
private $plotArea;
|
||||
|
||||
@@ -84,20 +84,6 @@ class Chart
|
||||
*/
|
||||
private $xAxis;
|
||||
|
||||
/**
|
||||
* Chart Major Gridlines as.
|
||||
*
|
||||
* @var GridLines
|
||||
*/
|
||||
private $majorGridlines;
|
||||
|
||||
/**
|
||||
* Chart Minor Gridlines as.
|
||||
*
|
||||
* @var GridLines
|
||||
*/
|
||||
private $minorGridlines;
|
||||
|
||||
/**
|
||||
* Top-Left Cell Position.
|
||||
*
|
||||
@@ -124,7 +110,7 @@ class Chart
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $bottomRightCellRef = 'A1';
|
||||
private $bottomRightCellRef = '';
|
||||
|
||||
/**
|
||||
* Bottom-Right X-Offset.
|
||||
@@ -140,8 +126,33 @@ class Chart
|
||||
*/
|
||||
private $bottomRightYOffset = 10;
|
||||
|
||||
/** @var ?int */
|
||||
private $rotX;
|
||||
|
||||
/** @var ?int */
|
||||
private $rotY;
|
||||
|
||||
/** @var ?int */
|
||||
private $rAngAx;
|
||||
|
||||
/** @var ?int */
|
||||
private $perspective;
|
||||
|
||||
/** @var bool */
|
||||
private $oneCellAnchor = false;
|
||||
|
||||
/** @var bool */
|
||||
private $autoTitleDeleted = false;
|
||||
|
||||
/** @var bool */
|
||||
private $noFill = false;
|
||||
|
||||
/** @var bool */
|
||||
private $roundedCorners = false;
|
||||
|
||||
/**
|
||||
* Create a new Chart.
|
||||
* majorGridlines and minorGridlines are deprecated, moved to Axis.
|
||||
*
|
||||
* @param mixed $name
|
||||
* @param mixed $plotVisibleOnly
|
||||
@@ -157,10 +168,14 @@ class Chart
|
||||
$this->plotArea = $plotArea;
|
||||
$this->plotVisibleOnly = $plotVisibleOnly;
|
||||
$this->displayBlanksAs = $displayBlanksAs;
|
||||
$this->xAxis = $xAxis;
|
||||
$this->yAxis = $yAxis;
|
||||
$this->majorGridlines = $majorGridlines;
|
||||
$this->minorGridlines = $minorGridlines;
|
||||
$this->xAxis = $xAxis ?? new Axis();
|
||||
$this->yAxis = $yAxis ?? new Axis();
|
||||
if ($majorGridlines !== null) {
|
||||
$this->yAxis->setMajorGridlines($majorGridlines);
|
||||
}
|
||||
if ($minorGridlines !== null) {
|
||||
$this->yAxis->setMinorGridlines($minorGridlines);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,12 +188,17 @@ class Chart
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Worksheet.
|
||||
*
|
||||
* @return Worksheet
|
||||
*/
|
||||
public function getWorksheet()
|
||||
public function getWorksheet(): ?Worksheet
|
||||
{
|
||||
return $this->worksheet;
|
||||
}
|
||||
@@ -186,23 +206,16 @@ class Chart
|
||||
/**
|
||||
* Set Worksheet.
|
||||
*
|
||||
* @param Worksheet $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWorksheet(?Worksheet $pValue = null)
|
||||
public function setWorksheet(?Worksheet $worksheet = null)
|
||||
{
|
||||
$this->worksheet = $pValue;
|
||||
$this->worksheet = $worksheet;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Title.
|
||||
*
|
||||
* @return Title
|
||||
*/
|
||||
public function getTitle()
|
||||
public function getTitle(): ?Title
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
@@ -219,12 +232,7 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Legend.
|
||||
*
|
||||
* @return Legend
|
||||
*/
|
||||
public function getLegend()
|
||||
public function getLegend(): ?Legend
|
||||
{
|
||||
return $this->legend;
|
||||
}
|
||||
@@ -241,12 +249,7 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X-Axis Label.
|
||||
*
|
||||
* @return Title
|
||||
*/
|
||||
public function getXAxisLabel()
|
||||
public function getXAxisLabel(): ?Title
|
||||
{
|
||||
return $this->xAxisLabel;
|
||||
}
|
||||
@@ -263,12 +266,7 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Y-Axis Label.
|
||||
*
|
||||
* @return Title
|
||||
*/
|
||||
public function getYAxisLabel()
|
||||
public function getYAxisLabel(): ?Title
|
||||
{
|
||||
return $this->yAxisLabel;
|
||||
}
|
||||
@@ -285,16 +283,21 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Plot Area.
|
||||
*
|
||||
* @return PlotArea
|
||||
*/
|
||||
public function getPlotArea()
|
||||
public function getPlotArea(): ?PlotArea
|
||||
{
|
||||
return $this->plotArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Plot Area.
|
||||
*/
|
||||
public function setPlotArea(PlotArea $plotArea): self
|
||||
{
|
||||
$this->plotArea = $plotArea;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Plot Visible Only.
|
||||
*
|
||||
@@ -343,74 +346,74 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get yAxis.
|
||||
*
|
||||
* @return Axis
|
||||
*/
|
||||
public function getChartAxisY()
|
||||
public function getChartAxisY(): Axis
|
||||
{
|
||||
if ($this->yAxis !== null) {
|
||||
return $this->yAxis;
|
||||
}
|
||||
|
||||
return new Axis();
|
||||
return $this->yAxis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get xAxis.
|
||||
*
|
||||
* @return Axis
|
||||
* Set yAxis.
|
||||
*/
|
||||
public function getChartAxisX()
|
||||
public function setChartAxisY(?Axis $axis): self
|
||||
{
|
||||
if ($this->xAxis !== null) {
|
||||
return $this->xAxis;
|
||||
}
|
||||
$this->yAxis = $axis ?? new Axis();
|
||||
|
||||
return new Axis();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getChartAxisX(): Axis
|
||||
{
|
||||
return $this->xAxis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set xAxis.
|
||||
*/
|
||||
public function setChartAxisX(?Axis $axis): self
|
||||
{
|
||||
$this->xAxis = $axis ?? new Axis();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Major Gridlines.
|
||||
*
|
||||
* @return GridLines
|
||||
* @deprecated 1.24.0 Use Axis->getMajorGridlines()
|
||||
* @see Axis::getMajorGridlines()
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getMajorGridlines()
|
||||
public function getMajorGridlines(): ?GridLines
|
||||
{
|
||||
if ($this->majorGridlines !== null) {
|
||||
return $this->majorGridlines;
|
||||
}
|
||||
|
||||
return new GridLines();
|
||||
return $this->yAxis->getMajorGridLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Minor Gridlines.
|
||||
*
|
||||
* @return GridLines
|
||||
* @deprecated 1.24.0 Use Axis->getMinorGridlines()
|
||||
* @see Axis::getMinorGridlines()
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getMinorGridlines()
|
||||
public function getMinorGridlines(): ?GridLines
|
||||
{
|
||||
if ($this->minorGridlines !== null) {
|
||||
return $this->minorGridlines;
|
||||
}
|
||||
|
||||
return new GridLines();
|
||||
return $this->yAxis->getMinorGridLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Top Left position for the chart.
|
||||
*
|
||||
* @param string $cell
|
||||
* @param string $cellAddress
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTopLeftPosition($cell, $xOffset = null, $yOffset = null)
|
||||
public function setTopLeftPosition($cellAddress, $xOffset = null, $yOffset = null)
|
||||
{
|
||||
$this->topLeftCellRef = $cell;
|
||||
$this->topLeftCellRef = $cellAddress;
|
||||
if ($xOffset !== null) {
|
||||
$this->setTopLeftXOffset($xOffset);
|
||||
}
|
||||
@@ -424,9 +427,11 @@ class Chart
|
||||
/**
|
||||
* Get the top left position of the chart.
|
||||
*
|
||||
* @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell
|
||||
* Returns ['cell' => string cell address, 'xOffset' => int, 'yOffset' => int].
|
||||
*
|
||||
* @return array{cell: string, xOffset: int, yOffset: int} an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell
|
||||
*/
|
||||
public function getTopLeftPosition()
|
||||
public function getTopLeftPosition(): array
|
||||
{
|
||||
return [
|
||||
'cell' => $this->topLeftCellRef,
|
||||
@@ -448,13 +453,13 @@ class Chart
|
||||
/**
|
||||
* Set the Top Left cell position for the chart.
|
||||
*
|
||||
* @param string $cell
|
||||
* @param string $cellAddress
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTopLeftCell($cell)
|
||||
public function setTopLeftCell($cellAddress)
|
||||
{
|
||||
$this->topLeftCellRef = $cell;
|
||||
$this->topLeftCellRef = $cellAddress;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -462,8 +467,8 @@ class Chart
|
||||
/**
|
||||
* Set the offset position within the Top Left cell for the chart.
|
||||
*
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
* @param ?int $xOffset
|
||||
* @param ?int $yOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -493,6 +498,11 @@ class Chart
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $xOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTopLeftXOffset($xOffset)
|
||||
{
|
||||
$this->topLeftXOffset = $xOffset;
|
||||
@@ -500,11 +510,16 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTopLeftXOffset()
|
||||
public function getTopLeftXOffset(): int
|
||||
{
|
||||
return $this->topLeftXOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTopLeftYOffset($yOffset)
|
||||
{
|
||||
$this->topLeftYOffset = $yOffset;
|
||||
@@ -512,7 +527,7 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTopLeftYOffset()
|
||||
public function getTopLeftYOffset(): int
|
||||
{
|
||||
return $this->topLeftYOffset;
|
||||
}
|
||||
@@ -520,15 +535,15 @@ class Chart
|
||||
/**
|
||||
* Set the Bottom Right position of the chart.
|
||||
*
|
||||
* @param string $cell
|
||||
* @param string $cellAddress
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottomRightPosition($cell, $xOffset = null, $yOffset = null)
|
||||
public function setBottomRightPosition($cellAddress = '', $xOffset = null, $yOffset = null)
|
||||
{
|
||||
$this->bottomRightCellRef = $cell;
|
||||
$this->bottomRightCellRef = $cellAddress;
|
||||
if ($xOffset !== null) {
|
||||
$this->setBottomRightXOffset($xOffset);
|
||||
}
|
||||
@@ -553,19 +568,22 @@ class Chart
|
||||
];
|
||||
}
|
||||
|
||||
public function setBottomRightCell($cell)
|
||||
/**
|
||||
* Set the Bottom Right cell for the chart.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottomRightCell(string $cellAddress = '')
|
||||
{
|
||||
$this->bottomRightCellRef = $cell;
|
||||
$this->bottomRightCellRef = $cellAddress;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cell address where the bottom right of the chart is fixed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBottomRightCell()
|
||||
public function getBottomRightCell(): string
|
||||
{
|
||||
return $this->bottomRightCellRef;
|
||||
}
|
||||
@@ -573,8 +591,8 @@ class Chart
|
||||
/**
|
||||
* Set the offset position within the Bottom Right cell for the chart.
|
||||
*
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
* @param ?int $xOffset
|
||||
* @param ?int $yOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -604,6 +622,11 @@ class Chart
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $xOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottomRightXOffset($xOffset)
|
||||
{
|
||||
$this->bottomRightXOffset = $xOffset;
|
||||
@@ -611,11 +634,16 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBottomRightXOffset()
|
||||
public function getBottomRightXOffset(): int
|
||||
{
|
||||
return $this->bottomRightXOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottomRightYOffset($yOffset)
|
||||
{
|
||||
$this->bottomRightYOffset = $yOffset;
|
||||
@@ -623,14 +651,14 @@ class Chart
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBottomRightYOffset()
|
||||
public function getBottomRightYOffset(): int
|
||||
{
|
||||
return $this->bottomRightYOffset;
|
||||
}
|
||||
|
||||
public function refresh(): void
|
||||
{
|
||||
if ($this->worksheet !== null) {
|
||||
if ($this->worksheet !== null && $this->plotArea !== null) {
|
||||
$this->plotArea->refresh($this->worksheet);
|
||||
}
|
||||
}
|
||||
@@ -658,6 +686,104 @@ class Chart
|
||||
|
||||
$renderer = new $libraryName($this);
|
||||
|
||||
return $renderer->render($outputDestination);
|
||||
return $renderer->render($outputDestination); // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
public function getRotX(): ?int
|
||||
{
|
||||
return $this->rotX;
|
||||
}
|
||||
|
||||
public function setRotX(?int $rotX): self
|
||||
{
|
||||
$this->rotX = $rotX;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRotY(): ?int
|
||||
{
|
||||
return $this->rotY;
|
||||
}
|
||||
|
||||
public function setRotY(?int $rotY): self
|
||||
{
|
||||
$this->rotY = $rotY;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRAngAx(): ?int
|
||||
{
|
||||
return $this->rAngAx;
|
||||
}
|
||||
|
||||
public function setRAngAx(?int $rAngAx): self
|
||||
{
|
||||
$this->rAngAx = $rAngAx;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPerspective(): ?int
|
||||
{
|
||||
return $this->perspective;
|
||||
}
|
||||
|
||||
public function setPerspective(?int $perspective): self
|
||||
{
|
||||
$this->perspective = $perspective;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOneCellAnchor(): bool
|
||||
{
|
||||
return $this->oneCellAnchor;
|
||||
}
|
||||
|
||||
public function setOneCellAnchor(bool $oneCellAnchor): self
|
||||
{
|
||||
$this->oneCellAnchor = $oneCellAnchor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAutoTitleDeleted(): bool
|
||||
{
|
||||
return $this->autoTitleDeleted;
|
||||
}
|
||||
|
||||
public function setAutoTitleDeleted(bool $autoTitleDeleted): self
|
||||
{
|
||||
$this->autoTitleDeleted = $autoTitleDeleted;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNoFill(): bool
|
||||
{
|
||||
return $this->noFill;
|
||||
}
|
||||
|
||||
public function setNoFill(bool $noFill): self
|
||||
{
|
||||
$this->noFill = $noFill;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRoundedCorners(): bool
|
||||
{
|
||||
return $this->roundedCorners;
|
||||
}
|
||||
|
||||
public function setRoundedCorners(?bool $roundedCorners): self
|
||||
{
|
||||
if ($roundedCorners !== null) {
|
||||
$this->roundedCorners = $roundedCorners;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
177
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/ChartColor.php
vendored
Normal file
177
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/ChartColor.php
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Chart;
|
||||
|
||||
class ChartColor
|
||||
{
|
||||
const EXCEL_COLOR_TYPE_STANDARD = 'prstClr';
|
||||
const EXCEL_COLOR_TYPE_SCHEME = 'schemeClr';
|
||||
const EXCEL_COLOR_TYPE_RGB = 'srgbClr';
|
||||
/** @deprecated 1.24 use EXCEL_COLOR_TYPE_RGB instead */
|
||||
const EXCEL_COLOR_TYPE_ARGB = 'srgbClr';
|
||||
const EXCEL_COLOR_TYPES = [
|
||||
self::EXCEL_COLOR_TYPE_ARGB,
|
||||
self::EXCEL_COLOR_TYPE_SCHEME,
|
||||
self::EXCEL_COLOR_TYPE_STANDARD,
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
private $value = '';
|
||||
|
||||
/** @var string */
|
||||
private $type = '';
|
||||
|
||||
/** @var ?int */
|
||||
private $alpha;
|
||||
|
||||
/** @var ?int */
|
||||
private $brightness;
|
||||
|
||||
/**
|
||||
* @param string|string[] $value
|
||||
*/
|
||||
public function __construct($value = '', ?int $alpha = null, ?string $type = null, ?int $brightness = null)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$this->setColorPropertiesArray($value);
|
||||
} else {
|
||||
$this->setColorProperties($value, $alpha, $type, $brightness);
|
||||
}
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setValue(string $value): self
|
||||
{
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(string $type): self
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAlpha(): ?int
|
||||
{
|
||||
return $this->alpha;
|
||||
}
|
||||
|
||||
public function setAlpha(?int $alpha): self
|
||||
{
|
||||
$this->alpha = $alpha;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBrightness(): ?int
|
||||
{
|
||||
return $this->brightness;
|
||||
}
|
||||
|
||||
public function setBrightness(?int $brightness): self
|
||||
{
|
||||
$this->brightness = $brightness;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|float|int|string $alpha
|
||||
* @param null|float|int|string $brightness
|
||||
*/
|
||||
public function setColorProperties(?string $color, $alpha = null, ?string $type = null, $brightness = null): self
|
||||
{
|
||||
if (empty($type) && !empty($color)) {
|
||||
if (substr($color, 0, 1) === '*') {
|
||||
$type = 'schemeClr';
|
||||
$color = substr($color, 1);
|
||||
} elseif (substr($color, 0, 1) === '/') {
|
||||
$type = 'prstClr';
|
||||
$color = substr($color, 1);
|
||||
} elseif (preg_match('/^[0-9A-Fa-f]{6}$/', $color) === 1) {
|
||||
$type = 'srgbClr';
|
||||
}
|
||||
}
|
||||
if ($color !== null) {
|
||||
$this->setValue("$color");
|
||||
}
|
||||
if ($type !== null) {
|
||||
$this->setType($type);
|
||||
}
|
||||
if ($alpha === null) {
|
||||
$this->setAlpha(null);
|
||||
} elseif (is_numeric($alpha)) {
|
||||
$this->setAlpha((int) $alpha);
|
||||
}
|
||||
if ($brightness === null) {
|
||||
$this->setBrightness(null);
|
||||
} elseif (is_numeric($brightness)) {
|
||||
$this->setBrightness((int) $brightness);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setColorPropertiesArray(array $color): self
|
||||
{
|
||||
return $this->setColorProperties(
|
||||
$color['value'] ?? '',
|
||||
$color['alpha'] ?? null,
|
||||
$color['type'] ?? null,
|
||||
$color['brightness'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
public function isUsable(): bool
|
||||
{
|
||||
return $this->type !== '' && $this->value !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Color Property.
|
||||
*
|
||||
* @param string $propertyName
|
||||
*
|
||||
* @return null|int|string
|
||||
*/
|
||||
public function getColorProperty($propertyName)
|
||||
{
|
||||
$retVal = null;
|
||||
if ($propertyName === 'value') {
|
||||
$retVal = $this->value;
|
||||
} elseif ($propertyName === 'type') {
|
||||
$retVal = $this->type;
|
||||
} elseif ($propertyName === 'alpha') {
|
||||
$retVal = $this->alpha;
|
||||
} elseif ($propertyName === 'brightness') {
|
||||
$retVal = $this->brightness;
|
||||
}
|
||||
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
public static function alphaToXml(int $alpha): string
|
||||
{
|
||||
return (string) (100 - $alpha) . '000';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int|string $alpha
|
||||
*/
|
||||
public static function alphaFromXml($alpha): int
|
||||
{
|
||||
return 100 - ((int) $alpha / 1000);
|
||||
}
|
||||
}
|
@@ -75,26 +75,26 @@ class DataSeries
|
||||
/**
|
||||
* Order of plots in Series.
|
||||
*
|
||||
* @var array of integer
|
||||
* @var int[]
|
||||
*/
|
||||
private $plotOrder = [];
|
||||
|
||||
/**
|
||||
* Plot Label.
|
||||
*
|
||||
* @var array of DataSeriesValues
|
||||
* @var DataSeriesValues[]
|
||||
*/
|
||||
private $plotLabel = [];
|
||||
|
||||
/**
|
||||
* Plot Category.
|
||||
*
|
||||
* @var array of DataSeriesValues
|
||||
* @var DataSeriesValues[]
|
||||
*/
|
||||
private $plotCategory = [];
|
||||
|
||||
/**
|
||||
* Smooth Line.
|
||||
* Smooth Line. Must be specified for both DataSeries and DataSeriesValues.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
@@ -103,10 +103,17 @@ class DataSeries
|
||||
/**
|
||||
* Plot Values.
|
||||
*
|
||||
* @var array of DataSeriesValues
|
||||
* @var DataSeriesValues[]
|
||||
*/
|
||||
private $plotValues = [];
|
||||
|
||||
/**
|
||||
* Plot Bubble Sizes.
|
||||
*
|
||||
* @var DataSeriesValues[]
|
||||
*/
|
||||
private $plotBubbleSizes = [];
|
||||
|
||||
/**
|
||||
* Create a new DataSeries.
|
||||
*
|
||||
@@ -127,12 +134,12 @@ class DataSeries
|
||||
$this->plotOrder = $plotOrder;
|
||||
$keys = array_keys($plotValues);
|
||||
$this->plotValues = $plotValues;
|
||||
if ((count($plotLabel) == 0) || ($plotLabel[$keys[0]] === null)) {
|
||||
if (!isset($plotLabel[$keys[0]])) {
|
||||
$plotLabel[$keys[0]] = new DataSeriesValues();
|
||||
}
|
||||
$this->plotLabel = $plotLabel;
|
||||
|
||||
if ((count($plotCategory) == 0) || ($plotCategory[$keys[0]] === null)) {
|
||||
if (!isset($plotCategory[$keys[0]])) {
|
||||
$plotCategory[$keys[0]] = new DataSeriesValues();
|
||||
}
|
||||
$this->plotCategory = $plotCategory;
|
||||
@@ -231,7 +238,7 @@ class DataSeries
|
||||
/**
|
||||
* Get Plot Labels.
|
||||
*
|
||||
* @return array of DataSeriesValues
|
||||
* @return DataSeriesValues[]
|
||||
*/
|
||||
public function getPlotLabels()
|
||||
{
|
||||
@@ -243,15 +250,13 @@ class DataSeries
|
||||
*
|
||||
* @param mixed $index
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return DataSeriesValues|false
|
||||
*/
|
||||
public function getPlotLabelByIndex($index)
|
||||
{
|
||||
$keys = array_keys($this->plotLabel);
|
||||
if (in_array($index, $keys)) {
|
||||
return $this->plotLabel[$index];
|
||||
} elseif (isset($keys[$index])) {
|
||||
return $this->plotLabel[$keys[$index]];
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -260,7 +265,7 @@ class DataSeries
|
||||
/**
|
||||
* Get Plot Categories.
|
||||
*
|
||||
* @return array of DataSeriesValues
|
||||
* @return DataSeriesValues[]
|
||||
*/
|
||||
public function getPlotCategories()
|
||||
{
|
||||
@@ -272,7 +277,7 @@ class DataSeries
|
||||
*
|
||||
* @param mixed $index
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return DataSeriesValues|false
|
||||
*/
|
||||
public function getPlotCategoryByIndex($index)
|
||||
{
|
||||
@@ -313,7 +318,7 @@ class DataSeries
|
||||
/**
|
||||
* Get Plot Values.
|
||||
*
|
||||
* @return array of DataSeriesValues
|
||||
* @return DataSeriesValues[]
|
||||
*/
|
||||
public function getPlotValues()
|
||||
{
|
||||
@@ -325,20 +330,40 @@ class DataSeries
|
||||
*
|
||||
* @param mixed $index
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return DataSeriesValues|false
|
||||
*/
|
||||
public function getPlotValuesByIndex($index)
|
||||
{
|
||||
$keys = array_keys($this->plotValues);
|
||||
if (in_array($index, $keys)) {
|
||||
return $this->plotValues[$index];
|
||||
} elseif (isset($keys[$index])) {
|
||||
return $this->plotValues[$keys[$index]];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Plot Bubble Sizes.
|
||||
*
|
||||
* @return DataSeriesValues[]
|
||||
*/
|
||||
public function getPlotBubbleSizes(): array
|
||||
{
|
||||
return $this->plotBubbleSizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Plot Bubble Sizes.
|
||||
*
|
||||
* @param DataSeriesValues[] $plotBubbleSizes
|
||||
*/
|
||||
public function setPlotBubbleSizes(array $plotBubbleSizes): self
|
||||
{
|
||||
$this->plotBubbleSizes = $plotBubbleSizes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Number of Plot Series.
|
||||
*
|
||||
|
@@ -7,12 +7,12 @@ use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class DataSeriesValues
|
||||
class DataSeriesValues extends Properties
|
||||
{
|
||||
const DATASERIES_TYPE_STRING = 'String';
|
||||
const DATASERIES_TYPE_NUMBER = 'Number';
|
||||
|
||||
private static $dataTypeValues = [
|
||||
private const DATA_TYPE_VALUES = [
|
||||
self::DATASERIES_TYPE_STRING,
|
||||
self::DATASERIES_TYPE_NUMBER,
|
||||
];
|
||||
@@ -27,7 +27,7 @@ class DataSeriesValues
|
||||
/**
|
||||
* Series Data Source.
|
||||
*
|
||||
* @var string
|
||||
* @var ?string
|
||||
*/
|
||||
private $dataSource;
|
||||
|
||||
@@ -45,6 +45,19 @@ class DataSeriesValues
|
||||
*/
|
||||
private $pointMarker;
|
||||
|
||||
/** @var ChartColor */
|
||||
private $markerFillColor;
|
||||
|
||||
/** @var ChartColor */
|
||||
private $markerBorderColor;
|
||||
|
||||
/**
|
||||
* Series Point Size.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $pointSize = 3;
|
||||
|
||||
/**
|
||||
* Point Count (The number of datapoints in the dataseries).
|
||||
*
|
||||
@@ -55,23 +68,28 @@ class DataSeriesValues
|
||||
/**
|
||||
* Data Values.
|
||||
*
|
||||
* @var array of mixed
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $dataValues = [];
|
||||
|
||||
/**
|
||||
* Fill color (can be array with colors if dataseries have custom colors).
|
||||
*
|
||||
* @var string|string[]
|
||||
* @var null|ChartColor|ChartColor[]
|
||||
*/
|
||||
private $fillColor;
|
||||
|
||||
/**
|
||||
* Line Width.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $lineWidth = 12700;
|
||||
/** @var bool */
|
||||
private $scatterLines = true;
|
||||
|
||||
/** @var bool */
|
||||
private $bubble3D = false;
|
||||
|
||||
/** @var ?Layout */
|
||||
private $labelLayout;
|
||||
|
||||
/** @var TrendLine[] */
|
||||
private $trendLines = [];
|
||||
|
||||
/**
|
||||
* Create a new DataSeriesValues object.
|
||||
@@ -82,17 +100,26 @@ class DataSeriesValues
|
||||
* @param int $pointCount
|
||||
* @param mixed $dataValues
|
||||
* @param null|mixed $marker
|
||||
* @param null|string|string[] $fillColor
|
||||
* @param null|ChartColor|ChartColor[]|string|string[] $fillColor
|
||||
* @param string $pointSize
|
||||
*/
|
||||
public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null)
|
||||
public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null, $pointSize = '3')
|
||||
{
|
||||
parent::__construct();
|
||||
$this->markerFillColor = new ChartColor();
|
||||
$this->markerBorderColor = new ChartColor();
|
||||
$this->setDataType($dataType);
|
||||
$this->dataSource = $dataSource;
|
||||
$this->formatCode = $formatCode;
|
||||
$this->pointCount = $pointCount;
|
||||
$this->dataValues = $dataValues;
|
||||
$this->pointMarker = $marker;
|
||||
$this->fillColor = $fillColor;
|
||||
if ($fillColor !== null) {
|
||||
$this->setFillColor($fillColor);
|
||||
}
|
||||
if (is_numeric($pointSize)) {
|
||||
$this->pointSize = (int) $pointSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +146,7 @@ class DataSeriesValues
|
||||
*/
|
||||
public function setDataType($dataType)
|
||||
{
|
||||
if (!in_array($dataType, self::$dataTypeValues)) {
|
||||
if (!in_array($dataType, self::DATA_TYPE_VALUES)) {
|
||||
throw new Exception('Invalid datatype for chart data series values');
|
||||
}
|
||||
$this->dataType = $dataType;
|
||||
@@ -130,7 +157,7 @@ class DataSeriesValues
|
||||
/**
|
||||
* Get Series Data Source (formula).
|
||||
*
|
||||
* @return string
|
||||
* @return ?string
|
||||
*/
|
||||
public function getDataSource()
|
||||
{
|
||||
@@ -140,7 +167,7 @@ class DataSeriesValues
|
||||
/**
|
||||
* Set Series Data Source (formula).
|
||||
*
|
||||
* @param string $dataSource
|
||||
* @param ?string $dataSource
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -175,6 +202,36 @@ class DataSeriesValues
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMarkerFillColor(): ChartColor
|
||||
{
|
||||
return $this->markerFillColor;
|
||||
}
|
||||
|
||||
public function getMarkerBorderColor(): ChartColor
|
||||
{
|
||||
return $this->markerBorderColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Point Size.
|
||||
*/
|
||||
public function getPointSize(): int
|
||||
{
|
||||
return $this->pointSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Point Size.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPointSize(int $size = 3)
|
||||
{
|
||||
$this->pointSize = $size;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Series Format Code.
|
||||
*
|
||||
@@ -209,6 +266,51 @@ class DataSeriesValues
|
||||
return $this->pointCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fill color object.
|
||||
*
|
||||
* @return null|ChartColor|ChartColor[]
|
||||
*/
|
||||
public function getFillColorObject()
|
||||
{
|
||||
return $this->fillColor;
|
||||
}
|
||||
|
||||
private function stringToChartColor(string $fillString): ChartColor
|
||||
{
|
||||
$value = $type = '';
|
||||
if (substr($fillString, 0, 1) === '*') {
|
||||
$type = 'schemeClr';
|
||||
$value = substr($fillString, 1);
|
||||
} elseif (substr($fillString, 0, 1) === '/') {
|
||||
$type = 'prstClr';
|
||||
$value = substr($fillString, 1);
|
||||
} elseif ($fillString !== '') {
|
||||
$type = 'srgbClr';
|
||||
$value = $fillString;
|
||||
$this->validateColor($value);
|
||||
}
|
||||
|
||||
return new ChartColor($value, null, $type);
|
||||
}
|
||||
|
||||
private function chartColorToString(ChartColor $chartColor): string
|
||||
{
|
||||
$type = (string) $chartColor->getColorProperty('type');
|
||||
$value = (string) $chartColor->getColorProperty('value');
|
||||
if ($type === '' || $value === '') {
|
||||
return '';
|
||||
}
|
||||
if ($type === 'schemeClr') {
|
||||
return "*$value";
|
||||
}
|
||||
if ($type === 'prstClr') {
|
||||
return "/$value";
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fill color.
|
||||
*
|
||||
@@ -216,26 +318,44 @@ class DataSeriesValues
|
||||
*/
|
||||
public function getFillColor()
|
||||
{
|
||||
return $this->fillColor;
|
||||
if ($this->fillColor === null) {
|
||||
return '';
|
||||
}
|
||||
if (is_array($this->fillColor)) {
|
||||
$array = [];
|
||||
foreach ($this->fillColor as $chartColor) {
|
||||
$array[] = $this->chartColorToString($chartColor);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
return $this->chartColorToString($this->fillColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fill color for series.
|
||||
*
|
||||
* @param string|string[] $color HEX color or array with HEX colors
|
||||
* @param ChartColor|ChartColor[]|string|string[] $color HEX color or array with HEX colors
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
*/
|
||||
public function setFillColor($color)
|
||||
{
|
||||
if (is_array($color)) {
|
||||
foreach ($color as $colorValue) {
|
||||
$this->validateColor($colorValue);
|
||||
$this->fillColor = [];
|
||||
foreach ($color as $fillString) {
|
||||
if ($fillString instanceof ChartColor) {
|
||||
$this->fillColor[] = $fillString;
|
||||
} else {
|
||||
$this->fillColor[] = $this->stringToChartColor($fillString);
|
||||
}
|
||||
}
|
||||
} elseif ($color instanceof ChartColor) {
|
||||
$this->fillColor = $color;
|
||||
} else {
|
||||
$this->validateColor($color);
|
||||
$this->fillColor = $this->stringToChartColor($color);
|
||||
}
|
||||
$this->fillColor = $color;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -259,24 +379,23 @@ class DataSeriesValues
|
||||
/**
|
||||
* Get line width for series.
|
||||
*
|
||||
* @return int
|
||||
* @return null|float|int
|
||||
*/
|
||||
public function getLineWidth()
|
||||
{
|
||||
return $this->lineWidth;
|
||||
return $this->lineStyleProperties['width'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set line width for the series.
|
||||
*
|
||||
* @param int $width
|
||||
* @param null|float|int $width
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLineWidth($width)
|
||||
{
|
||||
$minWidth = 12700;
|
||||
$this->lineWidth = max($minWidth, $width);
|
||||
$this->lineStyleProperties['width'] = $width;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -288,7 +407,7 @@ class DataSeriesValues
|
||||
*/
|
||||
public function isMultiLevelSeries()
|
||||
{
|
||||
if (count($this->dataValues) > 0) {
|
||||
if (!empty($this->dataValues)) {
|
||||
return is_array(array_values($this->dataValues)[0]);
|
||||
}
|
||||
|
||||
@@ -313,7 +432,7 @@ class DataSeriesValues
|
||||
/**
|
||||
* Get Series Data Values.
|
||||
*
|
||||
* @return array of mixed
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getDataValues()
|
||||
{
|
||||
@@ -352,7 +471,7 @@ class DataSeriesValues
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function refresh(Worksheet $worksheet, $flatten = true): void
|
||||
public function refresh(Worksheet $worksheet, bool $flatten = true): void
|
||||
{
|
||||
if ($this->dataSource !== null) {
|
||||
$calcEngine = Calculation::getInstance($worksheet->getParent());
|
||||
@@ -377,7 +496,7 @@ class DataSeriesValues
|
||||
if (($dimensions[0] == 1) || ($dimensions[1] == 1)) {
|
||||
$this->dataValues = Functions::flattenArray($newDataValues);
|
||||
} else {
|
||||
$newArray = array_values(array_shift($newDataValues));
|
||||
$newArray = array_values(array_shift(/** @scrutinizer ignore-type */ $newDataValues));
|
||||
foreach ($newArray as $i => $newDataSet) {
|
||||
$newArray[$i] = [$newDataSet];
|
||||
}
|
||||
@@ -394,4 +513,83 @@ class DataSeriesValues
|
||||
$this->pointCount = count($this->dataValues);
|
||||
}
|
||||
}
|
||||
|
||||
public function getScatterLines(): bool
|
||||
{
|
||||
return $this->scatterLines;
|
||||
}
|
||||
|
||||
public function setScatterLines(bool $scatterLines): self
|
||||
{
|
||||
$this->scatterLines = $scatterLines;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBubble3D(): bool
|
||||
{
|
||||
return $this->bubble3D;
|
||||
}
|
||||
|
||||
public function setBubble3D(bool $bubble3D): self
|
||||
{
|
||||
$this->bubble3D = $bubble3D;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Smooth Line. Must be specified for both DataSeries and DataSeriesValues.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $smoothLine;
|
||||
|
||||
/**
|
||||
* Get Smooth Line.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSmoothLine()
|
||||
{
|
||||
return $this->smoothLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Smooth Line.
|
||||
*
|
||||
* @param bool $smoothLine
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSmoothLine($smoothLine)
|
||||
{
|
||||
$this->smoothLine = $smoothLine;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabelLayout(): ?Layout
|
||||
{
|
||||
return $this->labelLayout;
|
||||
}
|
||||
|
||||
public function setLabelLayout(?Layout $labelLayout): self
|
||||
{
|
||||
$this->labelLayout = $labelLayout;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTrendLines(array $trendLines): self
|
||||
{
|
||||
$this->trendLines = $trendLines;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTrendLines(): array
|
||||
{
|
||||
return $this->trendLines;
|
||||
}
|
||||
}
|
||||
|
@@ -10,445 +10,4 @@ namespace PhpOffice\PhpSpreadsheet\Chart;
|
||||
*/
|
||||
class GridLines extends Properties
|
||||
{
|
||||
/**
|
||||
* Properties of Class:
|
||||
* Object State (State for Minor Tick Mark) @var bool
|
||||
* Line Properties @var array of mixed
|
||||
* Shadow Properties @var array of mixed
|
||||
* Glow Properties @var array of mixed
|
||||
* Soft Properties @var array of mixed.
|
||||
*/
|
||||
private $objectState = false;
|
||||
|
||||
private $lineProperties = [
|
||||
'color' => [
|
||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
||||
'value' => null,
|
||||
'alpha' => 0,
|
||||
],
|
||||
'style' => [
|
||||
'width' => '9525',
|
||||
'compound' => self::LINE_STYLE_COMPOUND_SIMPLE,
|
||||
'dash' => self::LINE_STYLE_DASH_SOLID,
|
||||
'cap' => self::LINE_STYLE_CAP_FLAT,
|
||||
'join' => self::LINE_STYLE_JOIN_BEVEL,
|
||||
'arrow' => [
|
||||
'head' => [
|
||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
||||
'size' => self::LINE_STYLE_ARROW_SIZE_5,
|
||||
],
|
||||
'end' => [
|
||||
'type' => self::LINE_STYLE_ARROW_TYPE_NOARROW,
|
||||
'size' => self::LINE_STYLE_ARROW_SIZE_8,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
private $shadowProperties = [
|
||||
'presets' => self::SHADOW_PRESETS_NOSHADOW,
|
||||
'effect' => null,
|
||||
'color' => [
|
||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
||||
'value' => 'black',
|
||||
'alpha' => 85,
|
||||
],
|
||||
'size' => [
|
||||
'sx' => null,
|
||||
'sy' => null,
|
||||
'kx' => null,
|
||||
],
|
||||
'blur' => null,
|
||||
'direction' => null,
|
||||
'distance' => null,
|
||||
'algn' => null,
|
||||
'rotWithShape' => null,
|
||||
];
|
||||
|
||||
private $glowProperties = [
|
||||
'size' => null,
|
||||
'color' => [
|
||||
'type' => self::EXCEL_COLOR_TYPE_STANDARD,
|
||||
'value' => 'black',
|
||||
'alpha' => 40,
|
||||
],
|
||||
];
|
||||
|
||||
private $softEdges = [
|
||||
'size' => null,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get Object State.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getObjectState()
|
||||
{
|
||||
return $this->objectState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change Object State to True.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function activateObject()
|
||||
{
|
||||
$this->objectState = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Line Color Properties.
|
||||
*
|
||||
* @param string $value
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*/
|
||||
public function setLineColorProperties($value, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_STANDARD): void
|
||||
{
|
||||
$this->activateObject()
|
||||
->lineProperties['color'] = $this->setColorProperties(
|
||||
$value,
|
||||
$alpha,
|
||||
$type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Line Color Properties.
|
||||
*
|
||||
* @param float $line_width
|
||||
* @param string $compound_type
|
||||
* @param string $dash_type
|
||||
* @param string $cap_type
|
||||
* @param string $join_type
|
||||
* @param string $head_arrow_type
|
||||
* @param string $head_arrow_size
|
||||
* @param string $end_arrow_type
|
||||
* @param string $end_arrow_size
|
||||
*/
|
||||
public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null): void
|
||||
{
|
||||
$this->activateObject();
|
||||
($line_width !== null)
|
||||
? $this->lineProperties['style']['width'] = $this->getExcelPointsWidth((float) $line_width)
|
||||
: null;
|
||||
($compound_type !== null)
|
||||
? $this->lineProperties['style']['compound'] = (string) $compound_type
|
||||
: null;
|
||||
($dash_type !== null)
|
||||
? $this->lineProperties['style']['dash'] = (string) $dash_type
|
||||
: null;
|
||||
($cap_type !== null)
|
||||
? $this->lineProperties['style']['cap'] = (string) $cap_type
|
||||
: null;
|
||||
($join_type !== null)
|
||||
? $this->lineProperties['style']['join'] = (string) $join_type
|
||||
: null;
|
||||
($head_arrow_type !== null)
|
||||
? $this->lineProperties['style']['arrow']['head']['type'] = (string) $head_arrow_type
|
||||
: null;
|
||||
($head_arrow_size !== null)
|
||||
? $this->lineProperties['style']['arrow']['head']['size'] = (string) $head_arrow_size
|
||||
: null;
|
||||
($end_arrow_type !== null)
|
||||
? $this->lineProperties['style']['arrow']['end']['type'] = (string) $end_arrow_type
|
||||
: null;
|
||||
($end_arrow_size !== null)
|
||||
? $this->lineProperties['style']['arrow']['end']['size'] = (string) $end_arrow_size
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Line Color Property.
|
||||
*
|
||||
* @param string $parameter
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLineColorProperty($parameter)
|
||||
{
|
||||
return $this->lineProperties['color'][$parameter];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Line Style Property.
|
||||
*
|
||||
* @param array|string $elements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLineStyleProperty($elements)
|
||||
{
|
||||
return $this->getArrayElementsValue($this->lineProperties['style'], $elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Glow Properties.
|
||||
*
|
||||
* @param float $size
|
||||
* @param string $color_value
|
||||
* @param int $color_alpha
|
||||
* @param string $color_type
|
||||
*/
|
||||
public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null): void
|
||||
{
|
||||
$this
|
||||
->activateObject()
|
||||
->setGlowSize($size)
|
||||
->setGlowColor($color_value, $color_alpha, $color_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Glow Color Property.
|
||||
*
|
||||
* @param string $property
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGlowColor($property)
|
||||
{
|
||||
return $this->glowProperties['color'][$property];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Glow Size.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGlowSize()
|
||||
{
|
||||
return $this->glowProperties['size'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Glow Size.
|
||||
*
|
||||
* @param float $size
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowSize($size)
|
||||
{
|
||||
$this->glowProperties['size'] = $this->getExcelPointsWidth((float) $size);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Glow Color.
|
||||
*
|
||||
* @param string $color
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowColor($color, $alpha, $type)
|
||||
{
|
||||
if ($color !== null) {
|
||||
$this->glowProperties['color']['value'] = (string) $color;
|
||||
}
|
||||
if ($alpha !== null) {
|
||||
$this->glowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha);
|
||||
}
|
||||
if ($type !== null) {
|
||||
$this->glowProperties['color']['type'] = (string) $type;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Line Style Arrow Parameters.
|
||||
*
|
||||
* @param string $arrow_selector
|
||||
* @param string $property_selector
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLineStyleArrowParameters($arrow_selector, $property_selector)
|
||||
{
|
||||
return $this->getLineStyleArrowSize($this->lineProperties['style']['arrow'][$arrow_selector]['size'], $property_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Properties.
|
||||
*
|
||||
* @param int $sh_presets
|
||||
* @param string $sh_color_value
|
||||
* @param string $sh_color_type
|
||||
* @param int $sh_color_alpha
|
||||
* @param string $sh_blur
|
||||
* @param int $sh_angle
|
||||
* @param float $sh_distance
|
||||
*/
|
||||
public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null): void
|
||||
{
|
||||
$this->activateObject()
|
||||
->setShadowPresetsProperties((int) $sh_presets)
|
||||
->setShadowColor(
|
||||
$sh_color_value === null ? $this->shadowProperties['color']['value'] : $sh_color_value,
|
||||
$sh_color_alpha === null ? (int) $this->shadowProperties['color']['alpha'] : $this->getTrueAlpha($sh_color_alpha),
|
||||
$sh_color_type === null ? $this->shadowProperties['color']['type'] : $sh_color_type
|
||||
)
|
||||
->setShadowBlur($sh_blur)
|
||||
->setShadowAngle($sh_angle)
|
||||
->setShadowDistance($sh_distance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Presets Properties.
|
||||
*
|
||||
* @param int $shadow_presets
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowPresetsProperties($shadow_presets)
|
||||
{
|
||||
$this->shadowProperties['presets'] = $shadow_presets;
|
||||
$this->setShadowProperiesMapValues($this->getShadowPresetsMap($shadow_presets));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Properties Values.
|
||||
*
|
||||
* @param mixed &$reference
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowProperiesMapValues(array $properties_map, &$reference = null)
|
||||
{
|
||||
$base_reference = $reference;
|
||||
foreach ($properties_map as $property_key => $property_val) {
|
||||
if (is_array($property_val)) {
|
||||
if ($reference === null) {
|
||||
$reference = &$this->shadowProperties[$property_key];
|
||||
} else {
|
||||
$reference = &$reference[$property_key];
|
||||
}
|
||||
$this->setShadowProperiesMapValues($property_val, $reference);
|
||||
} else {
|
||||
if ($base_reference === null) {
|
||||
$this->shadowProperties[$property_key] = $property_val;
|
||||
} else {
|
||||
$reference[$property_key] = $property_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Color.
|
||||
*
|
||||
* @param string $color
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowColor($color, $alpha, $type)
|
||||
{
|
||||
if ($color !== null) {
|
||||
$this->shadowProperties['color']['value'] = (string) $color;
|
||||
}
|
||||
if ($alpha !== null) {
|
||||
$this->shadowProperties['color']['alpha'] = $this->getTrueAlpha((int) $alpha);
|
||||
}
|
||||
if ($type !== null) {
|
||||
$this->shadowProperties['color']['type'] = (string) $type;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Blur.
|
||||
*
|
||||
* @param float $blur
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowBlur($blur)
|
||||
{
|
||||
if ($blur !== null) {
|
||||
$this->shadowProperties['blur'] = (string) $this->getExcelPointsWidth($blur);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Angle.
|
||||
*
|
||||
* @param int $angle
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowAngle($angle)
|
||||
{
|
||||
if ($angle !== null) {
|
||||
$this->shadowProperties['direction'] = (string) $this->getExcelPointsAngle($angle);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow Distance.
|
||||
*
|
||||
* @param float $distance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowDistance($distance)
|
||||
{
|
||||
if ($distance !== null) {
|
||||
$this->shadowProperties['distance'] = (string) $this->getExcelPointsWidth($distance);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Shadow Property.
|
||||
*
|
||||
* @param string|string[] $elements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getShadowProperty($elements)
|
||||
{
|
||||
return $this->getArrayElementsValue($this->shadowProperties, $elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Soft Edges Size.
|
||||
*
|
||||
* @param float $size
|
||||
*/
|
||||
public function setSoftEdgesSize($size): void
|
||||
{
|
||||
if ($size !== null) {
|
||||
$this->activateObject();
|
||||
$this->softEdges['size'] = (string) $this->getExcelPointsWidth($size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Soft Edges Size.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSoftEdgesSize()
|
||||
{
|
||||
return $this->softEdges['size'];
|
||||
}
|
||||
}
|
||||
|
@@ -7,57 +7,70 @@ class Layout
|
||||
/**
|
||||
* layoutTarget.
|
||||
*
|
||||
* @var string
|
||||
* @var ?string
|
||||
*/
|
||||
private $layoutTarget;
|
||||
|
||||
/**
|
||||
* X Mode.
|
||||
*
|
||||
* @var string
|
||||
* @var ?string
|
||||
*/
|
||||
private $xMode;
|
||||
|
||||
/**
|
||||
* Y Mode.
|
||||
*
|
||||
* @var string
|
||||
* @var ?string
|
||||
*/
|
||||
private $yMode;
|
||||
|
||||
/**
|
||||
* X-Position.
|
||||
*
|
||||
* @var float
|
||||
* @var ?float
|
||||
*/
|
||||
private $xPos;
|
||||
|
||||
/**
|
||||
* Y-Position.
|
||||
*
|
||||
* @var float
|
||||
* @var ?float
|
||||
*/
|
||||
private $yPos;
|
||||
|
||||
/**
|
||||
* width.
|
||||
*
|
||||
* @var float
|
||||
* @var ?float
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* height.
|
||||
*
|
||||
* @var float
|
||||
* @var ?float
|
||||
*/
|
||||
private $height;
|
||||
|
||||
/**
|
||||
* Position - t=top.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $dLblPos = '';
|
||||
|
||||
/** @var string */
|
||||
private $numFmtCode = '';
|
||||
|
||||
/** @var bool */
|
||||
private $numFmtLinked = false;
|
||||
|
||||
/**
|
||||
* show legend key
|
||||
* Specifies that legend keys should be shown in data labels.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $showLegendKey;
|
||||
|
||||
@@ -65,7 +78,7 @@ class Layout
|
||||
* show value
|
||||
* Specifies that the value should be shown in a data label.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $showVal;
|
||||
|
||||
@@ -73,7 +86,7 @@ class Layout
|
||||
* show category name
|
||||
* Specifies that the category name should be shown in the data label.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $showCatName;
|
||||
|
||||
@@ -81,7 +94,7 @@ class Layout
|
||||
* show data series name
|
||||
* Specifies that the series name should be shown in the data label.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $showSerName;
|
||||
|
||||
@@ -89,14 +102,14 @@ class Layout
|
||||
* show percentage
|
||||
* Specifies that the percentage should be shown in the data label.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $showPercent;
|
||||
|
||||
/**
|
||||
* show bubble size.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $showBubbleSize;
|
||||
|
||||
@@ -104,10 +117,19 @@ class Layout
|
||||
* show leader lines
|
||||
* Specifies that leader lines should be shown for the data label.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $showLeaderLines;
|
||||
|
||||
/** @var ?ChartColor */
|
||||
private $labelFillColor;
|
||||
|
||||
/** @var ?ChartColor */
|
||||
private $labelBorderColor;
|
||||
|
||||
/** @var ?ChartColor */
|
||||
private $labelFontColor;
|
||||
|
||||
/**
|
||||
* Create a new Layout.
|
||||
*/
|
||||
@@ -134,12 +156,43 @@ class Layout
|
||||
if (isset($layout['h'])) {
|
||||
$this->height = (float) $layout['h'];
|
||||
}
|
||||
if (isset($layout['dLblPos'])) {
|
||||
$this->dLblPos = (string) $layout['dLblPos'];
|
||||
}
|
||||
if (isset($layout['numFmtCode'])) {
|
||||
$this->numFmtCode = (string) $layout['numFmtCode'];
|
||||
}
|
||||
$this->initBoolean($layout, 'showLegendKey');
|
||||
$this->initBoolean($layout, 'showVal');
|
||||
$this->initBoolean($layout, 'showCatName');
|
||||
$this->initBoolean($layout, 'showSerName');
|
||||
$this->initBoolean($layout, 'showPercent');
|
||||
$this->initBoolean($layout, 'showBubbleSize');
|
||||
$this->initBoolean($layout, 'showLeaderLines');
|
||||
$this->initBoolean($layout, 'numFmtLinked');
|
||||
$this->initColor($layout, 'labelFillColor');
|
||||
$this->initColor($layout, 'labelBorderColor');
|
||||
$this->initColor($layout, 'labelFontColor');
|
||||
}
|
||||
|
||||
private function initBoolean(array $layout, string $name): void
|
||||
{
|
||||
if (isset($layout[$name])) {
|
||||
$this->$name = (bool) $layout[$name];
|
||||
}
|
||||
}
|
||||
|
||||
private function initColor(array $layout, string $name): void
|
||||
{
|
||||
if (isset($layout[$name]) && $layout[$name] instanceof ChartColor) {
|
||||
$this->$name = $layout[$name];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Layout Target.
|
||||
*
|
||||
* @return string
|
||||
* @return ?string
|
||||
*/
|
||||
public function getLayoutTarget()
|
||||
{
|
||||
@@ -149,13 +202,13 @@ class Layout
|
||||
/**
|
||||
* Set Layout Target.
|
||||
*
|
||||
* @param string $value
|
||||
* @param ?string $target
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLayoutTarget($value)
|
||||
public function setLayoutTarget($target)
|
||||
{
|
||||
$this->layoutTarget = $value;
|
||||
$this->layoutTarget = $target;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -163,7 +216,7 @@ class Layout
|
||||
/**
|
||||
* Get X-Mode.
|
||||
*
|
||||
* @return string
|
||||
* @return ?string
|
||||
*/
|
||||
public function getXMode()
|
||||
{
|
||||
@@ -173,13 +226,13 @@ class Layout
|
||||
/**
|
||||
* Set X-Mode.
|
||||
*
|
||||
* @param string $value
|
||||
* @param ?string $mode
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setXMode($value)
|
||||
public function setXMode($mode)
|
||||
{
|
||||
$this->xMode = (string) $value;
|
||||
$this->xMode = (string) $mode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -187,7 +240,7 @@ class Layout
|
||||
/**
|
||||
* Get Y-Mode.
|
||||
*
|
||||
* @return string
|
||||
* @return ?string
|
||||
*/
|
||||
public function getYMode()
|
||||
{
|
||||
@@ -197,13 +250,13 @@ class Layout
|
||||
/**
|
||||
* Set Y-Mode.
|
||||
*
|
||||
* @param string $value
|
||||
* @param ?string $mode
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setYMode($value)
|
||||
public function setYMode($mode)
|
||||
{
|
||||
$this->yMode = (string) $value;
|
||||
$this->yMode = (string) $mode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -211,7 +264,7 @@ class Layout
|
||||
/**
|
||||
* Get X-Position.
|
||||
*
|
||||
* @return number
|
||||
* @return null|float|int
|
||||
*/
|
||||
public function getXPosition()
|
||||
{
|
||||
@@ -221,13 +274,13 @@ class Layout
|
||||
/**
|
||||
* Set X-Position.
|
||||
*
|
||||
* @param float $value
|
||||
* @param ?float $position
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setXPosition($value)
|
||||
public function setXPosition($position)
|
||||
{
|
||||
$this->xPos = (float) $value;
|
||||
$this->xPos = (float) $position;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -235,7 +288,7 @@ class Layout
|
||||
/**
|
||||
* Get Y-Position.
|
||||
*
|
||||
* @return number
|
||||
* @return null|float
|
||||
*/
|
||||
public function getYPosition()
|
||||
{
|
||||
@@ -245,13 +298,13 @@ class Layout
|
||||
/**
|
||||
* Set Y-Position.
|
||||
*
|
||||
* @param float $value
|
||||
* @param ?float $position
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setYPosition($value)
|
||||
public function setYPosition($position)
|
||||
{
|
||||
$this->yPos = (float) $value;
|
||||
$this->yPos = (float) $position;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -259,7 +312,7 @@ class Layout
|
||||
/**
|
||||
* Get Width.
|
||||
*
|
||||
* @return number
|
||||
* @return ?float
|
||||
*/
|
||||
public function getWidth()
|
||||
{
|
||||
@@ -269,13 +322,13 @@ class Layout
|
||||
/**
|
||||
* Set Width.
|
||||
*
|
||||
* @param float $value
|
||||
* @param ?float $width
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($value)
|
||||
public function setWidth($width)
|
||||
{
|
||||
$this->width = $value;
|
||||
$this->width = $width;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -283,7 +336,7 @@ class Layout
|
||||
/**
|
||||
* Get Height.
|
||||
*
|
||||
* @return number
|
||||
* @return null|float
|
||||
*/
|
||||
public function getHeight()
|
||||
{
|
||||
@@ -293,23 +346,18 @@ class Layout
|
||||
/**
|
||||
* Set Height.
|
||||
*
|
||||
* @param float $value
|
||||
* @param ?float $height
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeight($value)
|
||||
public function setHeight($height)
|
||||
{
|
||||
$this->height = $value;
|
||||
$this->height = $height;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show legend key.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowLegendKey()
|
||||
public function getShowLegendKey(): ?bool
|
||||
{
|
||||
return $this->showLegendKey;
|
||||
}
|
||||
@@ -317,24 +365,15 @@ class Layout
|
||||
/**
|
||||
* Set show legend key
|
||||
* Specifies that legend keys should be shown in data labels.
|
||||
*
|
||||
* @param bool $value Show legend key
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowLegendKey($value)
|
||||
public function setShowLegendKey(?bool $showLegendKey): self
|
||||
{
|
||||
$this->showLegendKey = $value;
|
||||
$this->showLegendKey = $showLegendKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowVal()
|
||||
public function getShowVal(): ?bool
|
||||
{
|
||||
return $this->showVal;
|
||||
}
|
||||
@@ -342,24 +381,15 @@ class Layout
|
||||
/**
|
||||
* Set show val
|
||||
* Specifies that the value should be shown in data labels.
|
||||
*
|
||||
* @param bool $value Show val
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowVal($value)
|
||||
public function setShowVal(?bool $showDataLabelValues): self
|
||||
{
|
||||
$this->showVal = $value;
|
||||
$this->showVal = $showDataLabelValues;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show category name.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowCatName()
|
||||
public function getShowCatName(): ?bool
|
||||
{
|
||||
return $this->showCatName;
|
||||
}
|
||||
@@ -367,114 +397,146 @@ class Layout
|
||||
/**
|
||||
* Set show cat name
|
||||
* Specifies that the category name should be shown in data labels.
|
||||
*
|
||||
* @param bool $value Show cat name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowCatName($value)
|
||||
public function setShowCatName(?bool $showCategoryName): self
|
||||
{
|
||||
$this->showCatName = $value;
|
||||
$this->showCatName = $showCategoryName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show data series name.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowSerName()
|
||||
public function getShowSerName(): ?bool
|
||||
{
|
||||
return $this->showSerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show ser name
|
||||
* Set show data series name.
|
||||
* Specifies that the series name should be shown in data labels.
|
||||
*
|
||||
* @param bool $value Show series name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowSerName($value)
|
||||
public function setShowSerName(?bool $showSeriesName): self
|
||||
{
|
||||
$this->showSerName = $value;
|
||||
$this->showSerName = $showSeriesName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show percentage.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowPercent()
|
||||
public function getShowPercent(): ?bool
|
||||
{
|
||||
return $this->showPercent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show percentage
|
||||
* Set show percentage.
|
||||
* Specifies that the percentage should be shown in data labels.
|
||||
*
|
||||
* @param bool $value Show percentage
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowPercent($value)
|
||||
public function setShowPercent(?bool $showPercentage): self
|
||||
{
|
||||
$this->showPercent = $value;
|
||||
$this->showPercent = $showPercentage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show bubble size.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowBubbleSize()
|
||||
public function getShowBubbleSize(): ?bool
|
||||
{
|
||||
return $this->showBubbleSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show bubble size
|
||||
* Set show bubble size.
|
||||
* Specifies that the bubble size should be shown in data labels.
|
||||
*
|
||||
* @param bool $value Show bubble size
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowBubbleSize($value)
|
||||
public function setShowBubbleSize(?bool $showBubbleSize): self
|
||||
{
|
||||
$this->showBubbleSize = $value;
|
||||
$this->showBubbleSize = $showBubbleSize;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show leader lines.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowLeaderLines()
|
||||
public function getShowLeaderLines(): ?bool
|
||||
{
|
||||
return $this->showLeaderLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show leader lines
|
||||
* Set show leader lines.
|
||||
* Specifies that leader lines should be shown in data labels.
|
||||
*
|
||||
* @param bool $value Show leader lines
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowLeaderLines($value)
|
||||
public function setShowLeaderLines(?bool $showLeaderLines): self
|
||||
{
|
||||
$this->showLeaderLines = $value;
|
||||
$this->showLeaderLines = $showLeaderLines;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabelFillColor(): ?ChartColor
|
||||
{
|
||||
return $this->labelFillColor;
|
||||
}
|
||||
|
||||
public function setLabelFillColor(?ChartColor $chartColor): self
|
||||
{
|
||||
$this->labelFillColor = $chartColor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabelBorderColor(): ?ChartColor
|
||||
{
|
||||
return $this->labelBorderColor;
|
||||
}
|
||||
|
||||
public function setLabelBorderColor(?ChartColor $chartColor): self
|
||||
{
|
||||
$this->labelBorderColor = $chartColor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabelFontColor(): ?ChartColor
|
||||
{
|
||||
return $this->labelFontColor;
|
||||
}
|
||||
|
||||
public function setLabelFontColor(?ChartColor $chartColor): self
|
||||
{
|
||||
$this->labelFontColor = $chartColor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDLblPos(): string
|
||||
{
|
||||
return $this->dLblPos;
|
||||
}
|
||||
|
||||
public function setDLblPos(string $dLblPos): self
|
||||
{
|
||||
$this->dLblPos = $dLblPos;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNumFmtCode(): string
|
||||
{
|
||||
return $this->numFmtCode;
|
||||
}
|
||||
|
||||
public function setNumFmtCode(string $numFmtCode): self
|
||||
{
|
||||
$this->numFmtCode = $numFmtCode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNumFmtLinked(): bool
|
||||
{
|
||||
return $this->numFmtLinked;
|
||||
}
|
||||
|
||||
public function setNumFmtLinked(bool $numFmtLinked): self
|
||||
{
|
||||
$this->numFmtLinked = $numFmtLinked;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ class Legend
|
||||
const POSITION_TOP = 't';
|
||||
const POSITION_TOPRIGHT = 'tr';
|
||||
|
||||
private static $positionXLref = [
|
||||
const POSITION_XLREF = [
|
||||
self::XL_LEGEND_POSITION_BOTTOM => self::POSITION_BOTTOM,
|
||||
self::XL_LEGEND_POSITION_CORNER => self::POSITION_TOPRIGHT,
|
||||
self::XL_LEGEND_POSITION_CUSTOM => '??',
|
||||
@@ -44,7 +44,7 @@ class Legend
|
||||
/**
|
||||
* Legend Layout.
|
||||
*
|
||||
* @var Layout
|
||||
* @var ?Layout
|
||||
*/
|
||||
private $layout;
|
||||
|
||||
@@ -80,7 +80,7 @@ class Legend
|
||||
*/
|
||||
public function setPosition($position)
|
||||
{
|
||||
if (!in_array($position, self::$positionXLref)) {
|
||||
if (!in_array($position, self::POSITION_XLREF)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -92,11 +92,12 @@ class Legend
|
||||
/**
|
||||
* Get legend position as an Excel internal numeric value.
|
||||
*
|
||||
* @return int
|
||||
* @return false|int
|
||||
*/
|
||||
public function getPositionXL()
|
||||
{
|
||||
return array_search($this->position, self::$positionXLref);
|
||||
// Scrutinizer thinks the following could return string. It is wrong.
|
||||
return array_search($this->position, self::POSITION_XLREF);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,11 +109,11 @@ class Legend
|
||||
*/
|
||||
public function setPositionXL($positionXL)
|
||||
{
|
||||
if (!isset(self::$positionXLref[$positionXL])) {
|
||||
if (!isset(self::POSITION_XLREF[$positionXL])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->position = self::$positionXLref[$positionXL];
|
||||
$this->position = self::POSITION_XLREF[$positionXL];
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -131,24 +132,16 @@ class Legend
|
||||
* Set allow overlay of other elements?
|
||||
*
|
||||
* @param bool $overlay
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setOverlay($overlay)
|
||||
public function setOverlay($overlay): void
|
||||
{
|
||||
if (!is_bool($overlay)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->overlay = $overlay;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Layout.
|
||||
*
|
||||
* @return Layout
|
||||
* @return ?Layout
|
||||
*/
|
||||
public function getLayout()
|
||||
{
|
||||
|
@@ -6,10 +6,34 @@ use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class PlotArea
|
||||
{
|
||||
/**
|
||||
* No fill in plot area (show Excel gridlines through chart).
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $noFill = false;
|
||||
|
||||
/**
|
||||
* PlotArea Gradient Stop list.
|
||||
* Each entry is a 2-element array.
|
||||
* First is position in %.
|
||||
* Second is ChartColor.
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
private $gradientFillStops = [];
|
||||
|
||||
/**
|
||||
* PlotArea Gradient Angle.
|
||||
*
|
||||
* @var ?float
|
||||
*/
|
||||
private $gradientFillAngle;
|
||||
|
||||
/**
|
||||
* PlotArea Layout.
|
||||
*
|
||||
* @var Layout
|
||||
* @var ?Layout
|
||||
*/
|
||||
private $layout;
|
||||
|
||||
@@ -31,22 +55,15 @@ class PlotArea
|
||||
$this->plotSeries = $plotSeries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Layout.
|
||||
*
|
||||
* @return Layout
|
||||
*/
|
||||
public function getLayout()
|
||||
public function getLayout(): ?Layout
|
||||
{
|
||||
return $this->layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Number of Plot Groups.
|
||||
*
|
||||
* @return array of DataSeries
|
||||
*/
|
||||
public function getPlotGroupCount()
|
||||
public function getPlotGroupCount(): int
|
||||
{
|
||||
return count($this->plotSeries);
|
||||
}
|
||||
@@ -69,7 +86,7 @@ class PlotArea
|
||||
/**
|
||||
* Get Plot Series.
|
||||
*
|
||||
* @return array of DataSeries
|
||||
* @return DataSeries[]
|
||||
*/
|
||||
public function getPlotGroup()
|
||||
{
|
||||
@@ -108,4 +125,42 @@ class PlotArea
|
||||
$plotSeries->refresh($worksheet);
|
||||
}
|
||||
}
|
||||
|
||||
public function setNoFill(bool $noFill): self
|
||||
{
|
||||
$this->noFill = $noFill;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNoFill(): bool
|
||||
{
|
||||
return $this->noFill;
|
||||
}
|
||||
|
||||
public function setGradientFillProperties(array $gradientFillStops, ?float $gradientFillAngle): self
|
||||
{
|
||||
$this->gradientFillStops = $gradientFillStops;
|
||||
$this->gradientFillAngle = $gradientFillAngle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gradientFillAngle.
|
||||
*/
|
||||
public function getGradientFillAngle(): ?float
|
||||
{
|
||||
return $this->gradientFillAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gradientFillStops.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGradientFillStops()
|
||||
{
|
||||
return $this->gradientFillStops;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,66 +2,28 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Chart\Renderer;
|
||||
|
||||
use AccBarPlot;
|
||||
use AccLinePlot;
|
||||
use BarPlot;
|
||||
use ContourPlot;
|
||||
use Graph;
|
||||
use GroupBarPlot;
|
||||
use LinePlot;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
use PieGraph;
|
||||
use PiePlot;
|
||||
use PiePlot3D;
|
||||
use PiePlotC;
|
||||
use RadarGraph;
|
||||
use RadarPlot;
|
||||
use ScatterPlot;
|
||||
use Spline;
|
||||
use StockPlot;
|
||||
|
||||
class JpGraph implements IRenderer
|
||||
/**
|
||||
* Jpgraph is not oficially maintained in Composer, so the version there
|
||||
* could be out of date. For that reason, all unit test requiring Jpgraph
|
||||
* are skipped. So, do not measure code coverage for this class till that
|
||||
* is fixed.
|
||||
*
|
||||
* This implementation uses abandoned package
|
||||
* https://packagist.org/packages/jpgraph/jpgraph
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class JpGraph extends JpGraphRendererBase
|
||||
{
|
||||
private static $width = 640;
|
||||
|
||||
private static $height = 480;
|
||||
|
||||
private static $colourSet = [
|
||||
'mediumpurple1', 'palegreen3', 'gold1', 'cadetblue1',
|
||||
'darkmagenta', 'coral', 'dodgerblue3', 'eggplant',
|
||||
'mediumblue', 'magenta', 'sandybrown', 'cyan',
|
||||
'firebrick1', 'forestgreen', 'deeppink4', 'darkolivegreen',
|
||||
'goldenrod2',
|
||||
];
|
||||
|
||||
private static $markSet;
|
||||
|
||||
private $chart;
|
||||
|
||||
private $graph;
|
||||
|
||||
private static $plotColour = 0;
|
||||
|
||||
private static $plotMark = 0;
|
||||
|
||||
/**
|
||||
* Create a new jpgraph.
|
||||
*/
|
||||
public function __construct(Chart $chart)
|
||||
{
|
||||
self::init();
|
||||
$this->graph = null;
|
||||
$this->chart = $chart;
|
||||
}
|
||||
|
||||
private static function init(): void
|
||||
protected static function init(): void
|
||||
{
|
||||
static $loaded = false;
|
||||
if ($loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
// JpGraph is no longer included with distribution, but user may install it.
|
||||
// So Scrutinizer's complaint that it can't find it is reasonable, but unfixable.
|
||||
\JpGraph\JpGraph::load();
|
||||
\JpGraph\JpGraph::module('bar');
|
||||
\JpGraph\JpGraph::module('contour');
|
||||
@@ -73,798 +35,6 @@ class JpGraph implements IRenderer
|
||||
\JpGraph\JpGraph::module('scatter');
|
||||
\JpGraph\JpGraph::module('stock');
|
||||
|
||||
self::$markSet = [
|
||||
'diamond' => MARK_DIAMOND,
|
||||
'square' => MARK_SQUARE,
|
||||
'triangle' => MARK_UTRIANGLE,
|
||||
'x' => MARK_X,
|
||||
'star' => MARK_STAR,
|
||||
'dot' => MARK_FILLEDCIRCLE,
|
||||
'dash' => MARK_DTRIANGLE,
|
||||
'circle' => MARK_CIRCLE,
|
||||
'plus' => MARK_CROSS,
|
||||
];
|
||||
|
||||
$loaded = true;
|
||||
}
|
||||
|
||||
private function formatPointMarker($seriesPlot, $markerID)
|
||||
{
|
||||
$plotMarkKeys = array_keys(self::$markSet);
|
||||
if ($markerID === null) {
|
||||
// Use default plot marker (next marker in the series)
|
||||
self::$plotMark %= count(self::$markSet);
|
||||
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
|
||||
} elseif ($markerID !== 'none') {
|
||||
// Use specified plot marker (if it exists)
|
||||
if (isset(self::$markSet[$markerID])) {
|
||||
$seriesPlot->mark->SetType(self::$markSet[$markerID]);
|
||||
} else {
|
||||
// If the specified plot marker doesn't exist, use default plot marker (next marker in the series)
|
||||
self::$plotMark %= count(self::$markSet);
|
||||
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
|
||||
}
|
||||
} else {
|
||||
// Hide plot marker
|
||||
$seriesPlot->mark->Hide();
|
||||
}
|
||||
$seriesPlot->mark->SetColor(self::$colourSet[self::$plotColour]);
|
||||
$seriesPlot->mark->SetFillColor(self::$colourSet[self::$plotColour]);
|
||||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
|
||||
|
||||
return $seriesPlot;
|
||||
}
|
||||
|
||||
private function formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '')
|
||||
{
|
||||
$datasetLabelFormatCode = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode();
|
||||
if ($datasetLabelFormatCode !== null) {
|
||||
// Retrieve any label formatting code
|
||||
$datasetLabelFormatCode = stripslashes($datasetLabelFormatCode);
|
||||
}
|
||||
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($datasetLabels as $i => $datasetLabel) {
|
||||
if (is_array($datasetLabel)) {
|
||||
if ($rotation == 'bar') {
|
||||
$datasetLabels[$i] = implode(' ', $datasetLabel);
|
||||
} else {
|
||||
$datasetLabel = array_reverse($datasetLabel);
|
||||
$datasetLabels[$i] = implode("\n", $datasetLabel);
|
||||
}
|
||||
} else {
|
||||
// Format labels according to any formatting code
|
||||
if ($datasetLabelFormatCode !== null) {
|
||||
$datasetLabels[$i] = NumberFormat::toFormattedString($datasetLabel, $datasetLabelFormatCode);
|
||||
}
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
return $datasetLabels;
|
||||
}
|
||||
|
||||
private function percentageSumCalculation($groupID, $seriesCount)
|
||||
{
|
||||
$sumValues = [];
|
||||
// Adjust our values to a percentage value across all series in the group
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
if ($i == 0) {
|
||||
$sumValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
} else {
|
||||
$nextValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
foreach ($nextValues as $k => $value) {
|
||||
if (isset($sumValues[$k])) {
|
||||
$sumValues[$k] += $value;
|
||||
} else {
|
||||
$sumValues[$k] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sumValues;
|
||||
}
|
||||
|
||||
private function percentageAdjustValues($dataValues, $sumValues)
|
||||
{
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
$dataValues[$k] = $dataValue / $sumValues[$k] * 100;
|
||||
}
|
||||
|
||||
return $dataValues;
|
||||
}
|
||||
|
||||
private function getCaption($captionElement)
|
||||
{
|
||||
// Read any caption
|
||||
$caption = ($captionElement !== null) ? $captionElement->getCaption() : null;
|
||||
// Test if we have a title caption to display
|
||||
if ($caption !== null) {
|
||||
// If we do, it could be a plain string or an array
|
||||
if (is_array($caption)) {
|
||||
// Implode an array to a plain string
|
||||
$caption = implode('', $caption);
|
||||
}
|
||||
}
|
||||
|
||||
return $caption;
|
||||
}
|
||||
|
||||
private function renderTitle(): void
|
||||
{
|
||||
$title = $this->getCaption($this->chart->getTitle());
|
||||
if ($title !== null) {
|
||||
$this->graph->title->Set($title);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderLegend(): void
|
||||
{
|
||||
$legend = $this->chart->getLegend();
|
||||
if ($legend !== null) {
|
||||
$legendPosition = $legend->getPosition();
|
||||
switch ($legendPosition) {
|
||||
case 'r':
|
||||
$this->graph->legend->SetPos(0.01, 0.5, 'right', 'center'); // right
|
||||
$this->graph->legend->SetColumns(1);
|
||||
|
||||
break;
|
||||
case 'l':
|
||||
$this->graph->legend->SetPos(0.01, 0.5, 'left', 'center'); // left
|
||||
$this->graph->legend->SetColumns(1);
|
||||
|
||||
break;
|
||||
case 't':
|
||||
$this->graph->legend->SetPos(0.5, 0.01, 'center', 'top'); // top
|
||||
|
||||
break;
|
||||
case 'b':
|
||||
$this->graph->legend->SetPos(0.5, 0.99, 'center', 'bottom'); // bottom
|
||||
|
||||
break;
|
||||
default:
|
||||
$this->graph->legend->SetPos(0.01, 0.01, 'right', 'top'); // top-right
|
||||
$this->graph->legend->SetColumns(1);
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$this->graph->legend->Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private function renderCartesianPlotArea($type = 'textlin'): void
|
||||
{
|
||||
$this->graph = new Graph(self::$width, self::$height);
|
||||
$this->graph->SetScale($type);
|
||||
|
||||
$this->renderTitle();
|
||||
|
||||
// Rotate for bar rather than column chart
|
||||
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection();
|
||||
$reverse = $rotation == 'bar';
|
||||
|
||||
$xAxisLabel = $this->chart->getXAxisLabel();
|
||||
if ($xAxisLabel !== null) {
|
||||
$title = $this->getCaption($xAxisLabel);
|
||||
if ($title !== null) {
|
||||
$this->graph->xaxis->SetTitle($title, 'center');
|
||||
$this->graph->xaxis->title->SetMargin(35);
|
||||
if ($reverse) {
|
||||
$this->graph->xaxis->title->SetAngle(90);
|
||||
$this->graph->xaxis->title->SetMargin(90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$yAxisLabel = $this->chart->getYAxisLabel();
|
||||
if ($yAxisLabel !== null) {
|
||||
$title = $this->getCaption($yAxisLabel);
|
||||
if ($title !== null) {
|
||||
$this->graph->yaxis->SetTitle($title, 'center');
|
||||
if ($reverse) {
|
||||
$this->graph->yaxis->title->SetAngle(0);
|
||||
$this->graph->yaxis->title->SetMargin(-55);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPiePlotArea(): void
|
||||
{
|
||||
$this->graph = new PieGraph(self::$width, self::$height);
|
||||
|
||||
$this->renderTitle();
|
||||
}
|
||||
|
||||
private function renderRadarPlotArea(): void
|
||||
{
|
||||
$this->graph = new RadarGraph(self::$width, self::$height);
|
||||
$this->graph->SetScale('lin');
|
||||
|
||||
$this->renderTitle();
|
||||
}
|
||||
|
||||
private function renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d'): void
|
||||
{
|
||||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
|
||||
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
|
||||
$this->graph->xaxis->SetTickLabels($datasetLabels);
|
||||
}
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
if ($grouping == 'percentStacked') {
|
||||
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount);
|
||||
}
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
|
||||
|
||||
if ($grouping == 'percentStacked') {
|
||||
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues);
|
||||
}
|
||||
|
||||
// Fill in any missing values in the $dataValues array
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
while ($k != $testCurrentIndex) {
|
||||
$dataValues[$testCurrentIndex] = null;
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
$seriesPlot = new LinePlot($dataValues);
|
||||
if ($combination) {
|
||||
$seriesPlot->SetBarCenter();
|
||||
}
|
||||
|
||||
if ($filled) {
|
||||
$seriesPlot->SetFilled(true);
|
||||
$seriesPlot->SetColor('black');
|
||||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]);
|
||||
} else {
|
||||
// Set the appropriate plot marker
|
||||
$this->formatPointMarker($seriesPlot, $marker);
|
||||
}
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$seriesPlots[] = $seriesPlot;
|
||||
}
|
||||
|
||||
if ($grouping == 'standard') {
|
||||
$groupPlot = $seriesPlots;
|
||||
} else {
|
||||
$groupPlot = new AccLinePlot($seriesPlots);
|
||||
}
|
||||
$this->graph->Add($groupPlot);
|
||||
}
|
||||
|
||||
private function renderPlotBar($groupID, $dimensions = '2d'): void
|
||||
{
|
||||
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection();
|
||||
// Rotate for bar rather than column chart
|
||||
if (($groupID == 0) && ($rotation == 'bar')) {
|
||||
$this->graph->Set90AndMargin();
|
||||
}
|
||||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
|
||||
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation);
|
||||
// Rotate for bar rather than column chart
|
||||
if ($rotation == 'bar') {
|
||||
$datasetLabels = array_reverse($datasetLabels);
|
||||
$this->graph->yaxis->SetPos('max');
|
||||
$this->graph->yaxis->SetLabelAlign('center', 'top');
|
||||
$this->graph->yaxis->SetLabelSide(SIDE_RIGHT);
|
||||
}
|
||||
$this->graph->xaxis->SetTickLabels($datasetLabels);
|
||||
}
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
if ($grouping == 'percentStacked') {
|
||||
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount);
|
||||
}
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($j = 0; $j < $seriesCount; ++$j) {
|
||||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
|
||||
if ($grouping == 'percentStacked') {
|
||||
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues);
|
||||
}
|
||||
|
||||
// Fill in any missing values in the $dataValues array
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
while ($k != $testCurrentIndex) {
|
||||
$dataValues[$testCurrentIndex] = null;
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
// Reverse the $dataValues order for bar rather than column chart
|
||||
if ($rotation == 'bar') {
|
||||
$dataValues = array_reverse($dataValues);
|
||||
}
|
||||
$seriesPlot = new BarPlot($dataValues);
|
||||
$seriesPlot->SetColor('black');
|
||||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]);
|
||||
if ($dimensions == '3d') {
|
||||
$seriesPlot->SetShadow();
|
||||
}
|
||||
if (!$this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) {
|
||||
$dataLabel = '';
|
||||
} else {
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue();
|
||||
}
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$seriesPlots[] = $seriesPlot;
|
||||
}
|
||||
// Reverse the plot order for bar rather than column chart
|
||||
if (($rotation == 'bar') && ($grouping != 'percentStacked')) {
|
||||
$seriesPlots = array_reverse($seriesPlots);
|
||||
}
|
||||
|
||||
if ($grouping == 'clustered') {
|
||||
$groupPlot = new GroupBarPlot($seriesPlots);
|
||||
} elseif ($grouping == 'standard') {
|
||||
$groupPlot = new GroupBarPlot($seriesPlots);
|
||||
} else {
|
||||
$groupPlot = new AccBarPlot($seriesPlots);
|
||||
if ($dimensions == '3d') {
|
||||
$groupPlot->SetShadow();
|
||||
}
|
||||
}
|
||||
|
||||
$this->graph->Add($groupPlot);
|
||||
}
|
||||
|
||||
private function renderPlotScatter($groupID, $bubble): void
|
||||
{
|
||||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
|
||||
$scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
|
||||
foreach ($dataValuesY as $k => $dataValueY) {
|
||||
$dataValuesY[$k] = $k;
|
||||
}
|
||||
|
||||
$seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY);
|
||||
if ($scatterStyle == 'lineMarker') {
|
||||
$seriesPlot->SetLinkPoints();
|
||||
$seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]);
|
||||
} elseif ($scatterStyle == 'smoothMarker') {
|
||||
$spline = new Spline($dataValuesY, $dataValuesX);
|
||||
[$splineDataY, $splineDataX] = $spline->Get(count($dataValuesX) * self::$width / 20);
|
||||
$lplot = new LinePlot($splineDataX, $splineDataY);
|
||||
$lplot->SetColor(self::$colourSet[self::$plotColour]);
|
||||
|
||||
$this->graph->Add($lplot);
|
||||
}
|
||||
|
||||
if ($bubble) {
|
||||
$this->formatPointMarker($seriesPlot, 'dot');
|
||||
$seriesPlot->mark->SetColor('black');
|
||||
$seriesPlot->mark->SetSize($bubbleSize);
|
||||
} else {
|
||||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
|
||||
$this->formatPointMarker($seriesPlot, $marker);
|
||||
}
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPlotRadar($groupID): void
|
||||
{
|
||||
$radarStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
|
||||
|
||||
$dataValues = [];
|
||||
foreach ($dataValuesY as $k => $dataValueY) {
|
||||
$dataValues[$k] = implode(' ', array_reverse($dataValueY));
|
||||
}
|
||||
$tmp = array_shift($dataValues);
|
||||
$dataValues[] = $tmp;
|
||||
$tmp = array_shift($dataValuesX);
|
||||
$dataValuesX[] = $tmp;
|
||||
|
||||
$this->graph->SetTitles(array_reverse($dataValues));
|
||||
|
||||
$seriesPlot = new RadarPlot(array_reverse($dataValuesX));
|
||||
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
|
||||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
|
||||
if ($radarStyle == 'filled') {
|
||||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour]);
|
||||
}
|
||||
$this->formatPointMarker($seriesPlot, $marker);
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPlotContour($groupID): void
|
||||
{
|
||||
$contourStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
|
||||
$dataValues = [];
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
|
||||
$dataValues[$i] = $dataValuesX;
|
||||
}
|
||||
$seriesPlot = new ContourPlot($dataValues);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
|
||||
private function renderPlotStock($groupID): void
|
||||
{
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$plotOrder = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder();
|
||||
|
||||
$dataValues = [];
|
||||
// Loop through each data series in turn and build the plot arrays
|
||||
foreach ($plotOrder as $i => $v) {
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($v)->getDataValues();
|
||||
foreach ($dataValuesX as $j => $dataValueX) {
|
||||
$dataValues[$plotOrder[$i]][$j] = $dataValueX;
|
||||
}
|
||||
}
|
||||
if (empty($dataValues)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dataValuesPlot = [];
|
||||
// Flatten the plot arrays to a single dimensional array to work with jpgraph
|
||||
$jMax = count($dataValues[0]);
|
||||
for ($j = 0; $j < $jMax; ++$j) {
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesPlot[] = $dataValues[$i][$j];
|
||||
}
|
||||
}
|
||||
|
||||
// Set the x-axis labels
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
|
||||
$this->graph->xaxis->SetTickLabels($datasetLabels);
|
||||
}
|
||||
|
||||
$seriesPlot = new StockPlot($dataValuesPlot);
|
||||
$seriesPlot->SetWidth(20);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
|
||||
private function renderAreaChart($groupCount, $dimensions = '2d'): void
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotLine($i, true, false, $dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderLineChart($groupCount, $dimensions = '2d'): void
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotLine($i, false, false, $dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderBarChart($groupCount, $dimensions = '2d'): void
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotBar($i, $dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderScatterChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('linlin');
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotScatter($i, false);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderBubbleChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('linlin');
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotScatter($i, true);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false): void
|
||||
{
|
||||
$this->renderPiePlotArea();
|
||||
|
||||
$iLimit = ($multiplePlots) ? $groupCount : 1;
|
||||
for ($groupID = 0; $groupID < $iLimit; ++$groupID) {
|
||||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
|
||||
$exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
|
||||
$datasetLabels = [];
|
||||
if ($groupID == 0) {
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
|
||||
}
|
||||
}
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
// For pie charts, we only display the first series: doughnut charts generally display all series
|
||||
$jLimit = ($multiplePlots) ? $seriesCount : 1;
|
||||
// Loop through each data series in turn
|
||||
for ($j = 0; $j < $jLimit; ++$j) {
|
||||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
|
||||
|
||||
// Fill in any missing values in the $dataValues array
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
while ($k != $testCurrentIndex) {
|
||||
$dataValues[$testCurrentIndex] = null;
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
if ($dimensions == '3d') {
|
||||
$seriesPlot = new PiePlot3D($dataValues);
|
||||
} else {
|
||||
if ($doughnut) {
|
||||
$seriesPlot = new PiePlotC($dataValues);
|
||||
} else {
|
||||
$seriesPlot = new PiePlot($dataValues);
|
||||
}
|
||||
}
|
||||
|
||||
if ($multiplePlots) {
|
||||
$seriesPlot->SetSize(($jLimit - $j) / ($jLimit * 4));
|
||||
}
|
||||
|
||||
if ($doughnut) {
|
||||
$seriesPlot->SetMidColor('white');
|
||||
}
|
||||
|
||||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
|
||||
if (count($datasetLabels) > 0) {
|
||||
$seriesPlot->SetLabels(array_fill(0, count($datasetLabels), ''));
|
||||
}
|
||||
if ($dimensions != '3d') {
|
||||
$seriesPlot->SetGuideLines(false);
|
||||
}
|
||||
if ($j == 0) {
|
||||
if ($exploded) {
|
||||
$seriesPlot->ExplodeAll();
|
||||
}
|
||||
$seriesPlot->SetLegends($datasetLabels);
|
||||
}
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function renderRadarChart($groupCount): void
|
||||
{
|
||||
$this->renderRadarPlotArea();
|
||||
|
||||
for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
|
||||
$this->renderPlotRadar($groupID);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderStockChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('intint');
|
||||
|
||||
for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
|
||||
$this->renderPlotStock($groupID);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderContourChart($groupCount, $dimensions): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('intint');
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotContour($i);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderCombinationChart($groupCount, $dimensions, $outputDestination)
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$dimensions = null;
|
||||
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
|
||||
switch ($chartType) {
|
||||
case 'area3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'areaChart':
|
||||
$this->renderPlotLine($i, true, true, $dimensions);
|
||||
|
||||
break;
|
||||
case 'bar3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'barChart':
|
||||
$this->renderPlotBar($i, $dimensions);
|
||||
|
||||
break;
|
||||
case 'line3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'lineChart':
|
||||
$this->renderPlotLine($i, false, true, $dimensions);
|
||||
|
||||
break;
|
||||
case 'scatterChart':
|
||||
$this->renderPlotScatter($i, false);
|
||||
|
||||
break;
|
||||
case 'bubbleChart':
|
||||
$this->renderPlotScatter($i, true);
|
||||
|
||||
break;
|
||||
default:
|
||||
$this->graph = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->renderLegend();
|
||||
|
||||
$this->graph->Stroke($outputDestination);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function render($outputDestination)
|
||||
{
|
||||
self::$plotColour = 0;
|
||||
|
||||
$groupCount = $this->chart->getPlotArea()->getPlotGroupCount();
|
||||
|
||||
$dimensions = null;
|
||||
if ($groupCount == 1) {
|
||||
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType();
|
||||
} else {
|
||||
$chartTypes = [];
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$chartTypes[] = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
|
||||
}
|
||||
$chartTypes = array_unique($chartTypes);
|
||||
if (count($chartTypes) == 1) {
|
||||
$chartType = array_pop($chartTypes);
|
||||
} elseif (count($chartTypes) == 0) {
|
||||
echo 'Chart is not yet implemented<br />';
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return $this->renderCombinationChart($groupCount, $dimensions, $outputDestination);
|
||||
}
|
||||
}
|
||||
|
||||
switch ($chartType) {
|
||||
case 'area3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'areaChart':
|
||||
$this->renderAreaChart($groupCount, $dimensions);
|
||||
|
||||
break;
|
||||
case 'bar3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'barChart':
|
||||
$this->renderBarChart($groupCount, $dimensions);
|
||||
|
||||
break;
|
||||
case 'line3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'lineChart':
|
||||
$this->renderLineChart($groupCount, $dimensions);
|
||||
|
||||
break;
|
||||
case 'pie3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'pieChart':
|
||||
$this->renderPieChart($groupCount, $dimensions, false, false);
|
||||
|
||||
break;
|
||||
case 'doughnut3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'doughnutChart':
|
||||
$this->renderPieChart($groupCount, $dimensions, true, true);
|
||||
|
||||
break;
|
||||
case 'scatterChart':
|
||||
$this->renderScatterChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'bubbleChart':
|
||||
$this->renderBubbleChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'radarChart':
|
||||
$this->renderRadarChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'surface3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'surfaceChart':
|
||||
$this->renderContourChart($groupCount, $dimensions);
|
||||
|
||||
break;
|
||||
case 'stockChart':
|
||||
$this->renderStockChart($groupCount);
|
||||
|
||||
break;
|
||||
default:
|
||||
echo $chartType . ' is not yet implemented<br />';
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->renderLegend();
|
||||
|
||||
$this->graph->Stroke($outputDestination);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
852
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php
vendored
Normal file
852
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php
vendored
Normal file
@@ -0,0 +1,852 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Chart\Renderer;
|
||||
|
||||
use AccBarPlot;
|
||||
use AccLinePlot;
|
||||
use BarPlot;
|
||||
use ContourPlot;
|
||||
use Graph;
|
||||
use GroupBarPlot;
|
||||
use LinePlot;
|
||||
use PhpOffice\PhpSpreadsheet\Chart\Chart;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
use PieGraph;
|
||||
use PiePlot;
|
||||
use PiePlot3D;
|
||||
use PiePlotC;
|
||||
use RadarGraph;
|
||||
use RadarPlot;
|
||||
use ScatterPlot;
|
||||
use Spline;
|
||||
use StockPlot;
|
||||
|
||||
/**
|
||||
* Base class for different Jpgraph implementations as charts renderer.
|
||||
*/
|
||||
abstract class JpGraphRendererBase implements IRenderer
|
||||
{
|
||||
private static $width = 640;
|
||||
|
||||
private static $height = 480;
|
||||
|
||||
private static $colourSet = [
|
||||
'mediumpurple1', 'palegreen3', 'gold1', 'cadetblue1',
|
||||
'darkmagenta', 'coral', 'dodgerblue3', 'eggplant',
|
||||
'mediumblue', 'magenta', 'sandybrown', 'cyan',
|
||||
'firebrick1', 'forestgreen', 'deeppink4', 'darkolivegreen',
|
||||
'goldenrod2',
|
||||
];
|
||||
|
||||
private static $markSet;
|
||||
|
||||
private $chart;
|
||||
|
||||
private $graph;
|
||||
|
||||
private static $plotColour = 0;
|
||||
|
||||
private static $plotMark = 0;
|
||||
|
||||
/**
|
||||
* Create a new jpgraph.
|
||||
*/
|
||||
public function __construct(Chart $chart)
|
||||
{
|
||||
static::init();
|
||||
$this->graph = null;
|
||||
$this->chart = $chart;
|
||||
|
||||
self::$markSet = [
|
||||
'diamond' => MARK_DIAMOND,
|
||||
'square' => MARK_SQUARE,
|
||||
'triangle' => MARK_UTRIANGLE,
|
||||
'x' => MARK_X,
|
||||
'star' => MARK_STAR,
|
||||
'dot' => MARK_FILLEDCIRCLE,
|
||||
'dash' => MARK_DTRIANGLE,
|
||||
'circle' => MARK_CIRCLE,
|
||||
'plus' => MARK_CROSS,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be overriden in descendants to do real JpGraph library initialization.
|
||||
*/
|
||||
abstract protected static function init(): void;
|
||||
|
||||
private function formatPointMarker($seriesPlot, $markerID)
|
||||
{
|
||||
$plotMarkKeys = array_keys(self::$markSet);
|
||||
if ($markerID === null) {
|
||||
// Use default plot marker (next marker in the series)
|
||||
self::$plotMark %= count(self::$markSet);
|
||||
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
|
||||
} elseif ($markerID !== 'none') {
|
||||
// Use specified plot marker (if it exists)
|
||||
if (isset(self::$markSet[$markerID])) {
|
||||
$seriesPlot->mark->SetType(self::$markSet[$markerID]);
|
||||
} else {
|
||||
// If the specified plot marker doesn't exist, use default plot marker (next marker in the series)
|
||||
self::$plotMark %= count(self::$markSet);
|
||||
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
|
||||
}
|
||||
} else {
|
||||
// Hide plot marker
|
||||
$seriesPlot->mark->Hide();
|
||||
}
|
||||
$seriesPlot->mark->SetColor(self::$colourSet[self::$plotColour]);
|
||||
$seriesPlot->mark->SetFillColor(self::$colourSet[self::$plotColour]);
|
||||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
|
||||
|
||||
return $seriesPlot;
|
||||
}
|
||||
|
||||
private function formatDataSetLabels($groupID, $datasetLabels, $rotation = '')
|
||||
{
|
||||
$datasetLabelFormatCode = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode() ?? '';
|
||||
// Retrieve any label formatting code
|
||||
$datasetLabelFormatCode = stripslashes($datasetLabelFormatCode);
|
||||
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($datasetLabels as $i => $datasetLabel) {
|
||||
if (is_array($datasetLabel)) {
|
||||
if ($rotation == 'bar') {
|
||||
$datasetLabels[$i] = implode(' ', $datasetLabel);
|
||||
} else {
|
||||
$datasetLabel = array_reverse($datasetLabel);
|
||||
$datasetLabels[$i] = implode("\n", $datasetLabel);
|
||||
}
|
||||
} else {
|
||||
// Format labels according to any formatting code
|
||||
if ($datasetLabelFormatCode !== null) {
|
||||
$datasetLabels[$i] = NumberFormat::toFormattedString($datasetLabel, $datasetLabelFormatCode);
|
||||
}
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
return $datasetLabels;
|
||||
}
|
||||
|
||||
private function percentageSumCalculation($groupID, $seriesCount)
|
||||
{
|
||||
$sumValues = [];
|
||||
// Adjust our values to a percentage value across all series in the group
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
if ($i == 0) {
|
||||
$sumValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
} else {
|
||||
$nextValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
foreach ($nextValues as $k => $value) {
|
||||
if (isset($sumValues[$k])) {
|
||||
$sumValues[$k] += $value;
|
||||
} else {
|
||||
$sumValues[$k] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sumValues;
|
||||
}
|
||||
|
||||
private function percentageAdjustValues($dataValues, $sumValues)
|
||||
{
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
$dataValues[$k] = $dataValue / $sumValues[$k] * 100;
|
||||
}
|
||||
|
||||
return $dataValues;
|
||||
}
|
||||
|
||||
private function getCaption($captionElement)
|
||||
{
|
||||
// Read any caption
|
||||
$caption = ($captionElement !== null) ? $captionElement->getCaption() : null;
|
||||
// Test if we have a title caption to display
|
||||
if ($caption !== null) {
|
||||
// If we do, it could be a plain string or an array
|
||||
if (is_array($caption)) {
|
||||
// Implode an array to a plain string
|
||||
$caption = implode('', $caption);
|
||||
}
|
||||
}
|
||||
|
||||
return $caption;
|
||||
}
|
||||
|
||||
private function renderTitle(): void
|
||||
{
|
||||
$title = $this->getCaption($this->chart->getTitle());
|
||||
if ($title !== null) {
|
||||
$this->graph->title->Set($title);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderLegend(): void
|
||||
{
|
||||
$legend = $this->chart->getLegend();
|
||||
if ($legend !== null) {
|
||||
$legendPosition = $legend->getPosition();
|
||||
switch ($legendPosition) {
|
||||
case 'r':
|
||||
$this->graph->legend->SetPos(0.01, 0.5, 'right', 'center'); // right
|
||||
$this->graph->legend->SetColumns(1);
|
||||
|
||||
break;
|
||||
case 'l':
|
||||
$this->graph->legend->SetPos(0.01, 0.5, 'left', 'center'); // left
|
||||
$this->graph->legend->SetColumns(1);
|
||||
|
||||
break;
|
||||
case 't':
|
||||
$this->graph->legend->SetPos(0.5, 0.01, 'center', 'top'); // top
|
||||
|
||||
break;
|
||||
case 'b':
|
||||
$this->graph->legend->SetPos(0.5, 0.99, 'center', 'bottom'); // bottom
|
||||
|
||||
break;
|
||||
default:
|
||||
$this->graph->legend->SetPos(0.01, 0.01, 'right', 'top'); // top-right
|
||||
$this->graph->legend->SetColumns(1);
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$this->graph->legend->Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private function renderCartesianPlotArea($type = 'textlin'): void
|
||||
{
|
||||
$this->graph = new Graph(self::$width, self::$height);
|
||||
$this->graph->SetScale($type);
|
||||
|
||||
$this->renderTitle();
|
||||
|
||||
// Rotate for bar rather than column chart
|
||||
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection();
|
||||
$reverse = $rotation == 'bar';
|
||||
|
||||
$xAxisLabel = $this->chart->getXAxisLabel();
|
||||
if ($xAxisLabel !== null) {
|
||||
$title = $this->getCaption($xAxisLabel);
|
||||
if ($title !== null) {
|
||||
$this->graph->xaxis->SetTitle($title, 'center');
|
||||
$this->graph->xaxis->title->SetMargin(35);
|
||||
if ($reverse) {
|
||||
$this->graph->xaxis->title->SetAngle(90);
|
||||
$this->graph->xaxis->title->SetMargin(90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$yAxisLabel = $this->chart->getYAxisLabel();
|
||||
if ($yAxisLabel !== null) {
|
||||
$title = $this->getCaption($yAxisLabel);
|
||||
if ($title !== null) {
|
||||
$this->graph->yaxis->SetTitle($title, 'center');
|
||||
if ($reverse) {
|
||||
$this->graph->yaxis->title->SetAngle(0);
|
||||
$this->graph->yaxis->title->SetMargin(-55);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPiePlotArea(): void
|
||||
{
|
||||
$this->graph = new PieGraph(self::$width, self::$height);
|
||||
|
||||
$this->renderTitle();
|
||||
}
|
||||
|
||||
private function renderRadarPlotArea(): void
|
||||
{
|
||||
$this->graph = new RadarGraph(self::$width, self::$height);
|
||||
$this->graph->SetScale('lin');
|
||||
|
||||
$this->renderTitle();
|
||||
}
|
||||
|
||||
private function renderPlotLine($groupID, $filled = false, $combination = false): void
|
||||
{
|
||||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
|
||||
|
||||
$index = array_keys($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder())[0];
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($index)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels);
|
||||
$this->graph->xaxis->SetTickLabels($datasetLabels);
|
||||
}
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
if ($grouping == 'percentStacked') {
|
||||
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount);
|
||||
} else {
|
||||
$sumValues = [];
|
||||
}
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$index = array_keys($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder())[$i];
|
||||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($index)->getDataValues();
|
||||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($index)->getPointMarker();
|
||||
|
||||
if ($grouping == 'percentStacked') {
|
||||
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues);
|
||||
}
|
||||
|
||||
// Fill in any missing values in the $dataValues array
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
while ($k != $testCurrentIndex) {
|
||||
$dataValues[$testCurrentIndex] = null;
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
$seriesPlot = new LinePlot($dataValues);
|
||||
if ($combination) {
|
||||
$seriesPlot->SetBarCenter();
|
||||
}
|
||||
|
||||
if ($filled) {
|
||||
$seriesPlot->SetFilled(true);
|
||||
$seriesPlot->SetColor('black');
|
||||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]);
|
||||
} else {
|
||||
// Set the appropriate plot marker
|
||||
$this->formatPointMarker($seriesPlot, $marker);
|
||||
}
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($index)->getDataValue();
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$seriesPlots[] = $seriesPlot;
|
||||
}
|
||||
|
||||
if ($grouping == 'standard') {
|
||||
$groupPlot = $seriesPlots;
|
||||
} else {
|
||||
$groupPlot = new AccLinePlot($seriesPlots);
|
||||
}
|
||||
$this->graph->Add($groupPlot);
|
||||
}
|
||||
|
||||
private function renderPlotBar($groupID, $dimensions = '2d'): void
|
||||
{
|
||||
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection();
|
||||
// Rotate for bar rather than column chart
|
||||
if (($groupID == 0) && ($rotation == 'bar')) {
|
||||
$this->graph->Set90AndMargin();
|
||||
}
|
||||
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
|
||||
|
||||
$index = array_keys($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder())[0];
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($index)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $rotation);
|
||||
// Rotate for bar rather than column chart
|
||||
if ($rotation == 'bar') {
|
||||
$datasetLabels = array_reverse($datasetLabels);
|
||||
$this->graph->yaxis->SetPos('max');
|
||||
$this->graph->yaxis->SetLabelAlign('center', 'top');
|
||||
$this->graph->yaxis->SetLabelSide(SIDE_RIGHT);
|
||||
}
|
||||
$this->graph->xaxis->SetTickLabels($datasetLabels);
|
||||
}
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$seriesPlots = [];
|
||||
if ($grouping == 'percentStacked') {
|
||||
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount);
|
||||
} else {
|
||||
$sumValues = [];
|
||||
}
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($j = 0; $j < $seriesCount; ++$j) {
|
||||
$index = array_keys($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder())[$j];
|
||||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($index)->getDataValues();
|
||||
if ($grouping == 'percentStacked') {
|
||||
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues);
|
||||
}
|
||||
|
||||
// Fill in any missing values in the $dataValues array
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
while ($k != $testCurrentIndex) {
|
||||
$dataValues[$testCurrentIndex] = null;
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
// Reverse the $dataValues order for bar rather than column chart
|
||||
if ($rotation == 'bar') {
|
||||
$dataValues = array_reverse($dataValues);
|
||||
}
|
||||
$seriesPlot = new BarPlot($dataValues);
|
||||
$seriesPlot->SetColor('black');
|
||||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]);
|
||||
if ($dimensions == '3d') {
|
||||
$seriesPlot->SetShadow();
|
||||
}
|
||||
if (!$this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) {
|
||||
$dataLabel = '';
|
||||
} else {
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue();
|
||||
}
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$seriesPlots[] = $seriesPlot;
|
||||
}
|
||||
// Reverse the plot order for bar rather than column chart
|
||||
if (($rotation == 'bar') && ($grouping != 'percentStacked')) {
|
||||
$seriesPlots = array_reverse($seriesPlots);
|
||||
}
|
||||
|
||||
if ($grouping == 'clustered') {
|
||||
$groupPlot = new GroupBarPlot($seriesPlots);
|
||||
} elseif ($grouping == 'standard') {
|
||||
$groupPlot = new GroupBarPlot($seriesPlots);
|
||||
} else {
|
||||
$groupPlot = new AccBarPlot($seriesPlots);
|
||||
if ($dimensions == '3d') {
|
||||
$groupPlot->SetShadow();
|
||||
}
|
||||
}
|
||||
|
||||
$this->graph->Add($groupPlot);
|
||||
}
|
||||
|
||||
private function renderPlotScatter($groupID, $bubble): void
|
||||
{
|
||||
$scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
|
||||
foreach ($dataValuesY as $k => $dataValueY) {
|
||||
$dataValuesY[$k] = $k;
|
||||
}
|
||||
|
||||
$seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY);
|
||||
if ($scatterStyle == 'lineMarker') {
|
||||
$seriesPlot->SetLinkPoints();
|
||||
$seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]);
|
||||
} elseif ($scatterStyle == 'smoothMarker') {
|
||||
$spline = new Spline($dataValuesY, $dataValuesX);
|
||||
[$splineDataY, $splineDataX] = $spline->Get(count($dataValuesX) * self::$width / 20);
|
||||
$lplot = new LinePlot($splineDataX, $splineDataY);
|
||||
$lplot->SetColor(self::$colourSet[self::$plotColour]);
|
||||
|
||||
$this->graph->Add($lplot);
|
||||
}
|
||||
|
||||
if ($bubble) {
|
||||
$this->formatPointMarker($seriesPlot, 'dot');
|
||||
$seriesPlot->mark->SetColor('black');
|
||||
$seriesPlot->mark->SetSize($bubbleSize);
|
||||
} else {
|
||||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
|
||||
$this->formatPointMarker($seriesPlot, $marker);
|
||||
}
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPlotRadar($groupID): void
|
||||
{
|
||||
$radarStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
|
||||
|
||||
$dataValues = [];
|
||||
foreach ($dataValuesY as $k => $dataValueY) {
|
||||
$dataValues[$k] = implode(' ', array_reverse($dataValueY));
|
||||
}
|
||||
$tmp = array_shift($dataValues);
|
||||
$dataValues[] = $tmp;
|
||||
$tmp = array_shift($dataValuesX);
|
||||
$dataValuesX[] = $tmp;
|
||||
|
||||
$this->graph->SetTitles(array_reverse($dataValues));
|
||||
|
||||
$seriesPlot = new RadarPlot(array_reverse($dataValuesX));
|
||||
|
||||
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
|
||||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
|
||||
if ($radarStyle == 'filled') {
|
||||
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour]);
|
||||
}
|
||||
$this->formatPointMarker($seriesPlot, $marker);
|
||||
$seriesPlot->SetLegend($dataLabel);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPlotContour($groupID): void
|
||||
{
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
|
||||
$dataValues = [];
|
||||
// Loop through each data series in turn
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
|
||||
|
||||
$dataValues[$i] = $dataValuesX;
|
||||
}
|
||||
$seriesPlot = new ContourPlot($dataValues);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
|
||||
private function renderPlotStock($groupID): void
|
||||
{
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
$plotOrder = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder();
|
||||
|
||||
$dataValues = [];
|
||||
// Loop through each data series in turn and build the plot arrays
|
||||
foreach ($plotOrder as $i => $v) {
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($v);
|
||||
if ($dataValuesX === false) {
|
||||
continue;
|
||||
}
|
||||
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($v)->getDataValues();
|
||||
foreach ($dataValuesX as $j => $dataValueX) {
|
||||
$dataValues[$plotOrder[$i]][$j] = $dataValueX;
|
||||
}
|
||||
}
|
||||
if (empty($dataValues)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dataValuesPlot = [];
|
||||
// Flatten the plot arrays to a single dimensional array to work with jpgraph
|
||||
$jMax = count($dataValues[0]);
|
||||
for ($j = 0; $j < $jMax; ++$j) {
|
||||
for ($i = 0; $i < $seriesCount; ++$i) {
|
||||
$dataValuesPlot[] = $dataValues[$i][$j] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the x-axis labels
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels);
|
||||
$this->graph->xaxis->SetTickLabels($datasetLabels);
|
||||
}
|
||||
|
||||
$seriesPlot = new StockPlot($dataValuesPlot);
|
||||
$seriesPlot->SetWidth(20);
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
|
||||
private function renderAreaChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotLine($i, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderLineChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotLine($i, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderBarChart($groupCount, $dimensions = '2d'): void
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotBar($i, $dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderScatterChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('linlin');
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotScatter($i, false);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderBubbleChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('linlin');
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotScatter($i, true);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false): void
|
||||
{
|
||||
$this->renderPiePlotArea();
|
||||
|
||||
$iLimit = ($multiplePlots) ? $groupCount : 1;
|
||||
for ($groupID = 0; $groupID < $iLimit; ++$groupID) {
|
||||
$exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
|
||||
$datasetLabels = [];
|
||||
if ($groupID == 0) {
|
||||
$labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
|
||||
if ($labelCount > 0) {
|
||||
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
|
||||
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels);
|
||||
}
|
||||
}
|
||||
|
||||
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
|
||||
// For pie charts, we only display the first series: doughnut charts generally display all series
|
||||
$jLimit = ($multiplePlots) ? $seriesCount : 1;
|
||||
// Loop through each data series in turn
|
||||
for ($j = 0; $j < $jLimit; ++$j) {
|
||||
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
|
||||
|
||||
// Fill in any missing values in the $dataValues array
|
||||
$testCurrentIndex = 0;
|
||||
foreach ($dataValues as $k => $dataValue) {
|
||||
while ($k != $testCurrentIndex) {
|
||||
$dataValues[$testCurrentIndex] = null;
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
++$testCurrentIndex;
|
||||
}
|
||||
|
||||
if ($dimensions == '3d') {
|
||||
$seriesPlot = new PiePlot3D($dataValues);
|
||||
} else {
|
||||
if ($doughnut) {
|
||||
$seriesPlot = new PiePlotC($dataValues);
|
||||
} else {
|
||||
$seriesPlot = new PiePlot($dataValues);
|
||||
}
|
||||
}
|
||||
|
||||
if ($multiplePlots) {
|
||||
$seriesPlot->SetSize(($jLimit - $j) / ($jLimit * 4));
|
||||
}
|
||||
|
||||
if ($doughnut && method_exists($seriesPlot, 'SetMidColor')) {
|
||||
$seriesPlot->SetMidColor('white');
|
||||
}
|
||||
|
||||
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
|
||||
if (count($datasetLabels) > 0) {
|
||||
$seriesPlot->SetLabels(array_fill(0, count($datasetLabels), ''));
|
||||
}
|
||||
if ($dimensions != '3d') {
|
||||
$seriesPlot->SetGuideLines(false);
|
||||
}
|
||||
if ($j == 0) {
|
||||
if ($exploded) {
|
||||
$seriesPlot->ExplodeAll();
|
||||
}
|
||||
$seriesPlot->SetLegends($datasetLabels);
|
||||
}
|
||||
|
||||
$this->graph->Add($seriesPlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function renderRadarChart($groupCount): void
|
||||
{
|
||||
$this->renderRadarPlotArea();
|
||||
|
||||
for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
|
||||
$this->renderPlotRadar($groupID);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderStockChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('intint');
|
||||
|
||||
for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
|
||||
$this->renderPlotStock($groupID);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderContourChart($groupCount): void
|
||||
{
|
||||
$this->renderCartesianPlotArea('intint');
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$this->renderPlotContour($i);
|
||||
}
|
||||
}
|
||||
|
||||
private function renderCombinationChart($groupCount, $outputDestination)
|
||||
{
|
||||
$this->renderCartesianPlotArea();
|
||||
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$dimensions = null;
|
||||
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
|
||||
switch ($chartType) {
|
||||
case 'area3DChart':
|
||||
case 'areaChart':
|
||||
$this->renderPlotLine($i, true, true);
|
||||
|
||||
break;
|
||||
case 'bar3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'barChart':
|
||||
$this->renderPlotBar($i, $dimensions);
|
||||
|
||||
break;
|
||||
case 'line3DChart':
|
||||
case 'lineChart':
|
||||
$this->renderPlotLine($i, false, true);
|
||||
|
||||
break;
|
||||
case 'scatterChart':
|
||||
$this->renderPlotScatter($i, false);
|
||||
|
||||
break;
|
||||
case 'bubbleChart':
|
||||
$this->renderPlotScatter($i, true);
|
||||
|
||||
break;
|
||||
default:
|
||||
$this->graph = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->renderLegend();
|
||||
|
||||
$this->graph->Stroke($outputDestination);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function render($outputDestination)
|
||||
{
|
||||
self::$plotColour = 0;
|
||||
|
||||
$groupCount = $this->chart->getPlotArea()->getPlotGroupCount();
|
||||
|
||||
$dimensions = null;
|
||||
if ($groupCount == 1) {
|
||||
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType();
|
||||
} else {
|
||||
$chartTypes = [];
|
||||
for ($i = 0; $i < $groupCount; ++$i) {
|
||||
$chartTypes[] = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
|
||||
}
|
||||
$chartTypes = array_unique($chartTypes);
|
||||
if (count($chartTypes) == 1) {
|
||||
$chartType = array_pop($chartTypes);
|
||||
} elseif (count($chartTypes) == 0) {
|
||||
echo 'Chart is not yet implemented<br />';
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return $this->renderCombinationChart($groupCount, $outputDestination);
|
||||
}
|
||||
}
|
||||
|
||||
switch ($chartType) {
|
||||
case 'area3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'areaChart':
|
||||
$this->renderAreaChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'bar3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'barChart':
|
||||
$this->renderBarChart($groupCount, $dimensions);
|
||||
|
||||
break;
|
||||
case 'line3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'lineChart':
|
||||
$this->renderLineChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'pie3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'pieChart':
|
||||
$this->renderPieChart($groupCount, $dimensions, false, false);
|
||||
|
||||
break;
|
||||
case 'doughnut3DChart':
|
||||
$dimensions = '3d';
|
||||
// no break
|
||||
case 'doughnutChart':
|
||||
$this->renderPieChart($groupCount, $dimensions, true, true);
|
||||
|
||||
break;
|
||||
case 'scatterChart':
|
||||
$this->renderScatterChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'bubbleChart':
|
||||
$this->renderBubbleChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'radarChart':
|
||||
$this->renderRadarChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'surface3DChart':
|
||||
case 'surfaceChart':
|
||||
$this->renderContourChart($groupCount);
|
||||
|
||||
break;
|
||||
case 'stockChart':
|
||||
$this->renderStockChart($groupCount);
|
||||
|
||||
break;
|
||||
default:
|
||||
echo $chartType . ' is not yet implemented<br />';
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->renderLegend();
|
||||
|
||||
$this->graph->Stroke($outputDestination);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
36
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php
vendored
Normal file
36
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Chart\Renderer;
|
||||
|
||||
/**
|
||||
* Jpgraph is not oficially maintained in Composer.
|
||||
*
|
||||
* This renderer implementation uses package
|
||||
* https://packagist.org/packages/mitoteam/jpgraph
|
||||
*
|
||||
* This package is up to date for August 2022 and has PHP 8.1 support.
|
||||
*/
|
||||
class MtJpGraphRenderer extends JpGraphRendererBase
|
||||
{
|
||||
protected static function init(): void
|
||||
{
|
||||
static $loaded = false;
|
||||
if ($loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
\mitoteam\jpgraph\MtJpGraph::load([
|
||||
'bar',
|
||||
'contour',
|
||||
'line',
|
||||
'pie',
|
||||
'pie3d',
|
||||
'radar',
|
||||
'regstat',
|
||||
'scatter',
|
||||
'stock',
|
||||
]);
|
||||
|
||||
$loaded = true;
|
||||
}
|
||||
}
|
@@ -5,7 +5,10 @@ GraPHPite
|
||||
http://graphpite.sourceforge.net/
|
||||
|
||||
JpGraph
|
||||
http://www.aditus.nu/jpgraph/
|
||||
https://jpgraph.net/
|
||||
Used composer packages:
|
||||
https://packagist.org/packages/jpgraph/jpgraph (\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph)
|
||||
https://packagist.org/packages/mitoteam/jpgraph (\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer)
|
||||
|
||||
LibChart
|
||||
https://naku.dohcrew.com/libchart/pages/introduction/
|
||||
@@ -17,4 +20,4 @@ TeeChart
|
||||
https://www.steema.com/
|
||||
|
||||
PHPGraphLib
|
||||
http://www.ebrueggeman.com/phpgraphlib
|
||||
http://www.ebrueggeman.com/phpgraphlib
|
||||
|
@@ -2,28 +2,30 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Chart;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\RichText\RichText;
|
||||
|
||||
class Title
|
||||
{
|
||||
/**
|
||||
* Title Caption.
|
||||
*
|
||||
* @var string
|
||||
* @var array|RichText|string
|
||||
*/
|
||||
private $caption;
|
||||
private $caption = '';
|
||||
|
||||
/**
|
||||
* Title Layout.
|
||||
*
|
||||
* @var Layout
|
||||
* @var ?Layout
|
||||
*/
|
||||
private $layout;
|
||||
|
||||
/**
|
||||
* Create a new Title.
|
||||
*
|
||||
* @param null|mixed $caption
|
||||
* @param array|RichText|string $caption
|
||||
*/
|
||||
public function __construct($caption = null, ?Layout $layout = null)
|
||||
public function __construct($caption = '', ?Layout $layout = null)
|
||||
{
|
||||
$this->caption = $caption;
|
||||
$this->layout = $layout;
|
||||
@@ -32,17 +34,40 @@ class Title
|
||||
/**
|
||||
* Get caption.
|
||||
*
|
||||
* @return string
|
||||
* @return array|RichText|string
|
||||
*/
|
||||
public function getCaption()
|
||||
{
|
||||
return $this->caption;
|
||||
}
|
||||
|
||||
public function getCaptionText(): string
|
||||
{
|
||||
$caption = $this->caption;
|
||||
if (is_string($caption)) {
|
||||
return $caption;
|
||||
}
|
||||
if ($caption instanceof RichText) {
|
||||
return $caption->getPlainText();
|
||||
}
|
||||
$retVal = '';
|
||||
foreach ($caption as $textx) {
|
||||
/** @var RichText|string */
|
||||
$text = $textx;
|
||||
if ($text instanceof RichText) {
|
||||
$retVal .= $text->getPlainText();
|
||||
} else {
|
||||
$retVal .= $text;
|
||||
}
|
||||
}
|
||||
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set caption.
|
||||
*
|
||||
* @param string $caption
|
||||
* @param array|RichText|string $caption
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -53,12 +78,7 @@ class Title
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Layout.
|
||||
*
|
||||
* @return Layout
|
||||
*/
|
||||
public function getLayout()
|
||||
public function getLayout(): ?Layout
|
||||
{
|
||||
return $this->layout;
|
||||
}
|
||||
|
226
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/TrendLine.php
vendored
Normal file
226
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/TrendLine.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Chart;
|
||||
|
||||
class TrendLine extends Properties
|
||||
{
|
||||
const TRENDLINE_EXPONENTIAL = 'exp';
|
||||
const TRENDLINE_LINEAR = 'linear';
|
||||
const TRENDLINE_LOGARITHMIC = 'log';
|
||||
const TRENDLINE_POLYNOMIAL = 'poly'; // + 'order'
|
||||
const TRENDLINE_POWER = 'power';
|
||||
const TRENDLINE_MOVING_AVG = 'movingAvg'; // + 'period'
|
||||
const TRENDLINE_TYPES = [
|
||||
self::TRENDLINE_EXPONENTIAL,
|
||||
self::TRENDLINE_LINEAR,
|
||||
self::TRENDLINE_LOGARITHMIC,
|
||||
self::TRENDLINE_POLYNOMIAL,
|
||||
self::TRENDLINE_POWER,
|
||||
self::TRENDLINE_MOVING_AVG,
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
private $trendLineType = 'linear'; // TRENDLINE_LINEAR
|
||||
|
||||
/** @var int */
|
||||
private $order = 2;
|
||||
|
||||
/** @var int */
|
||||
private $period = 3;
|
||||
|
||||
/** @var bool */
|
||||
private $dispRSqr = false;
|
||||
|
||||
/** @var bool */
|
||||
private $dispEq = false;
|
||||
|
||||
/** @var string */
|
||||
private $name = '';
|
||||
|
||||
/** @var float */
|
||||
private $backward = 0.0;
|
||||
|
||||
/** @var float */
|
||||
private $forward = 0.0;
|
||||
|
||||
/** @var float */
|
||||
private $intercept = 0.0;
|
||||
|
||||
/**
|
||||
* Create a new TrendLine object.
|
||||
*/
|
||||
public function __construct(
|
||||
string $trendLineType = '',
|
||||
?int $order = null,
|
||||
?int $period = null,
|
||||
bool $dispRSqr = false,
|
||||
bool $dispEq = false,
|
||||
?float $backward = null,
|
||||
?float $forward = null,
|
||||
?float $intercept = null,
|
||||
?string $name = null
|
||||
) {
|
||||
parent::__construct();
|
||||
$this->setTrendLineProperties(
|
||||
$trendLineType,
|
||||
$order,
|
||||
$period,
|
||||
$dispRSqr,
|
||||
$dispEq,
|
||||
$backward,
|
||||
$forward,
|
||||
$intercept,
|
||||
$name
|
||||
);
|
||||
}
|
||||
|
||||
public function getTrendLineType(): string
|
||||
{
|
||||
return $this->trendLineType;
|
||||
}
|
||||
|
||||
public function setTrendLineType(string $trendLineType): self
|
||||
{
|
||||
$this->trendLineType = $trendLineType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrder(): int
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
public function setOrder(int $order): self
|
||||
{
|
||||
$this->order = $order;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPeriod(): int
|
||||
{
|
||||
return $this->period;
|
||||
}
|
||||
|
||||
public function setPeriod(int $period): self
|
||||
{
|
||||
$this->period = $period;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDispRSqr(): bool
|
||||
{
|
||||
return $this->dispRSqr;
|
||||
}
|
||||
|
||||
public function setDispRSqr(bool $dispRSqr): self
|
||||
{
|
||||
$this->dispRSqr = $dispRSqr;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDispEq(): bool
|
||||
{
|
||||
return $this->dispEq;
|
||||
}
|
||||
|
||||
public function setDispEq(bool $dispEq): self
|
||||
{
|
||||
$this->dispEq = $dispEq;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBackward(): float
|
||||
{
|
||||
return $this->backward;
|
||||
}
|
||||
|
||||
public function setBackward(float $backward): self
|
||||
{
|
||||
$this->backward = $backward;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getForward(): float
|
||||
{
|
||||
return $this->forward;
|
||||
}
|
||||
|
||||
public function setForward(float $forward): self
|
||||
{
|
||||
$this->forward = $forward;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIntercept(): float
|
||||
{
|
||||
return $this->intercept;
|
||||
}
|
||||
|
||||
public function setIntercept(float $intercept): self
|
||||
{
|
||||
$this->intercept = $intercept;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTrendLineProperties(
|
||||
?string $trendLineType = null,
|
||||
?int $order = 0,
|
||||
?int $period = 0,
|
||||
?bool $dispRSqr = false,
|
||||
?bool $dispEq = false,
|
||||
?float $backward = null,
|
||||
?float $forward = null,
|
||||
?float $intercept = null,
|
||||
?string $name = null
|
||||
): self {
|
||||
if (!empty($trendLineType)) {
|
||||
$this->setTrendLineType($trendLineType);
|
||||
}
|
||||
if ($order !== null) {
|
||||
$this->setOrder($order);
|
||||
}
|
||||
if ($period !== null) {
|
||||
$this->setPeriod($period);
|
||||
}
|
||||
if ($dispRSqr !== null) {
|
||||
$this->setDispRSqr($dispRSqr);
|
||||
}
|
||||
if ($dispEq !== null) {
|
||||
$this->setDispEq($dispEq);
|
||||
}
|
||||
if ($backward !== null) {
|
||||
$this->setBackward($backward);
|
||||
}
|
||||
if ($forward !== null) {
|
||||
$this->setForward($forward);
|
||||
}
|
||||
if ($intercept !== null) {
|
||||
$this->setIntercept($intercept);
|
||||
}
|
||||
if ($name !== null) {
|
||||
$this->setName($name);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user