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

   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      private $pageLayoutStyles = [];
  37  
  38      /**
  39       * @var string[]
  40       */
  41      private $masterStylesCrossReference = [];
  42  
  43      /**
  44       * @var string[]
  45       */
  46      private $masterPrintStylesCrossReference = [];
  47  
  48      public function __construct(DOMDocument $styleDom)
  49      {
  50          $this->setDomNameSpaces($styleDom);
  51          $this->readPageSettingStyles($styleDom);
  52          $this->readStyleMasterLookup($styleDom);
  53      }
  54  
  55      private function setDomNameSpaces(DOMDocument $styleDom): void
  56      {
  57          $this->officeNs = $styleDom->lookupNamespaceUri('office');
  58          $this->stylesNs = $styleDom->lookupNamespaceUri('style');
  59          $this->stylesFo = $styleDom->lookupNamespaceUri('fo');
  60          $this->tableNs = $styleDom->lookupNamespaceUri('table');
  61      }
  62  
  63      private function readPageSettingStyles(DOMDocument $styleDom): void
  64      {
  65          $styles = $styleDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')
  66              ->item(0)
  67              ->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          $styleMasterLookup = $styleDom->getElementsByTagNameNS($this->officeNs, 'master-styles')
 108              ->item(0)
 109              ->getElementsByTagNameNS($this->stylesNs, 'master-page');
 110  
 111          foreach ($styleMasterLookup as $styleMasterSet) {
 112              $styleMasterName = $styleMasterSet->getAttributeNS($this->stylesNs, 'name');
 113              $pageLayoutName = $styleMasterSet->getAttributeNS($this->stylesNs, 'page-layout-name');
 114              $this->masterPrintStylesCrossReference[$styleMasterName] = $pageLayoutName;
 115          }
 116      }
 117  
 118      public function readStyleCrossReferences(DOMDocument $contentDom): void
 119      {
 120          $styleXReferences = $contentDom->getElementsByTagNameNS($this->officeNs, 'automatic-styles')
 121              ->item(0)
 122              ->getElementsByTagNameNS($this->stylesNs, 'style');
 123  
 124          foreach ($styleXReferences as $styleXreferenceSet) {
 125              $styleXRefName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'name');
 126              $stylePageLayoutName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'master-page-name');
 127              $styleFamilyName = $styleXreferenceSet->getAttributeNS($this->stylesNs, 'family');
 128              if (!empty($styleFamilyName) && $styleFamilyName === 'table') {
 129                  $styleVisibility = 'true';
 130                  foreach ($styleXreferenceSet->getElementsByTagNameNS($this->stylesNs, 'table-properties') as $tableProperties) {
 131                      $styleVisibility = $tableProperties->getAttributeNS($this->tableNs, 'display');
 132                  }
 133                  $this->tableStylesCrossReference[$styleXRefName] = $styleVisibility;
 134              }
 135              if (!empty($stylePageLayoutName)) {
 136                  $this->masterStylesCrossReference[$styleXRefName] = $stylePageLayoutName;
 137              }
 138          }
 139      }
 140  
 141      public function setVisibilityForWorksheet(Worksheet $worksheet, string $styleName): void
 142      {
 143          if (!array_key_exists($styleName, $this->tableStylesCrossReference)) {
 144              return;
 145          }
 146  
 147          $worksheet->setSheetState(
 148              $this->tableStylesCrossReference[$styleName] === 'false'
 149                  ? Worksheet::SHEETSTATE_HIDDEN
 150                  : Worksheet::SHEETSTATE_VISIBLE
 151          );
 152      }
 153  
 154      public function setPrintSettingsForWorksheet(Worksheet $worksheet, string $styleName): void
 155      {
 156          if (!array_key_exists($styleName, $this->masterStylesCrossReference)) {
 157              return;
 158          }
 159          $masterStyleName = $this->masterStylesCrossReference[$styleName];
 160  
 161          if (!array_key_exists($masterStyleName, $this->masterPrintStylesCrossReference)) {
 162              return;
 163          }
 164          $printSettingsIndex = $this->masterPrintStylesCrossReference[$masterStyleName];
 165  
 166          if (!array_key_exists($printSettingsIndex, $this->pageLayoutStyles)) {
 167              return;
 168          }
 169          $printSettings = $this->pageLayoutStyles[$printSettingsIndex];
 170  
 171          $worksheet->getPageSetup()
 172              ->setOrientation($printSettings->orientation ?? PageSetup::ORIENTATION_DEFAULT)
 173              ->setPageOrder($printSettings->printOrder === 'ltr' ? PageSetup::PAGEORDER_OVER_THEN_DOWN : PageSetup::PAGEORDER_DOWN_THEN_OVER)
 174              ->setScale((int) trim($printSettings->scale, '%'))
 175              ->setHorizontalCentered($printSettings->horizontalCentered)
 176              ->setVerticalCentered($printSettings->verticalCentered);
 177  
 178          $worksheet->getPageMargins()
 179              ->setLeft($printSettings->marginLeft)
 180              ->setRight($printSettings->marginRight)
 181              ->setTop($printSettings->marginTop)
 182              ->setBottom($printSettings->marginBottom)
 183              ->setHeader($printSettings->marginHeader)
 184              ->setFooter($printSettings->marginFooter);
 185      }
 186  }