1<?php 2 3namespace PhpOffice\PhpSpreadsheet\Helper; 4 5use PhpOffice\PhpSpreadsheet\IOFactory; 6use PhpOffice\PhpSpreadsheet\Spreadsheet; 7use PhpOffice\PhpSpreadsheet\Writer\IWriter; 8use PhpOffice\PhpSpreadsheet\Writer\Pdf; 9use RecursiveDirectoryIterator; 10use RecursiveIteratorIterator; 11use RecursiveRegexIterator; 12use ReflectionClass; 13use RegexIterator; 14 15/** 16 * Helper class to be used in sample code. 17 */ 18class Sample 19{ 20 /** 21 * Returns whether we run on CLI or browser. 22 * 23 * @return bool 24 */ 25 public function isCli() 26 { 27 return PHP_SAPI === 'cli'; 28 } 29 30 /** 31 * Return the filename currently being executed. 32 * 33 * @return string 34 */ 35 public function getScriptFilename() 36 { 37 return basename($_SERVER['SCRIPT_FILENAME'], '.php'); 38 } 39 40 /** 41 * Whether we are executing the index page. 42 * 43 * @return bool 44 */ 45 public function isIndex() 46 { 47 return $this->getScriptFilename() === 'index'; 48 } 49 50 /** 51 * Return the page title. 52 * 53 * @return string 54 */ 55 public function getPageTitle() 56 { 57 return $this->isIndex() ? 'PHPSpreadsheet' : $this->getScriptFilename(); 58 } 59 60 /** 61 * Return the page heading. 62 * 63 * @return string 64 */ 65 public function getPageHeading() 66 { 67 return $this->isIndex() ? '' : '<h1>' . str_replace('_', ' ', $this->getScriptFilename()) . '</h1>'; 68 } 69 70 /** 71 * Returns an array of all known samples. 72 * 73 * @return string[] [$name => $path] 74 */ 75 public function getSamples() 76 { 77 // Populate samples 78 $baseDir = realpath(__DIR__ . '/../../../samples'); 79 $directory = new RecursiveDirectoryIterator($baseDir); 80 $iterator = new RecursiveIteratorIterator($directory); 81 $regex = new RegexIterator($iterator, '/^.+\.php$/', RecursiveRegexIterator::GET_MATCH); 82 83 $files = []; 84 foreach ($regex as $file) { 85 $file = str_replace(str_replace('\\', '/', $baseDir) . '/', '', str_replace('\\', '/', $file[0])); 86 $info = pathinfo($file); 87 $category = str_replace('_', ' ', $info['dirname']); 88 $name = str_replace('_', ' ', preg_replace('/(|\.php)/', '', $info['filename'])); 89 if (!in_array($category, ['.', 'boostrap', 'templates'])) { 90 if (!isset($files[$category])) { 91 $files[$category] = []; 92 } 93 $files[$category][$name] = $file; 94 } 95 } 96 97 // Sort everything 98 ksort($files); 99 foreach ($files as &$f) { 100 asort($f); 101 } 102 103 return $files; 104 } 105 106 /** 107 * Write documents. 108 * 109 * @param Spreadsheet $spreadsheet 110 * @param string $filename 111 * @param string[] $writers 112 */ 113 public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls']) 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) 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() 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 IWriter $writer 201 * @param string $path 202 * @param float $callStartTime 203 */ 204 public function logWrite(IWriter $writer, $path, $callStartTime) 205 { 206 $callEndTime = microtime(true); 207 $callTime = $callEndTime - $callStartTime; 208 $reflection = new ReflectionClass($writer); 209 $format = $reflection->getShortName(); 210 $message = "Write {$format} format to <code>{$path}</code> in " . sprintf('%.4f', $callTime) . ' seconds'; 211 212 $this->log($message); 213 } 214 215 /** 216 * Log a line about the read operation. 217 * 218 * @param string $format 219 * @param string $path 220 * @param float $callStartTime 221 */ 222 public function logRead($format, $path, $callStartTime) 223 { 224 $callEndTime = microtime(true); 225 $callTime = $callEndTime - $callStartTime; 226 $message = "Read {$format} format from <code>{$path}</code> in " . sprintf('%.4f', $callTime) . ' seconds'; 227 228 $this->log($message); 229 } 230} 231