OpenXE/classes/Widgets/Chart/Dataset.php
2021-05-21 08:49:41 +02:00

282 lines
7.3 KiB
PHP

<?php
namespace Xentral\Widgets\Chart;
use InvalidArgumentException;
use JsonSerializable;
class Dataset implements JsonSerializable
{
const LINE_STYLE_SOLID = 'solid';
const LINE_STYLE_DASHED = 'dashed';
const LINE_STYLE_DOTTED = 'dotted';
const COLOR_GREEN = 'green';
const COLOR_BLUE = 'blue';
const COLOR_ORANGE = 'orange';
const COLOR_DARKBLUE = 'darkblue';
/** @var array $validLineStyles */
protected static $validLineStyles = [
self::LINE_STYLE_SOLID,
self::LINE_STYLE_DOTTED,
self::LINE_STYLE_DASHED,
];
/** @var array $colorMap */
protected static $colorMap = [
self::COLOR_GREEN => [162, 197, 90],
self::COLOR_BLUE => [69, 185, 211],
self::COLOR_ORANGE => [246, 158, 6],
self::COLOR_DARKBLUE => [14, 131, 148],
];
/** @var array $defaultOptions Standardwerte für Dataset-Optionen */
protected static $defaultOptions = [
'pointBorderWidth' => 1,
'pointHoverBorderWidth' => 2,
'pointRadius' => 1,
'pointHoverRadius' => 5,
'pointHitRadius' => 15,
'lineTension' => 0.2,
'fill' => true,
'borderWidth' => 3,
'borderDash' => [],
'borderCapStyle' => 'butt',
'borderColor' => 'rgba(0, 0, 0, 0.1)',
'backgroundColor' => 'rgba(0, 0, 0, 0.1)',
'pointBackgroundColor' => 'rgba(0, 0, 0, 0.1)',
];
/** @var array $defaultAlphaValues Transparenz-Werte */
protected static $defaultAlphaValues = [
'borderColor' => 1.0,
'backgroundColor' => 0.1,
'pointBackgroundColor' => 1.0,
];
protected $data;
protected $label;
protected $options;
/** @var bool $isDataAccumulated Gibt an ob Daten bereits kumuliert wurden */
protected $isDataAccumulated = false;
/** @var bool $hasColorSet Gibt an ob bereits eine Farbe manuell gesetzt wurde */
protected $hasColorAssigned = false;
/**
* @param string $label
* @param array $data
* @param array $options
*/
public function __construct($label, $data, array $options = [])
{
// Ungültige Werte in leeres Array wandeln
if (!is_array($data)) {
$data = [];
}
$this->data = $data;
$this->label = $label;
$this->options = array_replace(self::$defaultOptions, $options);
$defaultColor = new Color(0, 0, 0, 0.1);
if (!is_object($this->options['borderColor'])) {
$this->options['borderColor'] = $defaultColor;
}
if (!is_object($this->options['backgroundColor'])) {
$this->options['backgroundColor'] = $defaultColor;
}
if (!is_object($this->options['pointBackgroundColor'])) {
$this->options['pointBackgroundColor'] = $defaultColor;
}
}
/**
* @return int
*/
public function getDataCount()
{
return count($this->data);
}
/**
* @return bool Wurde bereits eine Farbe gesetzt
*/
public function hasColorAssigned()
{
return $this->hasColorAssigned;
}
/**
* @return void
*/
public function accumulateData()
{
if ($this->isDataAccumulated === true) {
return;
}
$sum = 0;
foreach ($this->data as $key => $value) {
$sum += (float)$value;
$this->data[$key] = $sum;
}
$this->isDataAccumulated = true;
}
/**
* @param string $lineStyle
*
* @return void
*/
public function setLineStyle($lineStyle)
{
if (!in_array($lineStyle, self::$validLineStyles, true)) {
throw new InvalidArgumentException(sprintf(
'Line style "%s" is not valid.', $lineStyle
));
}
if ($lineStyle === self::LINE_STYLE_DOTTED) {
$this->options['borderDash'] = [1, 15];
$this->options['borderCapStyle'] = 'round';
}
if ($lineStyle === self::LINE_STYLE_DASHED) {
$this->options['borderDash'] = [15, 10];
$this->options['borderCapStyle'] = 'butt';
}
if ($lineStyle === self::LINE_STYLE_SOLID) {
$this->options['borderDash'] = [];
$this->options['borderCapStyle'] = 'butt';
}
}
/**
* @param Color $color
*
* @return void
*/
public function setColor(Color $color)
{
$borderColor = clone $color;
$backgroundColor = clone $color;
$pointBackgroundColor = clone $color;
$borderColor->setAlpha($this->getDefaultAlphaValue('borderColor'));
$backgroundColor->setAlpha($this->getDefaultAlphaValue('backgroundColor'));
$pointBackgroundColor->setAlpha($this->getDefaultAlphaValue('pointBackgroundColor'));
$this->options['borderColor'] = $borderColor;
$this->options['backgroundColor'] = $backgroundColor;
$this->options['pointBackgroundColor'] = $pointBackgroundColor;
$this->hasColorAssigned = true;
}
/**
* @param int $red
* @param int $green
* @param int $blue
*
* @return void
*/
public function setColorByRgb($red, $green, $blue)
{
$this->setColor(new Color($red, $green, $blue, 1.0));
}
/**
* @param string $hexColor
*
* @return void
*/
public function setColorByHex($hexColor)
{
$hexColor = str_replace('#', '', $hexColor);
if (strlen($hexColor) !== 6) {
throw new InvalidArgumentException('Only full length hex values are supported.');
}
$parts = str_split($hexColor, 2);
$red = hexdec($parts[0]);
$green = hexdec($parts[1]);
$blue = hexdec($parts[2]);
$this->setColorByRgb($red, $green, $blue);
}
/**
* @param string $colorName
*
* @return void
*/
public function setColorByName($colorName)
{
if (!isset(self::$colorMap[$colorName])) {
throw new InvalidArgumentException(sprintf(
'Color name "%s" is not valid.', $colorName
));
}
$rgb = self::$colorMap[$colorName];
$this->setColorByRgb(...$rgb);
}
/**
* Zufällige ID generieren; wird für Multiple Axes Config benötigt
*
* @see http://www.chartjs.org/docs/latest/axes/cartesian/#axis-id
*
* @return string
*/
public function generateYAxisId()
{
if (!isset($this->options['yAxisID'])) {
$this->options['yAxisID'] = uniqid('', false);
}
return $this->options['yAxisID'];
}
/**
* @return array
*/
public function jsonSerialize()
{
return $this->toArray();
}
/**
* @return array
*/
public function toArray()
{
$result = $this->options;
$result['data'] = $this->data;
if (!empty($this->label)) {
$result['label'] = $this->label;
}
return $result;
}
/**
* @param string $colorType
*
* @return float
*/
protected function getDefaultAlphaValue($colorType)
{
if (!isset(static::$defaultAlphaValues[$colorType])) {
return 1.0;
}
// Wichtig: static nicht self!
// Sonst hat Überschreiben von $defaultAlphaValues in abgeleiteten Klassen keine Auswirkung.
return static::$defaultAlphaValues[$colorType];
}
}