Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Reader\Xml;
   4  
   5  use PhpOffice\PhpSpreadsheet\Document\Properties as DocumentProperties;
   6  use PhpOffice\PhpSpreadsheet\Spreadsheet;
   7  use SimpleXMLElement;
   8  
   9  class Properties
  10  {
  11      /**
  12       * @var Spreadsheet
  13       */
  14      protected $spreadsheet;
  15  
  16      public function __construct(Spreadsheet $spreadsheet)
  17      {
  18          $this->spreadsheet = $spreadsheet;
  19      }
  20  
  21      public function readProperties(SimpleXMLElement $xml, array $namespaces): void
  22      {
  23          $this->readStandardProperties($xml);
  24          $this->readCustomProperties($xml, $namespaces);
  25      }
  26  
  27      protected function readStandardProperties(SimpleXMLElement $xml): void
  28      {
  29          if (isset($xml->DocumentProperties[0])) {
  30              $docProps = $this->spreadsheet->getProperties();
  31  
  32              foreach ($xml->DocumentProperties[0] as $propertyName => $propertyValue) {
  33                  $propertyValue = (string) $propertyValue;
  34  
  35                  $this->processStandardProperty($docProps, $propertyName, $propertyValue);
  36              }
  37          }
  38      }
  39  
  40      protected function readCustomProperties(SimpleXMLElement $xml, array $namespaces): void
  41      {
  42          if (isset($xml->CustomDocumentProperties)) {
  43              $docProps = $this->spreadsheet->getProperties();
  44  
  45              foreach ($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) {
  46                  $propertyAttributes = self::getAttributes($propertyValue, $namespaces['dt']);
  47                  $propertyName = preg_replace_callback('/_x([0-9a-f]{4})_/i', [$this, 'hex2str'], $propertyName);
  48  
  49                  $this->processCustomProperty($docProps, $propertyName, $propertyValue, $propertyAttributes);
  50              }
  51          }
  52      }
  53  
  54      protected function processStandardProperty(
  55          DocumentProperties $docProps,
  56          string $propertyName,
  57          string $stringValue
  58      ): void {
  59          switch ($propertyName) {
  60              case 'Title':
  61                  $docProps->setTitle($stringValue);
  62  
  63                  break;
  64              case 'Subject':
  65                  $docProps->setSubject($stringValue);
  66  
  67                  break;
  68              case 'Author':
  69                  $docProps->setCreator($stringValue);
  70  
  71                  break;
  72              case 'Created':
  73                  $docProps->setCreated($stringValue);
  74  
  75                  break;
  76              case 'LastAuthor':
  77                  $docProps->setLastModifiedBy($stringValue);
  78  
  79                  break;
  80              case 'LastSaved':
  81                  $docProps->setModified($stringValue);
  82  
  83                  break;
  84              case 'Company':
  85                  $docProps->setCompany($stringValue);
  86  
  87                  break;
  88              case 'Category':
  89                  $docProps->setCategory($stringValue);
  90  
  91                  break;
  92              case 'Manager':
  93                  $docProps->setManager($stringValue);
  94  
  95                  break;
  96              case 'Keywords':
  97                  $docProps->setKeywords($stringValue);
  98  
  99                  break;
 100              case 'Description':
 101                  $docProps->setDescription($stringValue);
 102  
 103                  break;
 104          }
 105      }
 106  
 107      protected function processCustomProperty(
 108          DocumentProperties $docProps,
 109          string $propertyName,
 110          ?SimpleXMLElement $propertyValue,
 111          SimpleXMLElement $propertyAttributes
 112      ): void {
 113          $propertyType = DocumentProperties::PROPERTY_TYPE_UNKNOWN;
 114  
 115          switch ((string) $propertyAttributes) {
 116              case 'string':
 117                  $propertyType = DocumentProperties::PROPERTY_TYPE_STRING;
 118                  $propertyValue = trim((string) $propertyValue);
 119  
 120                  break;
 121              case 'boolean':
 122                  $propertyType = DocumentProperties::PROPERTY_TYPE_BOOLEAN;
 123                  $propertyValue = (bool) $propertyValue;
 124  
 125                  break;
 126              case 'integer':
 127                  $propertyType = DocumentProperties::PROPERTY_TYPE_INTEGER;
 128                  $propertyValue = (int) $propertyValue;
 129  
 130                  break;
 131              case 'float':
 132                  $propertyType = DocumentProperties::PROPERTY_TYPE_FLOAT;
 133                  $propertyValue = (float) $propertyValue;
 134  
 135                  break;
 136              case 'dateTime.tz':
 137                  $propertyType = DocumentProperties::PROPERTY_TYPE_DATE;
 138                  $propertyValue = trim((string) $propertyValue);
 139  
 140                  break;
 141          }
 142  
 143          $docProps->setCustomProperty($propertyName, $propertyValue, $propertyType);
 144      }
 145  
 146      protected function hex2str(array $hex): string
 147      {
 148          return mb_chr((int) hexdec($hex[1]), 'UTF-8');
 149      }
 150  
 151      private static function getAttributes(?SimpleXMLElement $simple, string $node): SimpleXMLElement
 152      {
 153          return ($simple === null)
 154              ? new SimpleXMLElement('<xml></xml>')
 155              : ($simple->attributes($node) ?? new SimpleXMLElement('<xml></xml>'));
 156      }
 157  }