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 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Style;
   4  
   5  use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
   6  
   7  class Font extends Supervisor
   8  {
   9      // Underline types
  10      const UNDERLINE_NONE = 'none';
  11      const UNDERLINE_DOUBLE = 'double';
  12      const UNDERLINE_DOUBLEACCOUNTING = 'doubleAccounting';
  13      const UNDERLINE_SINGLE = 'single';
  14      const UNDERLINE_SINGLEACCOUNTING = 'singleAccounting';
  15  
  16      /**
  17       * Font Name.
  18       *
  19       * @var null|string
  20       */
  21      protected $name = 'Calibri';
  22  
  23      /**
  24       * The following 7 are used only for chart titles, I think.
  25       *
  26       *@var string
  27       */
  28      private $latin = '';
  29  
  30      /** @var string */
  31      private $eastAsian = '';
  32  
  33      /** @var string */
  34      private $complexScript = '';
  35  
  36      /** @var int */
  37      private $baseLine = 0;
  38  
  39      /** @var string */
  40      private $strikeType = '';
  41  
  42      /** @var ?ChartColor */
  43      private $underlineColor;
  44  
  45      /** @var ?ChartColor */
  46      private $chartColor;
  47      // end of chart title items
  48  
  49      /**
  50       * Font Size.
  51       *
  52       * @var null|float
  53       */
  54      protected $size = 11;
  55  
  56      /**
  57       * Bold.
  58       *
  59       * @var null|bool
  60       */
  61      protected $bold = false;
  62  
  63      /**
  64       * Italic.
  65       *
  66       * @var null|bool
  67       */
  68      protected $italic = false;
  69  
  70      /**
  71       * Superscript.
  72       *
  73       * @var null|bool
  74       */
  75      protected $superscript = false;
  76  
  77      /**
  78       * Subscript.
  79       *
  80       * @var null|bool
  81       */
  82      protected $subscript = false;
  83  
  84      /**
  85       * Underline.
  86       *
  87       * @var null|string
  88       */
  89      protected $underline = self::UNDERLINE_NONE;
  90  
  91      /**
  92       * Strikethrough.
  93       *
  94       * @var null|bool
  95       */
  96      protected $strikethrough = false;
  97  
  98      /**
  99       * Foreground color.
 100       *
 101       * @var Color
 102       */
 103      protected $color;
 104  
 105      /**
 106       * @var null|int
 107       */
 108      public $colorIndex;
 109  
 110      /**
 111       * Create a new Font.
 112       *
 113       * @param bool $isSupervisor Flag indicating if this is a supervisor or not
 114       *                                    Leave this value at default unless you understand exactly what
 115       *                                        its ramifications are
 116       * @param bool $isConditional Flag indicating if this is a conditional style or not
 117       *                                    Leave this value at default unless you understand exactly what
 118       *                                        its ramifications are
 119       */
 120      public function __construct($isSupervisor = false, $isConditional = false)
 121      {
 122          // Supervisor?
 123          parent::__construct($isSupervisor);
 124  
 125          // Initialise values
 126          if ($isConditional) {
 127              $this->name = null;
 128              $this->size = null;
 129              $this->bold = null;
 130              $this->italic = null;
 131              $this->superscript = null;
 132              $this->subscript = null;
 133              $this->underline = null;
 134              $this->strikethrough = null;
 135              $this->color = new Color(Color::COLOR_BLACK, $isSupervisor, $isConditional);
 136          } else {
 137              $this->color = new Color(Color::COLOR_BLACK, $isSupervisor);
 138          }
 139          // bind parent if we are a supervisor
 140          if ($isSupervisor) {
 141              $this->color->bindParent($this, 'color');
 142          }
 143      }
 144  
 145      /**
 146       * Get the shared style component for the currently active cell in currently active sheet.
 147       * Only used for style supervisor.
 148       *
 149       * @return Font
 150       */
 151      public function getSharedComponent()
 152      {
 153          /** @var Style */
 154          $parent = $this->parent;
 155  
 156          return $parent->getSharedComponent()->getFont();
 157      }
 158  
 159      /**
 160       * Build style array from subcomponents.
 161       *
 162       * @param array $array
 163       *
 164       * @return array
 165       */
 166      public function getStyleArray($array)
 167      {
 168          return ['font' => $array];
 169      }
 170  
 171      /**
 172       * Apply styles from array.
 173       *
 174       * <code>
 175       * $spreadsheet->getActiveSheet()->getStyle('B2')->getFont()->applyFromArray(
 176       *     [
 177       *         'name' => 'Arial',
 178       *         'bold' => TRUE,
 179       *         'italic' => FALSE,
 180       *         'underline' => \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLE,
 181       *         'strikethrough' => FALSE,
 182       *         'color' => [
 183       *             'rgb' => '808080'
 184       *         ]
 185       *     ]
 186       * );
 187       * </code>
 188       *
 189       * @param array $styleArray Array containing style information
 190       *
 191       * @return $this
 192       */
 193      public function applyFromArray(array $styleArray)
 194      {
 195          if ($this->isSupervisor) {
 196              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($styleArray));
 197          } else {
 198              if (isset($styleArray['name'])) {
 199                  $this->setName($styleArray['name']);
 200              }
 201              if (isset($styleArray['latin'])) {
 202                  $this->setLatin($styleArray['latin']);
 203              }
 204              if (isset($styleArray['eastAsian'])) {
 205                  $this->setEastAsian($styleArray['eastAsian']);
 206              }
 207              if (isset($styleArray['complexScript'])) {
 208                  $this->setComplexScript($styleArray['complexScript']);
 209              }
 210              if (isset($styleArray['bold'])) {
 211                  $this->setBold($styleArray['bold']);
 212              }
 213              if (isset($styleArray['italic'])) {
 214                  $this->setItalic($styleArray['italic']);
 215              }
 216              if (isset($styleArray['superscript'])) {
 217                  $this->setSuperscript($styleArray['superscript']);
 218              }
 219              if (isset($styleArray['subscript'])) {
 220                  $this->setSubscript($styleArray['subscript']);
 221              }
 222              if (isset($styleArray['underline'])) {
 223                  $this->setUnderline($styleArray['underline']);
 224              }
 225              if (isset($styleArray['strikethrough'])) {
 226                  $this->setStrikethrough($styleArray['strikethrough']);
 227              }
 228              if (isset($styleArray['color'])) {
 229                  $this->getColor()->applyFromArray($styleArray['color']);
 230              }
 231              if (isset($styleArray['size'])) {
 232                  $this->setSize($styleArray['size']);
 233              }
 234          }
 235  
 236          return $this;
 237      }
 238  
 239      /**
 240       * Get Name.
 241       *
 242       * @return null|string
 243       */
 244      public function getName()
 245      {
 246          if ($this->isSupervisor) {
 247              return $this->getSharedComponent()->getName();
 248          }
 249  
 250          return $this->name;
 251      }
 252  
 253      public function getLatin(): string
 254      {
 255          if ($this->isSupervisor) {
 256              return $this->getSharedComponent()->getLatin();
 257          }
 258  
 259          return $this->latin;
 260      }
 261  
 262      public function getEastAsian(): string
 263      {
 264          if ($this->isSupervisor) {
 265              return $this->getSharedComponent()->getEastAsian();
 266          }
 267  
 268          return $this->eastAsian;
 269      }
 270  
 271      public function getComplexScript(): string
 272      {
 273          if ($this->isSupervisor) {
 274              return $this->getSharedComponent()->getComplexScript();
 275          }
 276  
 277          return $this->complexScript;
 278      }
 279  
 280      /**
 281       * Set Name.
 282       *
 283       * @param string $fontname
 284       *
 285       * @return $this
 286       */
 287      public function setName($fontname)
 288      {
 289          if ($fontname == '') {
 290              $fontname = 'Calibri';
 291          }
 292          if ($this->isSupervisor) {
 293              $styleArray = $this->getStyleArray(['name' => $fontname]);
 294              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 295          } else {
 296              $this->name = $fontname;
 297          }
 298  
 299          return $this;
 300      }
 301  
 302      public function setLatin(string $fontname): self
 303      {
 304          if ($fontname == '') {
 305              $fontname = 'Calibri';
 306          }
 307          if (!$this->isSupervisor) {
 308              $this->latin = $fontname;
 309          } else {
 310              // should never be true
 311              // @codeCoverageIgnoreStart
 312              $styleArray = $this->getStyleArray(['latin' => $fontname]);
 313              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 314              // @codeCoverageIgnoreEnd
 315          }
 316  
 317          return $this;
 318      }
 319  
 320      public function setEastAsian(string $fontname): self
 321      {
 322          if ($fontname == '') {
 323              $fontname = 'Calibri';
 324          }
 325          if (!$this->isSupervisor) {
 326              $this->eastAsian = $fontname;
 327          } else {
 328              // should never be true
 329              // @codeCoverageIgnoreStart
 330              $styleArray = $this->getStyleArray(['eastAsian' => $fontname]);
 331              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 332              // @codeCoverageIgnoreEnd
 333          }
 334  
 335          return $this;
 336      }
 337  
 338      public function setComplexScript(string $fontname): self
 339      {
 340          if ($fontname == '') {
 341              $fontname = 'Calibri';
 342          }
 343          if (!$this->isSupervisor) {
 344              $this->complexScript = $fontname;
 345          } else {
 346              // should never be true
 347              // @codeCoverageIgnoreStart
 348              $styleArray = $this->getStyleArray(['complexScript' => $fontname]);
 349              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 350              // @codeCoverageIgnoreEnd
 351          }
 352  
 353          return $this;
 354      }
 355  
 356      /**
 357       * Get Size.
 358       *
 359       * @return null|float
 360       */
 361      public function getSize()
 362      {
 363          if ($this->isSupervisor) {
 364              return $this->getSharedComponent()->getSize();
 365          }
 366  
 367          return $this->size;
 368      }
 369  
 370      /**
 371       * Set Size.
 372       *
 373       * @param mixed $sizeInPoints A float representing the value of a positive measurement in points (1/72 of an inch)
 374       *
 375       * @return $this
 376       */
 377      public function setSize($sizeInPoints, bool $nullOk = false)
 378      {
 379          if (is_string($sizeInPoints) || is_int($sizeInPoints)) {
 380              $sizeInPoints = (float) $sizeInPoints; // $pValue = 0 if given string is not numeric
 381          }
 382  
 383          // Size must be a positive floating point number
 384          // ECMA-376-1:2016, part 1, chapter 18.4.11 sz (Font Size), p. 1536
 385          if (!is_float($sizeInPoints) || !($sizeInPoints > 0)) {
 386              if (!$nullOk || $sizeInPoints !== null) {
 387                  $sizeInPoints = 10.0;
 388              }
 389          }
 390  
 391          if ($this->isSupervisor) {
 392              $styleArray = $this->getStyleArray(['size' => $sizeInPoints]);
 393              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 394          } else {
 395              $this->size = $sizeInPoints;
 396          }
 397  
 398          return $this;
 399      }
 400  
 401      /**
 402       * Get Bold.
 403       *
 404       * @return null|bool
 405       */
 406      public function getBold()
 407      {
 408          if ($this->isSupervisor) {
 409              return $this->getSharedComponent()->getBold();
 410          }
 411  
 412          return $this->bold;
 413      }
 414  
 415      /**
 416       * Set Bold.
 417       *
 418       * @param bool $bold
 419       *
 420       * @return $this
 421       */
 422      public function setBold($bold)
 423      {
 424          if ($bold == '') {
 425              $bold = false;
 426          }
 427          if ($this->isSupervisor) {
 428              $styleArray = $this->getStyleArray(['bold' => $bold]);
 429              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 430          } else {
 431              $this->bold = $bold;
 432          }
 433  
 434          return $this;
 435      }
 436  
 437      /**
 438       * Get Italic.
 439       *
 440       * @return null|bool
 441       */
 442      public function getItalic()
 443      {
 444          if ($this->isSupervisor) {
 445              return $this->getSharedComponent()->getItalic();
 446          }
 447  
 448          return $this->italic;
 449      }
 450  
 451      /**
 452       * Set Italic.
 453       *
 454       * @param bool $italic
 455       *
 456       * @return $this
 457       */
 458      public function setItalic($italic)
 459      {
 460          if ($italic == '') {
 461              $italic = false;
 462          }
 463          if ($this->isSupervisor) {
 464              $styleArray = $this->getStyleArray(['italic' => $italic]);
 465              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 466          } else {
 467              $this->italic = $italic;
 468          }
 469  
 470          return $this;
 471      }
 472  
 473      /**
 474       * Get Superscript.
 475       *
 476       * @return null|bool
 477       */
 478      public function getSuperscript()
 479      {
 480          if ($this->isSupervisor) {
 481              return $this->getSharedComponent()->getSuperscript();
 482          }
 483  
 484          return $this->superscript;
 485      }
 486  
 487      /**
 488       * Set Superscript.
 489       *
 490       * @return $this
 491       */
 492      public function setSuperscript(bool $superscript)
 493      {
 494          if ($this->isSupervisor) {
 495              $styleArray = $this->getStyleArray(['superscript' => $superscript]);
 496              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 497          } else {
 498              $this->superscript = $superscript;
 499              if ($this->superscript) {
 500                  $this->subscript = false;
 501              }
 502          }
 503  
 504          return $this;
 505      }
 506  
 507      /**
 508       * Get Subscript.
 509       *
 510       * @return null|bool
 511       */
 512      public function getSubscript()
 513      {
 514          if ($this->isSupervisor) {
 515              return $this->getSharedComponent()->getSubscript();
 516          }
 517  
 518          return $this->subscript;
 519      }
 520  
 521      /**
 522       * Set Subscript.
 523       *
 524       * @return $this
 525       */
 526      public function setSubscript(bool $subscript)
 527      {
 528          if ($this->isSupervisor) {
 529              $styleArray = $this->getStyleArray(['subscript' => $subscript]);
 530              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 531          } else {
 532              $this->subscript = $subscript;
 533              if ($this->subscript) {
 534                  $this->superscript = false;
 535              }
 536          }
 537  
 538          return $this;
 539      }
 540  
 541      public function getBaseLine(): int
 542      {
 543          if ($this->isSupervisor) {
 544              return $this->getSharedComponent()->getBaseLine();
 545          }
 546  
 547          return $this->baseLine;
 548      }
 549  
 550      public function setBaseLine(int $baseLine): self
 551      {
 552          if (!$this->isSupervisor) {
 553              $this->baseLine = $baseLine;
 554          } else {
 555              // should never be true
 556              // @codeCoverageIgnoreStart
 557              $styleArray = $this->getStyleArray(['baseLine' => $baseLine]);
 558              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 559              // @codeCoverageIgnoreEnd
 560          }
 561  
 562          return $this;
 563      }
 564  
 565      public function getStrikeType(): string
 566      {
 567          if ($this->isSupervisor) {
 568              return $this->getSharedComponent()->getStrikeType();
 569          }
 570  
 571          return $this->strikeType;
 572      }
 573  
 574      public function setStrikeType(string $strikeType): self
 575      {
 576          if (!$this->isSupervisor) {
 577              $this->strikeType = $strikeType;
 578          } else {
 579              // should never be true
 580              // @codeCoverageIgnoreStart
 581              $styleArray = $this->getStyleArray(['strikeType' => $strikeType]);
 582              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 583              // @codeCoverageIgnoreEnd
 584          }
 585  
 586          return $this;
 587      }
 588  
 589      public function getUnderlineColor(): ?ChartColor
 590      {
 591          if ($this->isSupervisor) {
 592              return $this->getSharedComponent()->getUnderlineColor();
 593          }
 594  
 595          return $this->underlineColor;
 596      }
 597  
 598      public function setUnderlineColor(array $colorArray): self
 599      {
 600          if (!$this->isSupervisor) {
 601              $this->underlineColor = new ChartColor($colorArray);
 602          } else {
 603              // should never be true
 604              // @codeCoverageIgnoreStart
 605              $styleArray = $this->getStyleArray(['underlineColor' => $colorArray]);
 606              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 607              // @codeCoverageIgnoreEnd
 608          }
 609  
 610          return $this;
 611      }
 612  
 613      public function getChartColor(): ?ChartColor
 614      {
 615          if ($this->isSupervisor) {
 616              return $this->getSharedComponent()->getChartColor();
 617          }
 618  
 619          return $this->chartColor;
 620      }
 621  
 622      public function setChartColor(array $colorArray): self
 623      {
 624          if (!$this->isSupervisor) {
 625              $this->chartColor = new ChartColor($colorArray);
 626          } else {
 627              // should never be true
 628              // @codeCoverageIgnoreStart
 629              $styleArray = $this->getStyleArray(['chartColor' => $colorArray]);
 630              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 631              // @codeCoverageIgnoreEnd
 632          }
 633  
 634          return $this;
 635      }
 636  
 637      /**
 638       * Get Underline.
 639       *
 640       * @return null|string
 641       */
 642      public function getUnderline()
 643      {
 644          if ($this->isSupervisor) {
 645              return $this->getSharedComponent()->getUnderline();
 646          }
 647  
 648          return $this->underline;
 649      }
 650  
 651      /**
 652       * Set Underline.
 653       *
 654       * @param bool|string $underlineStyle \PhpOffice\PhpSpreadsheet\Style\Font underline type
 655       *                                    If a boolean is passed, then TRUE equates to UNDERLINE_SINGLE,
 656       *                                        false equates to UNDERLINE_NONE
 657       *
 658       * @return $this
 659       */
 660      public function setUnderline($underlineStyle)
 661      {
 662          if (is_bool($underlineStyle)) {
 663              $underlineStyle = ($underlineStyle) ? self::UNDERLINE_SINGLE : self::UNDERLINE_NONE;
 664          } elseif ($underlineStyle == '') {
 665              $underlineStyle = self::UNDERLINE_NONE;
 666          }
 667          if ($this->isSupervisor) {
 668              $styleArray = $this->getStyleArray(['underline' => $underlineStyle]);
 669              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 670          } else {
 671              $this->underline = $underlineStyle;
 672          }
 673  
 674          return $this;
 675      }
 676  
 677      /**
 678       * Get Strikethrough.
 679       *
 680       * @return null|bool
 681       */
 682      public function getStrikethrough()
 683      {
 684          if ($this->isSupervisor) {
 685              return $this->getSharedComponent()->getStrikethrough();
 686          }
 687  
 688          return $this->strikethrough;
 689      }
 690  
 691      /**
 692       * Set Strikethrough.
 693       *
 694       * @param bool $strikethru
 695       *
 696       * @return $this
 697       */
 698      public function setStrikethrough($strikethru)
 699      {
 700          if ($strikethru == '') {
 701              $strikethru = false;
 702          }
 703  
 704          if ($this->isSupervisor) {
 705              $styleArray = $this->getStyleArray(['strikethrough' => $strikethru]);
 706              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 707          } else {
 708              $this->strikethrough = $strikethru;
 709          }
 710  
 711          return $this;
 712      }
 713  
 714      /**
 715       * Get Color.
 716       *
 717       * @return Color
 718       */
 719      public function getColor()
 720      {
 721          return $this->color;
 722      }
 723  
 724      /**
 725       * Set Color.
 726       *
 727       * @return $this
 728       */
 729      public function setColor(Color $color)
 730      {
 731          // make sure parameter is a real color and not a supervisor
 732          $color = $color->getIsSupervisor() ? $color->getSharedComponent() : $color;
 733  
 734          if ($this->isSupervisor) {
 735              $styleArray = $this->getColor()->getStyleArray(['argb' => $color->getARGB()]);
 736              $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray);
 737          } else {
 738              $this->color = $color;
 739          }
 740  
 741          return $this;
 742      }
 743  
 744      private function hashChartColor(?ChartColor $underlineColor): string
 745      {
 746          if ($underlineColor === null) {
 747              return '';
 748          }
 749  
 750          return
 751              $underlineColor->getValue()
 752              . $underlineColor->getType()
 753              . (string) $underlineColor->getAlpha();
 754      }
 755  
 756      /**
 757       * Get hash code.
 758       *
 759       * @return string Hash code
 760       */
 761      public function getHashCode()
 762      {
 763          if ($this->isSupervisor) {
 764              return $this->getSharedComponent()->getHashCode();
 765          }
 766  
 767          return md5(
 768              $this->name .
 769              $this->size .
 770              ($this->bold ? 't' : 'f') .
 771              ($this->italic ? 't' : 'f') .
 772              ($this->superscript ? 't' : 'f') .
 773              ($this->subscript ? 't' : 'f') .
 774              $this->underline .
 775              ($this->strikethrough ? 't' : 'f') .
 776              $this->color->getHashCode() .
 777              implode(
 778                  '*',
 779                  [
 780                      $this->latin,
 781                      $this->eastAsian,
 782                      $this->complexScript,
 783                      $this->strikeType,
 784                      $this->hashChartColor($this->chartColor),
 785                      $this->hashChartColor($this->underlineColor),
 786                      (string) $this->baseLine,
 787                  ]
 788              ) .
 789              __CLASS__
 790          );
 791      }
 792  
 793      protected function exportArray1(): array
 794      {
 795          $exportedArray = [];
 796          $this->exportArray2($exportedArray, 'baseLine', $this->getBaseLine());
 797          $this->exportArray2($exportedArray, 'bold', $this->getBold());
 798          $this->exportArray2($exportedArray, 'chartColor', $this->getChartColor());
 799          $this->exportArray2($exportedArray, 'color', $this->getColor());
 800          $this->exportArray2($exportedArray, 'complexScript', $this->getComplexScript());
 801          $this->exportArray2($exportedArray, 'eastAsian', $this->getEastAsian());
 802          $this->exportArray2($exportedArray, 'italic', $this->getItalic());
 803          $this->exportArray2($exportedArray, 'latin', $this->getLatin());
 804          $this->exportArray2($exportedArray, 'name', $this->getName());
 805          $this->exportArray2($exportedArray, 'size', $this->getSize());
 806          $this->exportArray2($exportedArray, 'strikethrough', $this->getStrikethrough());
 807          $this->exportArray2($exportedArray, 'strikeType', $this->getStrikeType());
 808          $this->exportArray2($exportedArray, 'subscript', $this->getSubscript());
 809          $this->exportArray2($exportedArray, 'superscript', $this->getSuperscript());
 810          $this->exportArray2($exportedArray, 'underline', $this->getUnderline());
 811          $this->exportArray2($exportedArray, 'underlineColor', $this->getUnderlineColor());
 812  
 813          return $exportedArray;
 814      }
 815  }