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] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Writer;
   4  
   5  use PhpOffice\PhpSpreadsheet\Shared\File;
   6  use PhpOffice\PhpSpreadsheet\Spreadsheet;
   7  use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
   8  use PhpOffice\PhpSpreadsheet\Writer\Ods\Content;
   9  use PhpOffice\PhpSpreadsheet\Writer\Ods\Meta;
  10  use PhpOffice\PhpSpreadsheet\Writer\Ods\MetaInf;
  11  use PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype;
  12  use PhpOffice\PhpSpreadsheet\Writer\Ods\Settings;
  13  use PhpOffice\PhpSpreadsheet\Writer\Ods\Styles;
  14  use PhpOffice\PhpSpreadsheet\Writer\Ods\Thumbnails;
  15  use ZipArchive;
  16  
  17  class Ods extends BaseWriter
  18  {
  19      /**
  20       * Private writer parts.
  21       *
  22       * @var Ods\WriterPart[]
  23       */
  24      private $writerParts = [];
  25  
  26      /**
  27       * Private PhpSpreadsheet.
  28       *
  29       * @var Spreadsheet
  30       */
  31      private $spreadSheet;
  32  
  33      /**
  34       * Create a new Ods.
  35       *
  36       * @param Spreadsheet $spreadsheet
  37       */
  38      public function __construct(Spreadsheet $spreadsheet)
  39      {
  40          $this->setSpreadsheet($spreadsheet);
  41  
  42          $writerPartsArray = [
  43              'content' => Content::class,
  44              'meta' => Meta::class,
  45              'meta_inf' => MetaInf::class,
  46              'mimetype' => Mimetype::class,
  47              'settings' => Settings::class,
  48              'styles' => Styles::class,
  49              'thumbnails' => Thumbnails::class,
  50          ];
  51  
  52          foreach ($writerPartsArray as $writer => $class) {
  53              $this->writerParts[$writer] = new $class($this);
  54          }
  55      }
  56  
  57      /**
  58       * Get writer part.
  59       *
  60       * @param string $pPartName Writer part name
  61       *
  62       * @return null|Ods\WriterPart
  63       */
  64      public function getWriterPart($pPartName)
  65      {
  66          if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) {
  67              return $this->writerParts[strtolower($pPartName)];
  68          }
  69  
  70          return null;
  71      }
  72  
  73      /**
  74       * Save PhpSpreadsheet to file.
  75       *
  76       * @param string $pFilename
  77       *
  78       * @throws WriterException
  79       */
  80      public function save($pFilename)
  81      {
  82          if (!$this->spreadSheet) {
  83              throw new WriterException('PhpSpreadsheet object unassigned.');
  84          }
  85  
  86          // garbage collect
  87          $this->spreadSheet->garbageCollect();
  88  
  89          // If $pFilename is php://output or php://stdout, make it a temporary file...
  90          $originalFilename = $pFilename;
  91          if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
  92              $pFilename = @tempnam(File::sysGetTempDir(), 'phpxltmp');
  93              if ($pFilename == '') {
  94                  $pFilename = $originalFilename;
  95              }
  96          }
  97  
  98          $zip = $this->createZip($pFilename);
  99  
 100          $zip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest());
 101          $zip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail());
 102          $zip->addFromString('content.xml', $this->getWriterPart('content')->write());
 103          $zip->addFromString('meta.xml', $this->getWriterPart('meta')->write());
 104          $zip->addFromString('mimetype', $this->getWriterPart('mimetype')->write());
 105          $zip->addFromString('settings.xml', $this->getWriterPart('settings')->write());
 106          $zip->addFromString('styles.xml', $this->getWriterPart('styles')->write());
 107  
 108          // Close file
 109          if ($zip->close() === false) {
 110              throw new WriterException("Could not close zip file $pFilename.");
 111          }
 112  
 113          // If a temporary file was used, copy it to the correct file stream
 114          if ($originalFilename != $pFilename) {
 115              if (copy($pFilename, $originalFilename) === false) {
 116                  throw new WriterException("Could not copy temporary zip file $pFilename to $originalFilename.");
 117              }
 118              @unlink($pFilename);
 119          }
 120      }
 121  
 122      /**
 123       * Create zip object.
 124       *
 125       * @param string $pFilename
 126       *
 127       * @throws WriterException
 128       *
 129       * @return ZipArchive
 130       */
 131      private function createZip($pFilename)
 132      {
 133          // Create new ZIP file and open it for writing
 134          $zip = new ZipArchive();
 135  
 136          if (file_exists($pFilename)) {
 137              unlink($pFilename);
 138          }
 139          // Try opening the ZIP file
 140          if ($zip->open($pFilename, ZipArchive::OVERWRITE) !== true) {
 141              if ($zip->open($pFilename, ZipArchive::CREATE) !== true) {
 142                  throw new WriterException("Could not open $pFilename for writing.");
 143              }
 144          }
 145  
 146          return $zip;
 147      }
 148  
 149      /**
 150       * Get Spreadsheet object.
 151       *
 152       * @throws WriterException
 153       *
 154       * @return Spreadsheet
 155       */
 156      public function getSpreadsheet()
 157      {
 158          if ($this->spreadSheet !== null) {
 159              return $this->spreadSheet;
 160          }
 161  
 162          throw new WriterException('No PhpSpreadsheet assigned.');
 163      }
 164  
 165      /**
 166       * Set Spreadsheet object.
 167       *
 168       * @param Spreadsheet $spreadsheet PhpSpreadsheet object
 169       *
 170       * @return self
 171       */
 172      public function setSpreadsheet(Spreadsheet $spreadsheet)
 173      {
 174          $this->spreadSheet = $spreadsheet;
 175  
 176          return $this;
 177      }
 178  }