Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

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

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Chart;
   4  
   5  use PhpOffice\PhpSpreadsheet\Settings;
   6  use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
   7  
   8  class Chart
   9  {
  10      /**
  11       * Chart Name.
  12       *
  13       * @var string
  14       */
  15      private $name = '';
  16  
  17      /**
  18       * Worksheet.
  19       *
  20       * @var ?Worksheet
  21       */
  22      private $worksheet;
  23  
  24      /**
  25       * Chart Title.
  26       *
  27       * @var ?Title
  28       */
  29      private $title;
  30  
  31      /**
  32       * Chart Legend.
  33       *
  34       * @var ?Legend
  35       */
  36      private $legend;
  37  
  38      /**
  39       * X-Axis Label.
  40       *
  41       * @var ?Title
  42       */
  43      private $xAxisLabel;
  44  
  45      /**
  46       * Y-Axis Label.
  47       *
  48       * @var ?Title
  49       */
  50      private $yAxisLabel;
  51  
  52      /**
  53       * Chart Plot Area.
  54       *
  55       * @var ?PlotArea
  56       */
  57      private $plotArea;
  58  
  59      /**
  60       * Plot Visible Only.
  61       *
  62       * @var bool
  63       */
  64      private $plotVisibleOnly = true;
  65  
  66      /**
  67       * Display Blanks as.
  68       *
  69       * @var string
  70       */
  71      private $displayBlanksAs = DataSeries::EMPTY_AS_GAP;
  72  
  73      /**
  74       * Chart Asix Y as.
  75       *
  76       * @var Axis
  77       */
  78      private $yAxis;
  79  
  80      /**
  81       * Chart Asix X as.
  82       *
  83       * @var Axis
  84       */
  85      private $xAxis;
  86  
  87      /**
  88       * Top-Left Cell Position.
  89       *
  90       * @var string
  91       */
  92      private $topLeftCellRef = 'A1';
  93  
  94      /**
  95       * Top-Left X-Offset.
  96       *
  97       * @var int
  98       */
  99      private $topLeftXOffset = 0;
 100  
 101      /**
 102       * Top-Left Y-Offset.
 103       *
 104       * @var int
 105       */
 106      private $topLeftYOffset = 0;
 107  
 108      /**
 109       * Bottom-Right Cell Position.
 110       *
 111       * @var string
 112       */
 113      private $bottomRightCellRef = '';
 114  
 115      /**
 116       * Bottom-Right X-Offset.
 117       *
 118       * @var int
 119       */
 120      private $bottomRightXOffset = 10;
 121  
 122      /**
 123       * Bottom-Right Y-Offset.
 124       *
 125       * @var int
 126       */
 127      private $bottomRightYOffset = 10;
 128  
 129      /** @var ?int */
 130      private $rotX;
 131  
 132      /** @var ?int */
 133      private $rotY;
 134  
 135      /** @var ?int */
 136      private $rAngAx;
 137  
 138      /** @var ?int */
 139      private $perspective;
 140  
 141      /** @var bool */
 142      private $oneCellAnchor = false;
 143  
 144      /** @var bool */
 145      private $autoTitleDeleted = false;
 146  
 147      /** @var bool */
 148      private $noFill = false;
 149  
 150      /** @var bool */
 151      private $roundedCorners = false;
 152  
 153      /**
 154       * Create a new Chart.
 155       * majorGridlines and minorGridlines are deprecated, moved to Axis.
 156       *
 157       * @param mixed $name
 158       * @param mixed $plotVisibleOnly
 159       * @param string $displayBlanksAs
 160       */
 161      public function __construct($name, ?Title $title = null, ?Legend $legend = null, ?PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = DataSeries::EMPTY_AS_GAP, ?Title $xAxisLabel = null, ?Title $yAxisLabel = null, ?Axis $xAxis = null, ?Axis $yAxis = null, ?GridLines $majorGridlines = null, ?GridLines $minorGridlines = null)
 162      {
 163          $this->name = $name;
 164          $this->title = $title;
 165          $this->legend = $legend;
 166          $this->xAxisLabel = $xAxisLabel;
 167          $this->yAxisLabel = $yAxisLabel;
 168          $this->plotArea = $plotArea;
 169          $this->plotVisibleOnly = $plotVisibleOnly;
 170          $this->displayBlanksAs = $displayBlanksAs;
 171          $this->xAxis = $xAxis ?? new Axis();
 172          $this->yAxis = $yAxis ?? new Axis();
 173          if ($majorGridlines !== null) {
 174              $this->yAxis->setMajorGridlines($majorGridlines);
 175          }
 176          if ($minorGridlines !== null) {
 177              $this->yAxis->setMinorGridlines($minorGridlines);
 178          }
 179      }
 180  
 181      /**
 182       * Get Name.
 183       *
 184       * @return string
 185       */
 186      public function getName()
 187      {
 188          return $this->name;
 189      }
 190  
 191      public function setName(string $name): self
 192      {
 193          $this->name = $name;
 194  
 195          return $this;
 196      }
 197  
 198      /**
 199       * Get Worksheet.
 200       */
 201      public function getWorksheet(): ?Worksheet
 202      {
 203          return $this->worksheet;
 204      }
 205  
 206      /**
 207       * Set Worksheet.
 208       *
 209       * @return $this
 210       */
 211      public function setWorksheet(?Worksheet $worksheet = null)
 212      {
 213          $this->worksheet = $worksheet;
 214  
 215          return $this;
 216      }
 217  
 218      public function getTitle(): ?Title
 219      {
 220          return $this->title;
 221      }
 222  
 223      /**
 224       * Set Title.
 225       *
 226       * @return $this
 227       */
 228      public function setTitle(Title $title)
 229      {
 230          $this->title = $title;
 231  
 232          return $this;
 233      }
 234  
 235      public function getLegend(): ?Legend
 236      {
 237          return $this->legend;
 238      }
 239  
 240      /**
 241       * Set Legend.
 242       *
 243       * @return $this
 244       */
 245      public function setLegend(Legend $legend)
 246      {
 247          $this->legend = $legend;
 248  
 249          return $this;
 250      }
 251  
 252      public function getXAxisLabel(): ?Title
 253      {
 254          return $this->xAxisLabel;
 255      }
 256  
 257      /**
 258       * Set X-Axis Label.
 259       *
 260       * @return $this
 261       */
 262      public function setXAxisLabel(Title $label)
 263      {
 264          $this->xAxisLabel = $label;
 265  
 266          return $this;
 267      }
 268  
 269      public function getYAxisLabel(): ?Title
 270      {
 271          return $this->yAxisLabel;
 272      }
 273  
 274      /**
 275       * Set Y-Axis Label.
 276       *
 277       * @return $this
 278       */
 279      public function setYAxisLabel(Title $label)
 280      {
 281          $this->yAxisLabel = $label;
 282  
 283          return $this;
 284      }
 285  
 286      public function getPlotArea(): ?PlotArea
 287      {
 288          return $this->plotArea;
 289      }
 290  
 291      /**
 292       * Set Plot Area.
 293       */
 294      public function setPlotArea(PlotArea $plotArea): self
 295      {
 296          $this->plotArea = $plotArea;
 297  
 298          return $this;
 299      }
 300  
 301      /**
 302       * Get Plot Visible Only.
 303       *
 304       * @return bool
 305       */
 306      public function getPlotVisibleOnly()
 307      {
 308          return $this->plotVisibleOnly;
 309      }
 310  
 311      /**
 312       * Set Plot Visible Only.
 313       *
 314       * @param bool $plotVisibleOnly
 315       *
 316       * @return $this
 317       */
 318      public function setPlotVisibleOnly($plotVisibleOnly)
 319      {
 320          $this->plotVisibleOnly = $plotVisibleOnly;
 321  
 322          return $this;
 323      }
 324  
 325      /**
 326       * Get Display Blanks as.
 327       *
 328       * @return string
 329       */
 330      public function getDisplayBlanksAs()
 331      {
 332          return $this->displayBlanksAs;
 333      }
 334  
 335      /**
 336       * Set Display Blanks as.
 337       *
 338       * @param string $displayBlanksAs
 339       *
 340       * @return $this
 341       */
 342      public function setDisplayBlanksAs($displayBlanksAs)
 343      {
 344          $this->displayBlanksAs = $displayBlanksAs;
 345  
 346          return $this;
 347      }
 348  
 349      public function getChartAxisY(): Axis
 350      {
 351          return $this->yAxis;
 352      }
 353  
 354      /**
 355       * Set yAxis.
 356       */
 357      public function setChartAxisY(?Axis $axis): self
 358      {
 359          $this->yAxis = $axis ?? new Axis();
 360  
 361          return $this;
 362      }
 363  
 364      public function getChartAxisX(): Axis
 365      {
 366          return $this->xAxis;
 367      }
 368  
 369      /**
 370       * Set xAxis.
 371       */
 372      public function setChartAxisX(?Axis $axis): self
 373      {
 374          $this->xAxis = $axis ?? new Axis();
 375  
 376          return $this;
 377      }
 378  
 379      /**
 380       * Get Major Gridlines.
 381       *
 382       * @deprecated 1.24.0 Use Axis->getMajorGridlines()
 383       * @see Axis::getMajorGridlines()
 384       *
 385       * @codeCoverageIgnore
 386       */
 387      public function getMajorGridlines(): ?GridLines
 388      {
 389          return $this->yAxis->getMajorGridLines();
 390      }
 391  
 392      /**
 393       * Get Minor Gridlines.
 394       *
 395       * @deprecated 1.24.0 Use Axis->getMinorGridlines()
 396       * @see Axis::getMinorGridlines()
 397       *
 398       * @codeCoverageIgnore
 399       */
 400      public function getMinorGridlines(): ?GridLines
 401      {
 402          return $this->yAxis->getMinorGridLines();
 403      }
 404  
 405      /**
 406       * Set the Top Left position for the chart.
 407       *
 408       * @param string $cellAddress
 409       * @param int $xOffset
 410       * @param int $yOffset
 411       *
 412       * @return $this
 413       */
 414      public function setTopLeftPosition($cellAddress, $xOffset = null, $yOffset = null)
 415      {
 416          $this->topLeftCellRef = $cellAddress;
 417          if ($xOffset !== null) {
 418              $this->setTopLeftXOffset($xOffset);
 419          }
 420          if ($yOffset !== null) {
 421              $this->setTopLeftYOffset($yOffset);
 422          }
 423  
 424          return $this;
 425      }
 426  
 427      /**
 428       * Get the top left position of the chart.
 429       *
 430       * Returns ['cell' => string cell address, 'xOffset' => int, 'yOffset' => int].
 431       *
 432       * @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
 433       */
 434      public function getTopLeftPosition(): array
 435      {
 436          return [
 437              'cell' => $this->topLeftCellRef,
 438              'xOffset' => $this->topLeftXOffset,
 439              'yOffset' => $this->topLeftYOffset,
 440          ];
 441      }
 442  
 443      /**
 444       * Get the cell address where the top left of the chart is fixed.
 445       *
 446       * @return string
 447       */
 448      public function getTopLeftCell()
 449      {
 450          return $this->topLeftCellRef;
 451      }
 452  
 453      /**
 454       * Set the Top Left cell position for the chart.
 455       *
 456       * @param string $cellAddress
 457       *
 458       * @return $this
 459       */
 460      public function setTopLeftCell($cellAddress)
 461      {
 462          $this->topLeftCellRef = $cellAddress;
 463  
 464          return $this;
 465      }
 466  
 467      /**
 468       * Set the offset position within the Top Left cell for the chart.
 469       *
 470       * @param ?int $xOffset
 471       * @param ?int $yOffset
 472       *
 473       * @return $this
 474       */
 475      public function setTopLeftOffset($xOffset, $yOffset)
 476      {
 477          if ($xOffset !== null) {
 478              $this->setTopLeftXOffset($xOffset);
 479          }
 480  
 481          if ($yOffset !== null) {
 482              $this->setTopLeftYOffset($yOffset);
 483          }
 484  
 485          return $this;
 486      }
 487  
 488      /**
 489       * Get the offset position within the Top Left cell for the chart.
 490       *
 491       * @return int[]
 492       */
 493      public function getTopLeftOffset()
 494      {
 495          return [
 496              'X' => $this->topLeftXOffset,
 497              'Y' => $this->topLeftYOffset,
 498          ];
 499      }
 500  
 501      /**
 502       * @param int $xOffset
 503       *
 504       * @return $this
 505       */
 506      public function setTopLeftXOffset($xOffset)
 507      {
 508          $this->topLeftXOffset = $xOffset;
 509  
 510          return $this;
 511      }
 512  
 513      public function getTopLeftXOffset(): int
 514      {
 515          return $this->topLeftXOffset;
 516      }
 517  
 518      /**
 519       * @param int $yOffset
 520       *
 521       * @return $this
 522       */
 523      public function setTopLeftYOffset($yOffset)
 524      {
 525          $this->topLeftYOffset = $yOffset;
 526  
 527          return $this;
 528      }
 529  
 530      public function getTopLeftYOffset(): int
 531      {
 532          return $this->topLeftYOffset;
 533      }
 534  
 535      /**
 536       * Set the Bottom Right position of the chart.
 537       *
 538       * @param string $cellAddress
 539       * @param int $xOffset
 540       * @param int $yOffset
 541       *
 542       * @return $this
 543       */
 544      public function setBottomRightPosition($cellAddress = '', $xOffset = null, $yOffset = null)
 545      {
 546          $this->bottomRightCellRef = $cellAddress;
 547          if ($xOffset !== null) {
 548              $this->setBottomRightXOffset($xOffset);
 549          }
 550          if ($yOffset !== null) {
 551              $this->setBottomRightYOffset($yOffset);
 552          }
 553  
 554          return $this;
 555      }
 556  
 557      /**
 558       * Get the bottom right position of the chart.
 559       *
 560       * @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell
 561       */
 562      public function getBottomRightPosition()
 563      {
 564          return [
 565              'cell' => $this->bottomRightCellRef,
 566              'xOffset' => $this->bottomRightXOffset,
 567              'yOffset' => $this->bottomRightYOffset,
 568          ];
 569      }
 570  
 571      /**
 572       * Set the Bottom Right cell for the chart.
 573       *
 574       * @return $this
 575       */
 576      public function setBottomRightCell(string $cellAddress = '')
 577      {
 578          $this->bottomRightCellRef = $cellAddress;
 579  
 580          return $this;
 581      }
 582  
 583      /**
 584       * Get the cell address where the bottom right of the chart is fixed.
 585       */
 586      public function getBottomRightCell(): string
 587      {
 588          return $this->bottomRightCellRef;
 589      }
 590  
 591      /**
 592       * Set the offset position within the Bottom Right cell for the chart.
 593       *
 594       * @param ?int $xOffset
 595       * @param ?int $yOffset
 596       *
 597       * @return $this
 598       */
 599      public function setBottomRightOffset($xOffset, $yOffset)
 600      {
 601          if ($xOffset !== null) {
 602              $this->setBottomRightXOffset($xOffset);
 603          }
 604  
 605          if ($yOffset !== null) {
 606              $this->setBottomRightYOffset($yOffset);
 607          }
 608  
 609          return $this;
 610      }
 611  
 612      /**
 613       * Get the offset position within the Bottom Right cell for the chart.
 614       *
 615       * @return int[]
 616       */
 617      public function getBottomRightOffset()
 618      {
 619          return [
 620              'X' => $this->bottomRightXOffset,
 621              'Y' => $this->bottomRightYOffset,
 622          ];
 623      }
 624  
 625      /**
 626       * @param int $xOffset
 627       *
 628       * @return $this
 629       */
 630      public function setBottomRightXOffset($xOffset)
 631      {
 632          $this->bottomRightXOffset = $xOffset;
 633  
 634          return $this;
 635      }
 636  
 637      public function getBottomRightXOffset(): int
 638      {
 639          return $this->bottomRightXOffset;
 640      }
 641  
 642      /**
 643       * @param int $yOffset
 644       *
 645       * @return $this
 646       */
 647      public function setBottomRightYOffset($yOffset)
 648      {
 649          $this->bottomRightYOffset = $yOffset;
 650  
 651          return $this;
 652      }
 653  
 654      public function getBottomRightYOffset(): int
 655      {
 656          return $this->bottomRightYOffset;
 657      }
 658  
 659      public function refresh(): void
 660      {
 661          if ($this->worksheet !== null && $this->plotArea !== null) {
 662              $this->plotArea->refresh($this->worksheet);
 663          }
 664      }
 665  
 666      /**
 667       * Render the chart to given file (or stream).
 668       *
 669       * @param string $outputDestination Name of the file render to
 670       *
 671       * @return bool true on success
 672       */
 673      public function render($outputDestination = null)
 674      {
 675          if ($outputDestination == 'php://output') {
 676              $outputDestination = null;
 677          }
 678  
 679          $libraryName = Settings::getChartRenderer();
 680          if ($libraryName === null) {
 681              return false;
 682          }
 683  
 684          // Ensure that data series values are up-to-date before we render
 685          $this->refresh();
 686  
 687          $renderer = new $libraryName($this);
 688  
 689          return $renderer->render($outputDestination); // @phpstan-ignore-line
 690      }
 691  
 692      public function getRotX(): ?int
 693      {
 694          return $this->rotX;
 695      }
 696  
 697      public function setRotX(?int $rotX): self
 698      {
 699          $this->rotX = $rotX;
 700  
 701          return $this;
 702      }
 703  
 704      public function getRotY(): ?int
 705      {
 706          return $this->rotY;
 707      }
 708  
 709      public function setRotY(?int $rotY): self
 710      {
 711          $this->rotY = $rotY;
 712  
 713          return $this;
 714      }
 715  
 716      public function getRAngAx(): ?int
 717      {
 718          return $this->rAngAx;
 719      }
 720  
 721      public function setRAngAx(?int $rAngAx): self
 722      {
 723          $this->rAngAx = $rAngAx;
 724  
 725          return $this;
 726      }
 727  
 728      public function getPerspective(): ?int
 729      {
 730          return $this->perspective;
 731      }
 732  
 733      public function setPerspective(?int $perspective): self
 734      {
 735          $this->perspective = $perspective;
 736  
 737          return $this;
 738      }
 739  
 740      public function getOneCellAnchor(): bool
 741      {
 742          return $this->oneCellAnchor;
 743      }
 744  
 745      public function setOneCellAnchor(bool $oneCellAnchor): self
 746      {
 747          $this->oneCellAnchor = $oneCellAnchor;
 748  
 749          return $this;
 750      }
 751  
 752      public function getAutoTitleDeleted(): bool
 753      {
 754          return $this->autoTitleDeleted;
 755      }
 756  
 757      public function setAutoTitleDeleted(bool $autoTitleDeleted): self
 758      {
 759          $this->autoTitleDeleted = $autoTitleDeleted;
 760  
 761          return $this;
 762      }
 763  
 764      public function getNoFill(): bool
 765      {
 766          return $this->noFill;
 767      }
 768  
 769      public function setNoFill(bool $noFill): self
 770      {
 771          $this->noFill = $noFill;
 772  
 773          return $this;
 774      }
 775  
 776      public function getRoundedCorners(): bool
 777      {
 778          return $this->roundedCorners;
 779      }
 780  
 781      public function setRoundedCorners(?bool $roundedCorners): self
 782      {
 783          if ($roundedCorners !== null) {
 784              $this->roundedCorners = $roundedCorners;
 785          }
 786  
 787          return $this;
 788      }
 789  }