Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Chart;
   4  
   5  /**
   6   * Created by PhpStorm.
   7   * User: nhw2h8s
   8   * Date: 7/2/14
   9   * Time: 5:45 PM.
  10   */
  11  abstract class Properties
  12  {
  13      /** @deprecated 1.24 use constant from ChartColor instead */
  14      const EXCEL_COLOR_TYPE_STANDARD = ChartColor::EXCEL_COLOR_TYPE_STANDARD;
  15      /** @deprecated 1.24 use constant from ChartColor instead */
  16      const EXCEL_COLOR_TYPE_SCHEME = ChartColor::EXCEL_COLOR_TYPE_SCHEME;
  17      /** @deprecated 1.24 use constant from ChartColor instead */
  18      const EXCEL_COLOR_TYPE_ARGB = ChartColor::EXCEL_COLOR_TYPE_ARGB;
  19  
  20      const
  21          AXIS_LABELS_LOW = 'low';
  22      const AXIS_LABELS_HIGH = 'high';
  23      const AXIS_LABELS_NEXT_TO = 'nextTo';
  24      const AXIS_LABELS_NONE = 'none';
  25  
  26      const
  27          TICK_MARK_NONE = 'none';
  28      const TICK_MARK_INSIDE = 'in';
  29      const TICK_MARK_OUTSIDE = 'out';
  30      const TICK_MARK_CROSS = 'cross';
  31  
  32      const
  33          HORIZONTAL_CROSSES_AUTOZERO = 'autoZero';
  34      const HORIZONTAL_CROSSES_MAXIMUM = 'max';
  35  
  36      const
  37          FORMAT_CODE_GENERAL = 'General';
  38      const FORMAT_CODE_NUMBER = '#,##0.00';
  39      const FORMAT_CODE_CURRENCY = '$#,##0.00';
  40      const FORMAT_CODE_ACCOUNTING = '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)';
  41      const FORMAT_CODE_DATE = 'm/d/yyyy';
  42      const FORMAT_CODE_DATE_ISO8601 = 'yyyy-mm-dd';
  43      const FORMAT_CODE_TIME = '[$-F400]h:mm:ss AM/PM';
  44      const FORMAT_CODE_PERCENTAGE = '0.00%';
  45      const FORMAT_CODE_FRACTION = '# ?/?';
  46      const FORMAT_CODE_SCIENTIFIC = '0.00E+00';
  47      const FORMAT_CODE_TEXT = '@';
  48      const FORMAT_CODE_SPECIAL = '00000';
  49  
  50      const
  51          ORIENTATION_NORMAL = 'minMax';
  52      const ORIENTATION_REVERSED = 'maxMin';
  53  
  54      const
  55          LINE_STYLE_COMPOUND_SIMPLE = 'sng';
  56      const LINE_STYLE_COMPOUND_DOUBLE = 'dbl';
  57      const LINE_STYLE_COMPOUND_THICKTHIN = 'thickThin';
  58      const LINE_STYLE_COMPOUND_THINTHICK = 'thinThick';
  59      const LINE_STYLE_COMPOUND_TRIPLE = 'tri';
  60      const LINE_STYLE_DASH_SOLID = 'solid';
  61      const LINE_STYLE_DASH_ROUND_DOT = 'sysDot';
  62      const LINE_STYLE_DASH_SQUARE_DOT = 'sysDash';
  63      /** @deprecated 1.24 use LINE_STYLE_DASH_SQUARE_DOT instead */
  64      const LINE_STYLE_DASH_SQUERE_DOT = 'sysDash';
  65      const LINE_STYPE_DASH_DASH = 'dash';
  66      const LINE_STYLE_DASH_DASH_DOT = 'dashDot';
  67      const LINE_STYLE_DASH_LONG_DASH = 'lgDash';
  68      const LINE_STYLE_DASH_LONG_DASH_DOT = 'lgDashDot';
  69      const LINE_STYLE_DASH_LONG_DASH_DOT_DOT = 'lgDashDotDot';
  70      const LINE_STYLE_CAP_SQUARE = 'sq';
  71      const LINE_STYLE_CAP_ROUND = 'rnd';
  72      const LINE_STYLE_CAP_FLAT = 'flat';
  73      const LINE_STYLE_JOIN_ROUND = 'round';
  74      const LINE_STYLE_JOIN_MITER = 'miter';
  75      const LINE_STYLE_JOIN_BEVEL = 'bevel';
  76      const LINE_STYLE_ARROW_TYPE_NOARROW = null;
  77      const LINE_STYLE_ARROW_TYPE_ARROW = 'triangle';
  78      const LINE_STYLE_ARROW_TYPE_OPEN = 'arrow';
  79      const LINE_STYLE_ARROW_TYPE_STEALTH = 'stealth';
  80      const LINE_STYLE_ARROW_TYPE_DIAMOND = 'diamond';
  81      const LINE_STYLE_ARROW_TYPE_OVAL = 'oval';
  82      const LINE_STYLE_ARROW_SIZE_1 = 1;
  83      const LINE_STYLE_ARROW_SIZE_2 = 2;
  84      const LINE_STYLE_ARROW_SIZE_3 = 3;
  85      const LINE_STYLE_ARROW_SIZE_4 = 4;
  86      const LINE_STYLE_ARROW_SIZE_5 = 5;
  87      const LINE_STYLE_ARROW_SIZE_6 = 6;
  88      const LINE_STYLE_ARROW_SIZE_7 = 7;
  89      const LINE_STYLE_ARROW_SIZE_8 = 8;
  90      const LINE_STYLE_ARROW_SIZE_9 = 9;
  91  
  92      const
  93          SHADOW_PRESETS_NOSHADOW = null;
  94      const SHADOW_PRESETS_OUTER_BOTTTOM_RIGHT = 1;
  95      const SHADOW_PRESETS_OUTER_BOTTOM = 2;
  96      const SHADOW_PRESETS_OUTER_BOTTOM_LEFT = 3;
  97      const SHADOW_PRESETS_OUTER_RIGHT = 4;
  98      const SHADOW_PRESETS_OUTER_CENTER = 5;
  99      const SHADOW_PRESETS_OUTER_LEFT = 6;
 100      const SHADOW_PRESETS_OUTER_TOP_RIGHT = 7;
 101      const SHADOW_PRESETS_OUTER_TOP = 8;
 102      const SHADOW_PRESETS_OUTER_TOP_LEFT = 9;
 103      const SHADOW_PRESETS_INNER_BOTTTOM_RIGHT = 10;
 104      const SHADOW_PRESETS_INNER_BOTTOM = 11;
 105      const SHADOW_PRESETS_INNER_BOTTOM_LEFT = 12;
 106      const SHADOW_PRESETS_INNER_RIGHT = 13;
 107      const SHADOW_PRESETS_INNER_CENTER = 14;
 108      const SHADOW_PRESETS_INNER_LEFT = 15;
 109      const SHADOW_PRESETS_INNER_TOP_RIGHT = 16;
 110      const SHADOW_PRESETS_INNER_TOP = 17;
 111      const SHADOW_PRESETS_INNER_TOP_LEFT = 18;
 112      const SHADOW_PRESETS_PERSPECTIVE_BELOW = 19;
 113      const SHADOW_PRESETS_PERSPECTIVE_UPPER_RIGHT = 20;
 114      const SHADOW_PRESETS_PERSPECTIVE_UPPER_LEFT = 21;
 115      const SHADOW_PRESETS_PERSPECTIVE_LOWER_RIGHT = 22;
 116      const SHADOW_PRESETS_PERSPECTIVE_LOWER_LEFT = 23;
 117  
 118      const POINTS_WIDTH_MULTIPLIER = 12700;
 119      const ANGLE_MULTIPLIER = 60000; // direction and size-kx size-ky
 120      const PERCENTAGE_MULTIPLIER = 100000; // size sx and sy
 121  
 122      /** @var bool */
 123      protected $objectState = false; // used only for minor gridlines
 124  
 125      /** @var ?float */
 126      protected $glowSize;
 127  
 128      /** @var ChartColor */
 129      protected $glowColor;
 130  
 131      /** @var array */
 132      protected $softEdges = [
 133          'size' => null,
 134      ];
 135  
 136      /** @var array */
 137      protected $shadowProperties = self::PRESETS_OPTIONS[0];
 138  
 139      /** @var ChartColor */
 140      protected $shadowColor;
 141  
 142      public function __construct()
 143      {
 144          $this->lineColor = new ChartColor();
 145          $this->glowColor = new ChartColor();
 146          $this->shadowColor = new ChartColor();
 147          $this->shadowColor->setType(ChartColor::EXCEL_COLOR_TYPE_STANDARD);
 148          $this->shadowColor->setValue('black');
 149          $this->shadowColor->setAlpha(40);
 150      }
 151  
 152      /**
 153       * Get Object State.
 154       *
 155       * @return bool
 156       */
 157      public function getObjectState()
 158      {
 159          return $this->objectState;
 160      }
 161  
 162      /**
 163       * Change Object State to True.
 164       *
 165       * @return $this
 166       */
 167      public function activateObject()
 168      {
 169          $this->objectState = true;
 170  
 171          return $this;
 172      }
 173  
 174      public static function pointsToXml(float $width): string
 175      {
 176          return (string) (int) ($width * self::POINTS_WIDTH_MULTIPLIER);
 177      }
 178  
 179      public static function xmlToPoints(string $width): float
 180      {
 181          return ((float) $width) / self::POINTS_WIDTH_MULTIPLIER;
 182      }
 183  
 184      public static function angleToXml(float $angle): string
 185      {
 186          return (string) (int) ($angle * self::ANGLE_MULTIPLIER);
 187      }
 188  
 189      public static function xmlToAngle(string $angle): float
 190      {
 191          return ((float) $angle) / self::ANGLE_MULTIPLIER;
 192      }
 193  
 194      public static function tenthOfPercentToXml(float $value): string
 195      {
 196          return (string) (int) ($value * self::PERCENTAGE_MULTIPLIER);
 197      }
 198  
 199      public static function xmlToTenthOfPercent(string $value): float
 200      {
 201          return ((float) $value) / self::PERCENTAGE_MULTIPLIER;
 202      }
 203  
 204      /**
 205       * @param null|float|int|string $alpha
 206       */
 207      protected function setColorProperties(?string $color, $alpha, ?string $colorType): array
 208      {
 209          return [
 210              'type' => $colorType,
 211              'value' => $color,
 212              'alpha' => ($alpha === null) ? null : (int) $alpha,
 213          ];
 214      }
 215  
 216      protected const PRESETS_OPTIONS = [
 217          //NONE
 218          0 => [
 219              'presets' => self::SHADOW_PRESETS_NOSHADOW,
 220              'effect' => null,
 221              //'color' => [
 222              //    'type' => ChartColor::EXCEL_COLOR_TYPE_STANDARD,
 223              //    'value' => 'black',
 224              //    'alpha' => 40,
 225              //],
 226              'size' => [
 227                  'sx' => null,
 228                  'sy' => null,
 229                  'kx' => null,
 230                  'ky' => null,
 231              ],
 232              'blur' => null,
 233              'direction' => null,
 234              'distance' => null,
 235              'algn' => null,
 236              'rotWithShape' => null,
 237          ],
 238          //OUTER
 239          1 => [
 240              'effect' => 'outerShdw',
 241              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 242              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 243              'direction' => 2700000 / self::ANGLE_MULTIPLIER,
 244              'algn' => 'tl',
 245              'rotWithShape' => '0',
 246          ],
 247          2 => [
 248              'effect' => 'outerShdw',
 249              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 250              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 251              'direction' => 5400000 / self::ANGLE_MULTIPLIER,
 252              'algn' => 't',
 253              'rotWithShape' => '0',
 254          ],
 255          3 => [
 256              'effect' => 'outerShdw',
 257              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 258              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 259              'direction' => 8100000 / self::ANGLE_MULTIPLIER,
 260              'algn' => 'tr',
 261              'rotWithShape' => '0',
 262          ],
 263          4 => [
 264              'effect' => 'outerShdw',
 265              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 266              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 267              'algn' => 'l',
 268              'rotWithShape' => '0',
 269          ],
 270          5 => [
 271              'effect' => 'outerShdw',
 272              'size' => [
 273                  'sx' => 102000 / self::PERCENTAGE_MULTIPLIER,
 274                  'sy' => 102000 / self::PERCENTAGE_MULTIPLIER,
 275              ],
 276              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 277              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 278              'algn' => 'ctr',
 279              'rotWithShape' => '0',
 280          ],
 281          6 => [
 282              'effect' => 'outerShdw',
 283              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 284              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 285              'direction' => 10800000 / self::ANGLE_MULTIPLIER,
 286              'algn' => 'r',
 287              'rotWithShape' => '0',
 288          ],
 289          7 => [
 290              'effect' => 'outerShdw',
 291              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 292              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 293              'direction' => 18900000 / self::ANGLE_MULTIPLIER,
 294              'algn' => 'bl',
 295              'rotWithShape' => '0',
 296          ],
 297          8 => [
 298              'effect' => 'outerShdw',
 299              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 300              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 301              'direction' => 16200000 / self::ANGLE_MULTIPLIER,
 302              'rotWithShape' => '0',
 303          ],
 304          9 => [
 305              'effect' => 'outerShdw',
 306              'blur' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 307              'distance' => 38100 / self::POINTS_WIDTH_MULTIPLIER,
 308              'direction' => 13500000 / self::ANGLE_MULTIPLIER,
 309              'algn' => 'br',
 310              'rotWithShape' => '0',
 311          ],
 312          //INNER
 313          10 => [
 314              'effect' => 'innerShdw',
 315              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 316              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 317              'direction' => 2700000 / self::ANGLE_MULTIPLIER,
 318          ],
 319          11 => [
 320              'effect' => 'innerShdw',
 321              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 322              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 323              'direction' => 5400000 / self::ANGLE_MULTIPLIER,
 324          ],
 325          12 => [
 326              'effect' => 'innerShdw',
 327              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 328              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 329              'direction' => 8100000 / self::ANGLE_MULTIPLIER,
 330          ],
 331          13 => [
 332              'effect' => 'innerShdw',
 333              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 334              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 335          ],
 336          14 => [
 337              'effect' => 'innerShdw',
 338              'blur' => 114300 / self::POINTS_WIDTH_MULTIPLIER,
 339          ],
 340          15 => [
 341              'effect' => 'innerShdw',
 342              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 343              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 344              'direction' => 10800000 / self::ANGLE_MULTIPLIER,
 345          ],
 346          16 => [
 347              'effect' => 'innerShdw',
 348              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 349              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 350              'direction' => 18900000 / self::ANGLE_MULTIPLIER,
 351          ],
 352          17 => [
 353              'effect' => 'innerShdw',
 354              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 355              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 356              'direction' => 16200000 / self::ANGLE_MULTIPLIER,
 357          ],
 358          18 => [
 359              'effect' => 'innerShdw',
 360              'blur' => 63500 / self::POINTS_WIDTH_MULTIPLIER,
 361              'distance' => 50800 / self::POINTS_WIDTH_MULTIPLIER,
 362              'direction' => 13500000 / self::ANGLE_MULTIPLIER,
 363          ],
 364          //perspective
 365          19 => [
 366              'effect' => 'outerShdw',
 367              'blur' => 152400 / self::POINTS_WIDTH_MULTIPLIER,
 368              'distance' => 317500 / self::POINTS_WIDTH_MULTIPLIER,
 369              'size' => [
 370                  'sx' => 90000 / self::PERCENTAGE_MULTIPLIER,
 371                  'sy' => -19000 / self::PERCENTAGE_MULTIPLIER,
 372              ],
 373              'direction' => 5400000 / self::ANGLE_MULTIPLIER,
 374              'rotWithShape' => '0',
 375          ],
 376          20 => [
 377              'effect' => 'outerShdw',
 378              'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
 379              'direction' => 18900000 / self::ANGLE_MULTIPLIER,
 380              'size' => [
 381                  'sy' => 23000 / self::PERCENTAGE_MULTIPLIER,
 382                  'kx' => -1200000 / self::ANGLE_MULTIPLIER,
 383              ],
 384              'algn' => 'bl',
 385              'rotWithShape' => '0',
 386          ],
 387          21 => [
 388              'effect' => 'outerShdw',
 389              'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
 390              'direction' => 13500000 / self::ANGLE_MULTIPLIER,
 391              'size' => [
 392                  'sy' => 23000 / self::PERCENTAGE_MULTIPLIER,
 393                  'kx' => 1200000 / self::ANGLE_MULTIPLIER,
 394              ],
 395              'algn' => 'br',
 396              'rotWithShape' => '0',
 397          ],
 398          22 => [
 399              'effect' => 'outerShdw',
 400              'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
 401              'distance' => 12700 / self::POINTS_WIDTH_MULTIPLIER,
 402              'direction' => 2700000 / self::ANGLE_MULTIPLIER,
 403              'size' => [
 404                  'sy' => -23000 / self::PERCENTAGE_MULTIPLIER,
 405                  'kx' => -800400 / self::ANGLE_MULTIPLIER,
 406              ],
 407              'algn' => 'bl',
 408              'rotWithShape' => '0',
 409          ],
 410          23 => [
 411              'effect' => 'outerShdw',
 412              'blur' => 76200 / self::POINTS_WIDTH_MULTIPLIER,
 413              'distance' => 12700 / self::POINTS_WIDTH_MULTIPLIER,
 414              'direction' => 8100000 / self::ANGLE_MULTIPLIER,
 415              'size' => [
 416                  'sy' => -23000 / self::PERCENTAGE_MULTIPLIER,
 417                  'kx' => 800400 / self::ANGLE_MULTIPLIER,
 418              ],
 419              'algn' => 'br',
 420              'rotWithShape' => '0',
 421          ],
 422      ];
 423  
 424      protected function getShadowPresetsMap(int $presetsOption): array
 425      {
 426          return self::PRESETS_OPTIONS[$presetsOption] ?? self::PRESETS_OPTIONS[0];
 427      }
 428  
 429      /**
 430       * Get value of array element.
 431       *
 432       * @param mixed $properties
 433       * @param mixed $elements
 434       *
 435       * @return mixed
 436       */
 437      protected function getArrayElementsValue($properties, $elements)
 438      {
 439          $reference = &$properties;
 440          if (!is_array($elements)) {
 441              return $reference[$elements];
 442          }
 443  
 444          foreach ($elements as $keys) {
 445              $reference = &$reference[$keys];
 446          }
 447  
 448          return $reference;
 449      }
 450  
 451      /**
 452       * Set Glow Properties.
 453       *
 454       * @param float $size
 455       * @param ?string $colorValue
 456       * @param ?int $colorAlpha
 457       * @param ?string $colorType
 458       */
 459      public function setGlowProperties($size, $colorValue = null, $colorAlpha = null, $colorType = null): void
 460      {
 461          $this
 462              ->activateObject()
 463              ->setGlowSize($size);
 464          $this->glowColor->setColorPropertiesArray(
 465              [
 466                  'value' => $colorValue,
 467                  'type' => $colorType,
 468                  'alpha' => $colorAlpha,
 469              ]
 470          );
 471      }
 472  
 473      /**
 474       * Get Glow Property.
 475       *
 476       * @param array|string $property
 477       *
 478       * @return null|array|float|int|string
 479       */
 480      public function getGlowProperty($property)
 481      {
 482          $retVal = null;
 483          if ($property === 'size') {
 484              $retVal = $this->glowSize;
 485          } elseif ($property === 'color') {
 486              $retVal = [
 487                  'value' => $this->glowColor->getColorProperty('value'),
 488                  'type' => $this->glowColor->getColorProperty('type'),
 489                  'alpha' => $this->glowColor->getColorProperty('alpha'),
 490              ];
 491          } elseif (is_array($property) && count($property) >= 2 && $property[0] === 'color') {
 492              $retVal = $this->glowColor->getColorProperty($property[1]);
 493          }
 494  
 495          return $retVal;
 496      }
 497  
 498      /**
 499       * Get Glow Color Property.
 500       *
 501       * @param string $propertyName
 502       *
 503       * @return null|int|string
 504       */
 505      public function getGlowColor($propertyName)
 506      {
 507          return $this->glowColor->getColorProperty($propertyName);
 508      }
 509  
 510      public function getGlowColorObject(): ChartColor
 511      {
 512          return $this->glowColor;
 513      }
 514  
 515      /**
 516       * Get Glow Size.
 517       *
 518       * @return ?float
 519       */
 520      public function getGlowSize()
 521      {
 522          return $this->glowSize;
 523      }
 524  
 525      /**
 526       * Set Glow Size.
 527       *
 528       * @param ?float $size
 529       *
 530       * @return $this
 531       */
 532      protected function setGlowSize($size)
 533      {
 534          $this->glowSize = $size;
 535  
 536          return $this;
 537      }
 538  
 539      /**
 540       * Set Soft Edges Size.
 541       *
 542       * @param float $size
 543       */
 544      public function setSoftEdges($size): void
 545      {
 546          if ($size !== null) {
 547              $this->activateObject();
 548              $this->softEdges['size'] = $size;
 549          }
 550      }
 551  
 552      /**
 553       * Get Soft Edges Size.
 554       *
 555       * @return string
 556       */
 557      public function getSoftEdgesSize()
 558      {
 559          return $this->softEdges['size'];
 560      }
 561  
 562      /**
 563       * @param mixed $value
 564       */
 565      public function setShadowProperty(string $propertyName, $value): self
 566      {
 567          $this->activateObject();
 568          if ($propertyName === 'color' && is_array($value)) {
 569              $this->shadowColor->setColorPropertiesArray($value);
 570          } else {
 571              $this->shadowProperties[$propertyName] = $value;
 572          }
 573  
 574          return $this;
 575      }
 576  
 577      /**
 578       * Set Shadow Properties.
 579       *
 580       * @param int $presets
 581       * @param string $colorValue
 582       * @param string $colorType
 583       * @param null|float|int|string $colorAlpha
 584       * @param null|float $blur
 585       * @param null|int $angle
 586       * @param null|float $distance
 587       */
 588      public function setShadowProperties($presets, $colorValue = null, $colorType = null, $colorAlpha = null, $blur = null, $angle = null, $distance = null): void
 589      {
 590          $this->activateObject()->setShadowPresetsProperties((int) $presets);
 591          if ($presets === 0) {
 592              $this->shadowColor->setType(ChartColor::EXCEL_COLOR_TYPE_STANDARD);
 593              $this->shadowColor->setValue('black');
 594              $this->shadowColor->setAlpha(40);
 595          }
 596          if ($colorValue !== null) {
 597              $this->shadowColor->setValue($colorValue);
 598          }
 599          if ($colorType !== null) {
 600              $this->shadowColor->setType($colorType);
 601          }
 602          if (is_numeric($colorAlpha)) {
 603              $this->shadowColor->setAlpha((int) $colorAlpha);
 604          }
 605          $this
 606              ->setShadowBlur($blur)
 607              ->setShadowAngle($angle)
 608              ->setShadowDistance($distance);
 609      }
 610  
 611      /**
 612       * Set Shadow Presets Properties.
 613       *
 614       * @param int $presets
 615       *
 616       * @return $this
 617       */
 618      protected function setShadowPresetsProperties($presets)
 619      {
 620          $this->shadowProperties['presets'] = $presets;
 621          $this->setShadowPropertiesMapValues($this->getShadowPresetsMap($presets));
 622  
 623          return $this;
 624      }
 625  
 626      protected const SHADOW_ARRAY_KEYS = ['size', 'color'];
 627  
 628      /**
 629       * Set Shadow Properties Values.
 630       *
 631       * @param mixed $reference
 632       *
 633       * @return $this
 634       */
 635      protected function setShadowPropertiesMapValues(array $propertiesMap, &$reference = null)
 636      {
 637          $base_reference = $reference;
 638          foreach ($propertiesMap as $property_key => $property_val) {
 639              if (is_array($property_val)) {
 640                  if (in_array($property_key, self::SHADOW_ARRAY_KEYS, true)) {
 641                      $reference = &$this->shadowProperties[$property_key];
 642                      $this->setShadowPropertiesMapValues($property_val, $reference);
 643                  }
 644              } else {
 645                  if ($base_reference === null) {
 646                      $this->shadowProperties[$property_key] = $property_val;
 647                  } else {
 648                      $reference[$property_key] = $property_val;
 649                  }
 650              }
 651          }
 652  
 653          return $this;
 654      }
 655  
 656      /**
 657       * Set Shadow Blur.
 658       *
 659       * @param ?float $blur
 660       *
 661       * @return $this
 662       */
 663      protected function setShadowBlur($blur)
 664      {
 665          if ($blur !== null) {
 666              $this->shadowProperties['blur'] = $blur;
 667          }
 668  
 669          return $this;
 670      }
 671  
 672      /**
 673       * Set Shadow Angle.
 674       *
 675       * @param null|float|int|string $angle
 676       *
 677       * @return $this
 678       */
 679      protected function setShadowAngle($angle)
 680      {
 681          if (is_numeric($angle)) {
 682              $this->shadowProperties['direction'] = $angle;
 683          }
 684  
 685          return $this;
 686      }
 687  
 688      /**
 689       * Set Shadow Distance.
 690       *
 691       * @param ?float $distance
 692       *
 693       * @return $this
 694       */
 695      protected function setShadowDistance($distance)
 696      {
 697          if ($distance !== null) {
 698              $this->shadowProperties['distance'] = $distance;
 699          }
 700  
 701          return $this;
 702      }
 703  
 704      public function getShadowColorObject(): ChartColor
 705      {
 706          return $this->shadowColor;
 707      }
 708  
 709      /**
 710       * Get Shadow Property.
 711       *
 712       * @param string|string[] $elements
 713       *
 714       * @return array|string
 715       */
 716      public function getShadowProperty($elements)
 717      {
 718          if ($elements === 'color') {
 719              return [
 720                  'value' => $this->shadowColor->getValue(),
 721                  'type' => $this->shadowColor->getType(),
 722                  'alpha' => $this->shadowColor->getAlpha(),
 723              ];
 724          }
 725  
 726          return $this->getArrayElementsValue($this->shadowProperties, $elements);
 727      }
 728  
 729      public function getShadowArray(): array
 730      {
 731          $array = $this->shadowProperties;
 732          if ($this->getShadowColorObject()->isUsable()) {
 733              $array['color'] = $this->getShadowProperty('color');
 734          }
 735  
 736          return $array;
 737      }
 738  
 739      /** @var ChartColor */
 740      protected $lineColor;
 741  
 742      /** @var array */
 743      protected $lineStyleProperties = [
 744          'width' => null, //'9525',
 745          'compound' => '', //self::LINE_STYLE_COMPOUND_SIMPLE,
 746          'dash' => '', //self::LINE_STYLE_DASH_SOLID,
 747          'cap' => '', //self::LINE_STYLE_CAP_FLAT,
 748          'join' => '', //self::LINE_STYLE_JOIN_BEVEL,
 749          'arrow' => [
 750              'head' => [
 751                  'type' => '', //self::LINE_STYLE_ARROW_TYPE_NOARROW,
 752                  'size' => '', //self::LINE_STYLE_ARROW_SIZE_5,
 753                  'w' => '',
 754                  'len' => '',
 755              ],
 756              'end' => [
 757                  'type' => '', //self::LINE_STYLE_ARROW_TYPE_NOARROW,
 758                  'size' => '', //self::LINE_STYLE_ARROW_SIZE_8,
 759                  'w' => '',
 760                  'len' => '',
 761              ],
 762          ],
 763      ];
 764  
 765      public function copyLineStyles(self $otherProperties): void
 766      {
 767          $this->lineStyleProperties = $otherProperties->lineStyleProperties;
 768          $this->lineColor = $otherProperties->lineColor;
 769          $this->glowSize = $otherProperties->glowSize;
 770          $this->glowColor = $otherProperties->glowColor;
 771          $this->softEdges = $otherProperties->softEdges;
 772          $this->shadowProperties = $otherProperties->shadowProperties;
 773      }
 774  
 775      public function getLineColor(): ChartColor
 776      {
 777          return $this->lineColor;
 778      }
 779  
 780      /**
 781       * Set Line Color Properties.
 782       *
 783       * @param string $value
 784       * @param ?int $alpha
 785       * @param ?string $colorType
 786       */
 787      public function setLineColorProperties($value, $alpha = null, $colorType = null): void
 788      {
 789          $this->activateObject();
 790          $this->lineColor->setColorPropertiesArray(
 791              $this->setColorProperties(
 792                  $value,
 793                  $alpha,
 794                  $colorType
 795              )
 796          );
 797      }
 798  
 799      /**
 800       * Get Line Color Property.
 801       *
 802       * @param string $propertyName
 803       *
 804       * @return null|int|string
 805       */
 806      public function getLineColorProperty($propertyName)
 807      {
 808          return $this->lineColor->getColorProperty($propertyName);
 809      }
 810  
 811      /**
 812       * Set Line Style Properties.
 813       *
 814       * @param null|float|int|string $lineWidth
 815       * @param string $compoundType
 816       * @param string $dashType
 817       * @param string $capType
 818       * @param string $joinType
 819       * @param string $headArrowType
 820       * @param string $headArrowSize
 821       * @param string $endArrowType
 822       * @param string $endArrowSize
 823       * @param string $headArrowWidth
 824       * @param string $headArrowLength
 825       * @param string $endArrowWidth
 826       * @param string $endArrowLength
 827       */
 828      public function setLineStyleProperties($lineWidth = null, $compoundType = '', $dashType = '', $capType = '', $joinType = '', $headArrowType = '', $headArrowSize = '', $endArrowType = '', $endArrowSize = '', $headArrowWidth = '', $headArrowLength = '', $endArrowWidth = '', $endArrowLength = ''): void
 829      {
 830          $this->activateObject();
 831          if (is_numeric($lineWidth)) {
 832              $this->lineStyleProperties['width'] = $lineWidth;
 833          }
 834          if ($compoundType !== '') {
 835              $this->lineStyleProperties['compound'] = $compoundType;
 836          }
 837          if ($dashType !== '') {
 838              $this->lineStyleProperties['dash'] = $dashType;
 839          }
 840          if ($capType !== '') {
 841              $this->lineStyleProperties['cap'] = $capType;
 842          }
 843          if ($joinType !== '') {
 844              $this->lineStyleProperties['join'] = $joinType;
 845          }
 846          if ($headArrowType !== '') {
 847              $this->lineStyleProperties['arrow']['head']['type'] = $headArrowType;
 848          }
 849          if (array_key_exists($headArrowSize, self::ARROW_SIZES)) {
 850              $this->lineStyleProperties['arrow']['head']['size'] = $headArrowSize;
 851              $this->lineStyleProperties['arrow']['head']['w'] = self::ARROW_SIZES[$headArrowSize]['w'];
 852              $this->lineStyleProperties['arrow']['head']['len'] = self::ARROW_SIZES[$headArrowSize]['len'];
 853          }
 854          if ($endArrowType !== '') {
 855              $this->lineStyleProperties['arrow']['end']['type'] = $endArrowType;
 856          }
 857          if (array_key_exists($endArrowSize, self::ARROW_SIZES)) {
 858              $this->lineStyleProperties['arrow']['end']['size'] = $endArrowSize;
 859              $this->lineStyleProperties['arrow']['end']['w'] = self::ARROW_SIZES[$endArrowSize]['w'];
 860              $this->lineStyleProperties['arrow']['end']['len'] = self::ARROW_SIZES[$endArrowSize]['len'];
 861          }
 862          if ($headArrowWidth !== '') {
 863              $this->lineStyleProperties['arrow']['head']['w'] = $headArrowWidth;
 864          }
 865          if ($headArrowLength !== '') {
 866              $this->lineStyleProperties['arrow']['head']['len'] = $headArrowLength;
 867          }
 868          if ($endArrowWidth !== '') {
 869              $this->lineStyleProperties['arrow']['end']['w'] = $endArrowWidth;
 870          }
 871          if ($endArrowLength !== '') {
 872              $this->lineStyleProperties['arrow']['end']['len'] = $endArrowLength;
 873          }
 874      }
 875  
 876      public function getLineStyleArray(): array
 877      {
 878          return $this->lineStyleProperties;
 879      }
 880  
 881      public function setLineStyleArray(array $lineStyleProperties = []): self
 882      {
 883          $this->activateObject();
 884          $this->lineStyleProperties['width'] = $lineStyleProperties['width'] ?? null;
 885          $this->lineStyleProperties['compound'] = $lineStyleProperties['compound'] ?? '';
 886          $this->lineStyleProperties['dash'] = $lineStyleProperties['dash'] ?? '';
 887          $this->lineStyleProperties['cap'] = $lineStyleProperties['cap'] ?? '';
 888          $this->lineStyleProperties['join'] = $lineStyleProperties['join'] ?? '';
 889          $this->lineStyleProperties['arrow']['head']['type'] = $lineStyleProperties['arrow']['head']['type'] ?? '';
 890          $this->lineStyleProperties['arrow']['head']['size'] = $lineStyleProperties['arrow']['head']['size'] ?? '';
 891          $this->lineStyleProperties['arrow']['head']['w'] = $lineStyleProperties['arrow']['head']['w'] ?? '';
 892          $this->lineStyleProperties['arrow']['head']['len'] = $lineStyleProperties['arrow']['head']['len'] ?? '';
 893          $this->lineStyleProperties['arrow']['end']['type'] = $lineStyleProperties['arrow']['end']['type'] ?? '';
 894          $this->lineStyleProperties['arrow']['end']['size'] = $lineStyleProperties['arrow']['end']['size'] ?? '';
 895          $this->lineStyleProperties['arrow']['end']['w'] = $lineStyleProperties['arrow']['end']['w'] ?? '';
 896          $this->lineStyleProperties['arrow']['end']['len'] = $lineStyleProperties['arrow']['end']['len'] ?? '';
 897  
 898          return $this;
 899      }
 900  
 901      /**
 902       * @param mixed $value
 903       */
 904      public function setLineStyleProperty(string $propertyName, $value): self
 905      {
 906          $this->activateObject();
 907          $this->lineStyleProperties[$propertyName] = $value;
 908  
 909          return $this;
 910      }
 911  
 912      /**
 913       * Get Line Style Property.
 914       *
 915       * @param array|string $elements
 916       *
 917       * @return string
 918       */
 919      public function getLineStyleProperty($elements)
 920      {
 921          return $this->getArrayElementsValue($this->lineStyleProperties, $elements);
 922      }
 923  
 924      protected const ARROW_SIZES = [
 925          1 => ['w' => 'sm', 'len' => 'sm'],
 926          2 => ['w' => 'sm', 'len' => 'med'],
 927          3 => ['w' => 'sm', 'len' => 'lg'],
 928          4 => ['w' => 'med', 'len' => 'sm'],
 929          5 => ['w' => 'med', 'len' => 'med'],
 930          6 => ['w' => 'med', 'len' => 'lg'],
 931          7 => ['w' => 'lg', 'len' => 'sm'],
 932          8 => ['w' => 'lg', 'len' => 'med'],
 933          9 => ['w' => 'lg', 'len' => 'lg'],
 934      ];
 935  
 936      /**
 937       * Get Line Style Arrow Size.
 938       *
 939       * @param int $arraySelector
 940       * @param string $arrayKaySelector
 941       *
 942       * @return string
 943       */
 944      protected function getLineStyleArrowSize($arraySelector, $arrayKaySelector)
 945      {
 946          return self::ARROW_SIZES[$arraySelector][$arrayKaySelector] ?? '';
 947      }
 948  
 949      /**
 950       * Get Line Style Arrow Parameters.
 951       *
 952       * @param string $arrowSelector
 953       * @param string $propertySelector
 954       *
 955       * @return string
 956       */
 957      public function getLineStyleArrowParameters($arrowSelector, $propertySelector)
 958      {
 959          return $this->getLineStyleArrowSize($this->lineStyleProperties['arrow'][$arrowSelector]['size'], $propertySelector);
 960      }
 961  
 962      /**
 963       * Get Line Style Arrow Width.
 964       *
 965       * @param string $arrow
 966       *
 967       * @return string
 968       */
 969      public function getLineStyleArrowWidth($arrow)
 970      {
 971          return $this->getLineStyleProperty(['arrow', $arrow, 'w']);
 972      }
 973  
 974      /**
 975       * Get Line Style Arrow Excel Length.
 976       *
 977       * @param string $arrow
 978       *
 979       * @return string
 980       */
 981      public function getLineStyleArrowLength($arrow)
 982      {
 983          return $this->getLineStyleProperty(['arrow', $arrow, 'len']);
 984      }
 985  }