Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401]

   1  <?php
   2  
   3  namespace Box\Spout\Writer\ODS\Manager\Style;
   4  
   5  use Box\Spout\Common\Entity\Style\BorderPart;
   6  use Box\Spout\Writer\Common\Entity\Worksheet;
   7  use Box\Spout\Writer\ODS\Helper\BorderHelper;
   8  
   9  /**
  10   * Class StyleManager
  11   * Manages styles to be applied to a cell
  12   */
  13  class StyleManager extends \Box\Spout\Writer\Common\Manager\Style\StyleManager
  14  {
  15      /** @var StyleRegistry */
  16      protected $styleRegistry;
  17  
  18      /**
  19       * Returns the content of the "styles.xml" file, given a list of styles.
  20       *
  21       * @param int $numWorksheets Number of worksheets created
  22       * @return string
  23       */
  24      public function getStylesXMLFileContent($numWorksheets)
  25      {
  26          $content = <<<'EOD'
  27  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  28  <office:document-styles office:version="1.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:msoxl="http://schemas.microsoft.com/office/excel/formula" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xlink="http://www.w3.org/1999/xlink">
  29  EOD;
  30  
  31          $content .= $this->getFontFaceSectionContent();
  32          $content .= $this->getStylesSectionContent();
  33          $content .= $this->getAutomaticStylesSectionContent($numWorksheets);
  34          $content .= $this->getMasterStylesSectionContent($numWorksheets);
  35  
  36          $content .= <<<'EOD'
  37  </office:document-styles>
  38  EOD;
  39  
  40          return $content;
  41      }
  42  
  43      /**
  44       * Returns the content of the "<office:font-face-decls>" section, inside "styles.xml" file.
  45       *
  46       * @return string
  47       */
  48      protected function getFontFaceSectionContent()
  49      {
  50          $content = '<office:font-face-decls>';
  51          foreach ($this->styleRegistry->getUsedFonts() as $fontName) {
  52              $content .= '<style:font-face style:name="' . $fontName . '" svg:font-family="' . $fontName . '"/>';
  53          }
  54          $content .= '</office:font-face-decls>';
  55  
  56          return $content;
  57      }
  58  
  59      /**
  60       * Returns the content of the "<office:styles>" section, inside "styles.xml" file.
  61       *
  62       * @return string
  63       */
  64      protected function getStylesSectionContent()
  65      {
  66          $defaultStyle = $this->getDefaultStyle();
  67  
  68          return <<<EOD
  69  <office:styles>
  70      <number:number-style style:name="N0">
  71          <number:number number:min-integer-digits="1"/>
  72      </number:number-style>
  73      <style:style style:data-style-name="N0" style:family="table-cell" style:name="Default">
  74          <style:table-cell-properties fo:background-color="transparent" style:vertical-align="automatic"/>
  75          <style:text-properties fo:color="#{$defaultStyle->getFontColor()}"
  76                                 fo:font-size="{$defaultStyle->getFontSize()}pt" style:font-size-asian="{$defaultStyle->getFontSize()}pt" style:font-size-complex="{$defaultStyle->getFontSize()}pt"
  77                                 style:font-name="{$defaultStyle->getFontName()}" style:font-name-asian="{$defaultStyle->getFontName()}" style:font-name-complex="{$defaultStyle->getFontName()}"/>
  78      </style:style>
  79  </office:styles>
  80  EOD;
  81      }
  82  
  83      /**
  84       * Returns the content of the "<office:automatic-styles>" section, inside "styles.xml" file.
  85       *
  86       * @param int $numWorksheets Number of worksheets created
  87       * @return string
  88       */
  89      protected function getAutomaticStylesSectionContent($numWorksheets)
  90      {
  91          $content = '<office:automatic-styles>';
  92  
  93          for ($i = 1; $i <= $numWorksheets; $i++) {
  94              $content .= <<<EOD
  95  <style:page-layout style:name="pm$i">
  96      <style:page-layout-properties style:first-page-number="continue" style:print="objects charts drawings" style:table-centering="none"/>
  97      <style:header-style/>
  98      <style:footer-style/>
  99  </style:page-layout>
 100  EOD;
 101          }
 102  
 103          $content .= '</office:automatic-styles>';
 104  
 105          return $content;
 106      }
 107  
 108      /**
 109       * Returns the content of the "<office:master-styles>" section, inside "styles.xml" file.
 110       *
 111       * @param int $numWorksheets Number of worksheets created
 112       * @return string
 113       */
 114      protected function getMasterStylesSectionContent($numWorksheets)
 115      {
 116          $content = '<office:master-styles>';
 117  
 118          for ($i = 1; $i <= $numWorksheets; $i++) {
 119              $content .= <<<EOD
 120  <style:master-page style:name="mp$i" style:page-layout-name="pm$i">
 121      <style:header/>
 122      <style:header-left style:display="false"/>
 123      <style:footer/>
 124      <style:footer-left style:display="false"/>
 125  </style:master-page>
 126  EOD;
 127          }
 128  
 129          $content .= '</office:master-styles>';
 130  
 131          return $content;
 132      }
 133  
 134      /**
 135       * Returns the contents of the "<office:font-face-decls>" section, inside "content.xml" file.
 136       *
 137       * @return string
 138       */
 139      public function getContentXmlFontFaceSectionContent()
 140      {
 141          $content = '<office:font-face-decls>';
 142          foreach ($this->styleRegistry->getUsedFonts() as $fontName) {
 143              $content .= '<style:font-face style:name="' . $fontName . '" svg:font-family="' . $fontName . '"/>';
 144          }
 145          $content .= '</office:font-face-decls>';
 146  
 147          return $content;
 148      }
 149  
 150      /**
 151       * Returns the contents of the "<office:automatic-styles>" section, inside "content.xml" file.
 152       *
 153       * @param Worksheet[] $worksheets
 154       * @return string
 155       */
 156      public function getContentXmlAutomaticStylesSectionContent($worksheets)
 157      {
 158          $content = '<office:automatic-styles>';
 159  
 160          foreach ($this->styleRegistry->getRegisteredStyles() as $style) {
 161              $content .= $this->getStyleSectionContent($style);
 162          }
 163  
 164          $content .= <<<'EOD'
 165  <style:style style:family="table-column" style:name="co1">
 166      <style:table-column-properties fo:break-before="auto"/>
 167  </style:style>
 168  <style:style style:family="table-row" style:name="ro1">
 169      <style:table-row-properties fo:break-before="auto" style:row-height="15pt" style:use-optimal-row-height="true"/>
 170  </style:style>
 171  EOD;
 172  
 173          foreach ($worksheets as $worksheet) {
 174              $worksheetId = $worksheet->getId();
 175              $isSheetVisible = $worksheet->getExternalSheet()->isVisible() ? 'true' : 'false';
 176  
 177              $content .= <<<EOD
 178  <style:style style:family="table" style:master-page-name="mp$worksheetId" style:name="ta$worksheetId">
 179      <style:table-properties style:writing-mode="lr-tb" table:display="$isSheetVisible"/>
 180  </style:style>
 181  EOD;
 182          }
 183  
 184          $content .= '</office:automatic-styles>';
 185  
 186          return $content;
 187      }
 188  
 189      /**
 190       * Returns the contents of the "<style:style>" section, inside "<office:automatic-styles>" section
 191       *
 192       * @param \Box\Spout\Common\Entity\Style\Style $style
 193       * @return string
 194       */
 195      protected function getStyleSectionContent($style)
 196      {
 197          $styleIndex = $style->getId() + 1; // 1-based
 198  
 199          $content = '<style:style style:data-style-name="N0" style:family="table-cell" style:name="ce' . $styleIndex . '" style:parent-style-name="Default">';
 200  
 201          $content .= $this->getTextPropertiesSectionContent($style);
 202          $content .= $this->getTableCellPropertiesSectionContent($style);
 203  
 204          $content .= '</style:style>';
 205  
 206          return $content;
 207      }
 208  
 209      /**
 210       * Returns the contents of the "<style:text-properties>" section, inside "<style:style>" section
 211       *
 212       * @param \Box\Spout\Common\Entity\Style\Style $style
 213       * @return string
 214       */
 215      private function getTextPropertiesSectionContent($style)
 216      {
 217          $content = '';
 218  
 219          if ($style->shouldApplyFont()) {
 220              $content .= $this->getFontSectionContent($style);
 221          }
 222  
 223          return $content;
 224      }
 225  
 226      /**
 227       * Returns the contents of the "<style:text-properties>" section, inside "<style:style>" section
 228       *
 229       * @param \Box\Spout\Common\Entity\Style\Style $style
 230       * @return string
 231       */
 232      private function getFontSectionContent($style)
 233      {
 234          $defaultStyle = $this->getDefaultStyle();
 235  
 236          $content = '<style:text-properties';
 237  
 238          $fontColor = $style->getFontColor();
 239          if ($fontColor !== $defaultStyle->getFontColor()) {
 240              $content .= ' fo:color="#' . $fontColor . '"';
 241          }
 242  
 243          $fontName = $style->getFontName();
 244          if ($fontName !== $defaultStyle->getFontName()) {
 245              $content .= ' style:font-name="' . $fontName . '" style:font-name-asian="' . $fontName . '" style:font-name-complex="' . $fontName . '"';
 246          }
 247  
 248          $fontSize = $style->getFontSize();
 249          if ($fontSize !== $defaultStyle->getFontSize()) {
 250              $content .= ' fo:font-size="' . $fontSize . 'pt" style:font-size-asian="' . $fontSize . 'pt" style:font-size-complex="' . $fontSize . 'pt"';
 251          }
 252  
 253          if ($style->isFontBold()) {
 254              $content .= ' fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"';
 255          }
 256          if ($style->isFontItalic()) {
 257              $content .= ' fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"';
 258          }
 259          if ($style->isFontUnderline()) {
 260              $content .= ' style:text-underline-style="solid" style:text-underline-type="single"';
 261          }
 262          if ($style->isFontStrikethrough()) {
 263              $content .= ' style:text-line-through-style="solid"';
 264          }
 265  
 266          $content .= '/>';
 267  
 268          return $content;
 269      }
 270  
 271      /**
 272       * Returns the contents of the "<style:table-cell-properties>" section, inside "<style:style>" section
 273       *
 274       * @param \Box\Spout\Common\Entity\Style\Style $style
 275       * @return string
 276       */
 277      private function getTableCellPropertiesSectionContent($style)
 278      {
 279          $content = '';
 280  
 281          if ($style->shouldWrapText()) {
 282              $content .= $this->getWrapTextXMLContent();
 283          }
 284  
 285          if ($style->shouldApplyBorder()) {
 286              $content .= $this->getBorderXMLContent($style);
 287          }
 288  
 289          if ($style->shouldApplyBackgroundColor()) {
 290              $content .= $this->getBackgroundColorXMLContent($style);
 291          }
 292  
 293          return $content;
 294      }
 295  
 296      /**
 297       * Returns the contents of the wrap text definition for the "<style:table-cell-properties>" section
 298       *
 299       * @return string
 300       */
 301      private function getWrapTextXMLContent()
 302      {
 303          return '<style:table-cell-properties fo:wrap-option="wrap" style:vertical-align="automatic"/>';
 304      }
 305  
 306      /**
 307       * Returns the contents of the borders definition for the "<style:table-cell-properties>" section
 308       *
 309       * @param \Box\Spout\Common\Entity\Style\Style $style
 310       * @return string
 311       */
 312      private function getBorderXMLContent($style)
 313      {
 314          $borderProperty = '<style:table-cell-properties %s />';
 315  
 316          $borders = array_map(function (BorderPart $borderPart) {
 317              return BorderHelper::serializeBorderPart($borderPart);
 318          }, $style->getBorder()->getParts());
 319  
 320          return sprintf($borderProperty, implode(' ', $borders));
 321      }
 322  
 323      /**
 324       * Returns the contents of the background color definition for the "<style:table-cell-properties>" section
 325       *
 326       * @param \Box\Spout\Common\Entity\Style\Style $style
 327       * @return string
 328       */
 329      private function getBackgroundColorXMLContent($style)
 330      {
 331          return sprintf(
 332              '<style:table-cell-properties fo:background-color="#%s"/>',
 333              $style->getBackgroundColor()
 334          );
 335      }
 336  }