Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Helper;
   4  
   5  use PhpOffice\PhpSpreadsheet\IOFactory;
   6  use PhpOffice\PhpSpreadsheet\Spreadsheet;
   7  use PhpOffice\PhpSpreadsheet\Writer\IWriter;
   8  use PhpOffice\PhpSpreadsheet\Writer\Pdf;
   9  use RecursiveDirectoryIterator;
  10  use RecursiveIteratorIterator;
  11  use RecursiveRegexIterator;
  12  use ReflectionClass;
  13  use RegexIterator;
  14  use RuntimeException;
  15  
  16  /**
  17   * Helper class to be used in sample code.
  18   */
  19  class Sample
  20  {
  21      /**
  22       * Returns whether we run on CLI or browser.
  23       *
  24       * @return bool
  25       */
  26      public function isCli()
  27      {
  28          return PHP_SAPI === 'cli';
  29      }
  30  
  31      /**
  32       * Return the filename currently being executed.
  33       *
  34       * @return string
  35       */
  36      public function getScriptFilename()
  37      {
  38          return basename($_SERVER['SCRIPT_FILENAME'], '.php');
  39      }
  40  
  41      /**
  42       * Whether we are executing the index page.
  43       *
  44       * @return bool
  45       */
  46      public function isIndex()
  47      {
  48          return $this->getScriptFilename() === 'index';
  49      }
  50  
  51      /**
  52       * Return the page title.
  53       *
  54       * @return string
  55       */
  56      public function getPageTitle()
  57      {
  58          return $this->isIndex() ? 'PHPSpreadsheet' : $this->getScriptFilename();
  59      }
  60  
  61      /**
  62       * Return the page heading.
  63       *
  64       * @return string
  65       */
  66      public function getPageHeading()
  67      {
  68          return $this->isIndex() ? '' : '<h1>' . str_replace('_', ' ', $this->getScriptFilename()) . '</h1>';
  69      }
  70  
  71      /**
  72       * Returns an array of all known samples.
  73       *
  74       * @return string[] [$name => $path]
  75       */
  76      public function getSamples()
  77      {
  78          // Populate samples
  79          $baseDir = realpath(__DIR__ . '/../../../samples');
  80          $directory = new RecursiveDirectoryIterator($baseDir);
  81          $iterator = new RecursiveIteratorIterator($directory);
  82          $regex = new RegexIterator($iterator, '/^.+\.php$/', RecursiveRegexIterator::GET_MATCH);
  83  
  84          $files = [];
  85          foreach ($regex as $file) {
  86              $file = str_replace(str_replace('\\', '/', $baseDir) . '/', '', str_replace('\\', '/', $file[0]));
  87              $info = pathinfo($file);
  88              $category = str_replace('_', ' ', $info['dirname']);
  89              $name = str_replace('_', ' ', preg_replace('/(|\.php)/', '', $info['filename']));
  90              if (!in_array($category, ['.', 'boostrap', 'templates'])) {
  91                  if (!isset($files[$category])) {
  92                      $files[$category] = [];
  93                  }
  94                  $files[$category][$name] = $file;
  95              }
  96          }
  97  
  98          // Sort everything
  99          ksort($files);
 100          foreach ($files as &$f) {
 101              asort($f);
 102          }
 103  
 104          return $files;
 105      }
 106  
 107      /**
 108       * Write documents.
 109       *
 110       * @param string $filename
 111       * @param string[] $writers
 112       */
 113      public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls']): void
 114      {
 115          // Set active sheet index to the first sheet, so Excel opens this as the first sheet
 116          $spreadsheet->setActiveSheetIndex(0);
 117  
 118          // Write documents
 119          foreach ($writers as $writerType) {
 120              $path = $this->getFilename($filename, mb_strtolower($writerType));
 121              $writer = IOFactory::createWriter($spreadsheet, $writerType);
 122              if ($writer instanceof Pdf) {
 123                  // PDF writer needs temporary directory
 124                  $tempDir = $this->getTemporaryFolder();
 125                  $writer->setTempDir($tempDir);
 126              }
 127              $callStartTime = microtime(true);
 128              $writer->save($path);
 129              $this->logWrite($writer, $path, $callStartTime);
 130          }
 131  
 132          $this->logEndingNotes();
 133      }
 134  
 135      /**
 136       * Returns the temporary directory and make sure it exists.
 137       *
 138       * @return string
 139       */
 140      private function getTemporaryFolder()
 141      {
 142          $tempFolder = sys_get_temp_dir() . '/phpspreadsheet';
 143          if (!is_dir($tempFolder)) {
 144              if (!mkdir($tempFolder) && !is_dir($tempFolder)) {
 145                  throw new RuntimeException(sprintf('Directory "%s" was not created', $tempFolder));
 146              }
 147          }
 148  
 149          return $tempFolder;
 150      }
 151  
 152      /**
 153       * Returns the filename that should be used for sample output.
 154       *
 155       * @param string $filename
 156       * @param string $extension
 157       *
 158       * @return string
 159       */
 160      public function getFilename($filename, $extension = 'xlsx')
 161      {
 162          $originalExtension = pathinfo($filename, PATHINFO_EXTENSION);
 163  
 164          return $this->getTemporaryFolder() . '/' . str_replace('.' . $originalExtension, '.' . $extension, basename($filename));
 165      }
 166  
 167      /**
 168       * Return a random temporary file name.
 169       *
 170       * @param string $extension
 171       *
 172       * @return string
 173       */
 174      public function getTemporaryFilename($extension = 'xlsx')
 175      {
 176          $temporaryFilename = tempnam($this->getTemporaryFolder(), 'phpspreadsheet-');
 177          unlink($temporaryFilename);
 178  
 179          return $temporaryFilename . '.' . $extension;
 180      }
 181  
 182      public function log($message): void
 183      {
 184          $eol = $this->isCli() ? PHP_EOL : '<br />';
 185          echo date('H:i:s ') . $message . $eol;
 186      }
 187  
 188      /**
 189       * Log ending notes.
 190       */
 191      public function logEndingNotes(): void
 192      {
 193          // Do not show execution time for index
 194          $this->log('Peak memory usage: ' . (memory_get_peak_usage(true) / 1024 / 1024) . 'MB');
 195      }
 196  
 197      /**
 198       * Log a line about the write operation.
 199       *
 200       * @param string $path
 201       * @param float $callStartTime
 202       */
 203      public function logWrite(IWriter $writer, $path, $callStartTime): void
 204      {
 205          $callEndTime = microtime(true);
 206          $callTime = $callEndTime - $callStartTime;
 207          $reflection = new ReflectionClass($writer);
 208          $format = $reflection->getShortName();
 209          $message = "Write {$format} format to <code>{$path}</code>  in " . sprintf('%.4f', $callTime) . ' seconds';
 210  
 211          $this->log($message);
 212      }
 213  
 214      /**
 215       * Log a line about the read operation.
 216       *
 217       * @param string $format
 218       * @param string $path
 219       * @param float $callStartTime
 220       */
 221      public function logRead($format, $path, $callStartTime): void
 222      {
 223          $callEndTime = microtime(true);
 224          $callTime = $callEndTime - $callStartTime;
 225          $message = "Read {$format} format from <code>{$path}</code>  in " . sprintf('%.4f', $callTime) . ' seconds';
 226  
 227          $this->log($message);
 228      }
 229  }