Search moodle.org's
Developer Documentation

See Release Notes

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

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