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 311 and 402] [Versions 400 and 402] [Versions 401 and 402]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Reader\Ods;
   4  
   5  use DOMDocument;
   6  use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
   7  use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
   8  
   9  class PageSettings
  10  {
  11      /**
  12       * @var string
  13       */
  14      private $officeNs;
  15  
  16      /**
  17       * @var string
  18       */
  19      private $stylesNs;
  20  
  21      /**
  22       * @var string
  23       */
  24      private $stylesFo;
  25  
  26      /**
  27       * @var string
  28       */
  29      private $tableNs;
  30  
  31      /**
  32       * @var string[]
  33       */
  34      private $tableStylesCrossReference = [];
  35  
  36      /** @var array */
  37      private $pageLayoutStyles = [];
  38  
  39      /**
  40       * @var string[]
  41       */
  42      private $masterStylesCrossReference = [];
  43  
  44      /**
  45       * @var string[]
  46       */
  47      private $masterPrintStylesCrossReference = [];
  48  
  49      public function __construct(DOMDocument $styleDom)
  50      {
  51          $this->setDomNameSpaces($styleDom);
  52          $this->readPageSettingStyles($styleDom);
  53          $this->readStyleMasterLookup($styleDom);
  54      }
  55  
  56      private function setDomNameSpaces(DOMDocument $styleDom): void
  57      {
  58          $this->officeNs = $styleDom->lookupNamespaceUri('office');
  59          $this->stylesNs = $styleDom->lookupNamespaceUri('style');
  60          $this->stylesFo = $styleDom->lookupNamespaceUri('fo');
  61          $this->tableNs = $styleDom->lookupNamespaceUri('table');
  62      }
  63  
  64      private function readPageSettingStyles(DOMDocument $styleDom): void
  65      {
  66          $item0 = $styleDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')->item(0);
  67          $styles = ($item0 === null) ? [] : $item0->getElementsByTagNameNS($this->stylesNs, 'page-layout');
  68  
  69          foreach ($styles as $styleSet) {
  70              $styleName = $styleSet->getAttributeNS($this->stylesNs, 'name');
  71              $pageLayoutProperties = $styleSet->getElementsByTagNameNS($this->stylesNs, 'page-layout-properties')[0];
  72              $styleOrientation = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-orientation');
  73              $styleScale = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'scale-to');
  74              $stylePrintOrder = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'print-page-order');
  75              $centered = $pageLayoutProperties->getAttributeNS($this->stylesNs, 'table-centering');
  76  
  77              $marginLeft = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-left');
  78              $marginRight = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-right');
  79              $marginTop = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-top');
  80              $marginBottom = $pageLayoutProperties->getAttributeNS($this->stylesFo, 'margin-bottom');
  81              $header = $styleSet->getElementsByTagNameNS($this->stylesNs, 'header-style')[0];
  82              $headerProperties = $header->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0];
  83              $marginHeader = isset($headerProperties) ? $headerProperties->getAttributeNS($this->stylesFo, 'min-height') : null;
  84              $footer = $styleSet->getElementsByTagNameNS($this->stylesNs, 'footer-style')[0];
  85              $footerProperties = $footer->getElementsByTagNameNS($this->stylesNs, 'header-footer-properties')[0];
  86              $marginFooter = isset($footerProperties) ? $footerProperties->getAttributeNS($this->stylesFo, 'min-height') : null;
  87  
  88              $this->pageLayoutStyles[$styleName] = (object) [
  89                  'orientation' => $styleOrientation ?: PageSetup::ORIENTATION_DEFAULT,
  90                  'scale' => $styleScale ?: 100,
  91                  'printOrder' => $stylePrintOrder,
  92                  'horizontalCentered' => $centered === 'horizontal' || $centered === 'both',
  93                  'verticalCentered' => $centered === 'vertical' || $centered === 'both',
  94                  // margin size is already stored in inches, so no UOM conversion is required
  95                  'marginLeft' => (float) ($marginLeft ?? 0.7),
  96                  'marginRight' => (float) ($marginRight ?? 0.7),
  97                  'marginTop' => (float) ($marginTop ?? 0.3),
  98                  'marginBottom' => (float) ($marginBottom ?? 0.3),
  99                  'marginHeader' => (float) ($marginHeader ?? 0.45),
 100                  'marginFooter' => (float) ($marginFooter ?? 0.45),
 101              ];
 102          }
 103      }
 104  
 105      private function readStyleMasterLookup(DOMDocument $styleDom): void
 106      {
 107          $item0 = $styleDom->getElementsByTagNameNS($this->officeNs, 'master-styles')->item(0);
 108          $styleMasterLookup = ($item0 === null) ? [] : $item0->getElementsByTagNameNS($this->stylesNs, 'master-page');
 109  
 110          foreach ($styleMasterLookup as $styleMasterSet) {
 111              $styleMasterName = $styleMasterSet->getAttributeNS($this->stylesNs, 'name');
 112              $pageLayoutName = $styleMasterSet->getAttributeNS($this->stylesNs, 'page-layout-name');
 113              $this->masterPrintStylesCrossReference[$styleMasterName] = $pageLayoutName;
 114          }
 115      }
 116  
 117      public function readStyleCrossReferences(DOMDocument $contentDom): void
 118      {
 119          $item0 = $contentDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')->item(0);
 120          $styleXReferences = ($item0 === null) ? [] : $item0->getElementsByTagNameNS($this->stylesNs, 'style');
 121  
 122          foreach ($styleXReferences as $styleXreferenceSet) {
 123              $styleXRefName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'name');
 124              $stylePageLayoutName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'master-page-name');
 125              $styleFamilyName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'family');
 126              if (!empty($styleFamilyName) && $styleFamilyName === 'table') {
 127                  $styleVisibility = 'true';
 128                  foreach ($styleXreferenceSet->getElementsByTagNameNS($this->stylesNs, 'table-properties') as $tableProperties) {
 129                      $styleVisibility = $tableProperties->getAttributeNS($this->tableNs, 'display');
 130                  }
 131                  $this->tableStylesCrossReference[$styleXRefName] = $styleVisibility;
 132              }
 133              if (!empty($stylePageLayoutName)) {
 134                  $this->masterStylesCrossReference[$styleXRefName] = $stylePageLayoutName;
 135              }
 136          }
 137      }
 138  
 139      public function setVisibilityForWorksheet(Worksheet $worksheet, string $styleName): void
 140      {
 141          if (!array_key_exists($styleName, $this->tableStylesCrossReference)) {
 142              return;
 143          }
 144  
 145          $worksheet->setSheetState(
 146              $this->tableStylesCrossReference[$styleName] === 'false'
 147                  ? Worksheet::SHEETSTATE_HIDDEN
 148                  : Worksheet::SHEETSTATE_VISIBLE
 149          );
 150      }
 151  
 152      public function setPrintSettingsForWorksheet(Worksheet $worksheet, string $styleName): void
 153      {
 154          if (!array_key_exists($styleName, $this->masterStylesCrossReference)) {
 155              return;
 156          }
 157          $masterStyleName = $this->masterStylesCrossReference[$styleName];
 158  
 159          if (!array_key_exists($masterStyleName, $this->masterPrintStylesCrossReference)) {
 160              return;
 161          }
 162          $printSettingsIndex = $this->masterPrintStylesCrossReference[$masterStyleName];
 163  
 164          if (!array_key_exists($printSettingsIndex, $this->pageLayoutStyles)) {
 165              return;
 166          }
 167          $printSettings = $this->pageLayoutStyles[$printSettingsIndex];
 168  
 169          $worksheet->getPageSetup()
 170              ->setOrientation($printSettings->orientation ?? PageSetup::ORIENTATION_DEFAULT)
 171              ->setPageOrder($printSettings->printOrder === 'ltr' ? PageSetup::PAGEORDER_OVER_THEN_DOWN : PageSetup::PAGEORDER_DOWN_THEN_OVER)
 172              ->setScale((int) trim($printSettings->scale, '%'))
 173              ->setHorizontalCentered($printSettings->horizontalCentered)
 174              ->setVerticalCentered($printSettings->verticalCentered);
 175  
 176          $worksheet->getPageMargins()
 177              ->setLeft($printSettings->marginLeft)
 178              ->setRight($printSettings->marginRight)
 179              ->setTop($printSettings->marginTop)
 180              ->setBottom($printSettings->marginBottom)
 181              ->setHeader($printSettings->marginHeader)
 182              ->setFooter($printSettings->marginFooter);
 183      }
 184  }