PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Helper / Downloader.php

Downloader.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Helper/Downloader.php

103 lines 2.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Helper;
4
5 use DateTimeImmutable;
6 use DateTimeZone;
7 use TablePress\PhpOffice\PhpSpreadsheet\Exception;
8
9 /**
10 * Assist downloading files when samples are run in browser.
11 * Never run as part of unit tests, which are command line.
12 *
13 * @codeCoverageIgnore
14 */
15 class Downloader
16 {
17 protected string $filepath;
18
19 protected string $filename;
20
21 protected string $filetype;
22
23 protected const CONTENT_TYPES = [
24 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
25 'xls' => 'application/vnd.ms-excel',
26 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
27 'csv' => 'text/csv',
28 'html' => 'text/html',
29 'pdf' => 'application/pdf',
30 ];
31
32 public function __construct(string $folder, string $filename, ?string $filetype = null)
33 {
34 clearstatcache();
35 $filepath = realpath("{$folder}/{$filename}");
36 if ($filepath === false || !is_file($filepath) || !is_readable($filepath)) {
37 throw new Exception('File not found, or cannot be read');
38 }
39 $this->filepath = $filepath;
40 $this->filename = basename($this->filepath);
41
42 $filetype ??= pathinfo($this->filename, PATHINFO_EXTENSION);
43 if (!array_key_exists(strtolower($filetype), self::CONTENT_TYPES)) {
44 throw new Exception('Invalid filetype: file cannot be downloaded');
45 }
46 $this->filetype = strtolower($filetype);
47 }
48
49 public function download(): void
50 {
51 $this->headers();
52
53 readfile($this->filepath);
54 }
55
56 public function headers(): void
57 {
58 // I cannot tell what this ob_clean is paired with.
59 // I have never seen a problem with it, but someone has - issue 3739.
60 // Perhaps it should be removed altogether,
61 // but making it conditional seems harmless, and safer.
62 if ((int) ob_get_length() > 0) {
63 ob_clean();
64 }
65
66 $this->contentType();
67 $this->contentDisposition();
68 $this->cacheHeaders();
69 $this->fileSize();
70
71 flush();
72 }
73
74 protected function contentType(): void
75 {
76 header('Content-Type: ' . self::CONTENT_TYPES[$this->filetype]);
77 }
78
79 protected function contentDisposition(): void
80 {
81 header('Content-Disposition: attachment;filename="' . $this->filename . '"');
82 }
83
84 protected function cacheHeaders(): void
85 {
86 header('Cache-Control: max-age=0');
87 // If you're serving to IE 9, then the following may be needed
88 header('Cache-Control: max-age=1');
89
90 // If you're serving to IE over SSL, then the following may be needed
91 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
92 $dt = new DateTimeImmutable('now', new DateTimeZone('UTC'));
93 header('Last-Modified: ' . $dt->format('D, d M Y H:i:s') . ' GMT'); // always modified
94 header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
95 header('Pragma: public'); // HTTP/1.0
96 }
97
98 protected function fileSize(): void
99 {
100 header('Content-Length: ' . filesize($this->filepath));
101 }
102 }
103