Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace OpenSpout\Writer;
6
 
7
use OpenSpout\Common\Entity\Row;
8
use OpenSpout\Common\Exception\IOException;
9
use OpenSpout\Writer\Exception\WriterNotOpenedException;
10
 
11
abstract class AbstractWriter implements WriterInterface
12
{
13
    /** @var resource Pointer to the file/stream we will write to */
14
    protected $filePointer;
15
 
16
    /** @var string document creator */
17
    protected string $creator = 'OpenSpout';
18
 
19
    /** @var string Content-Type value for the header - to be defined by child class */
20
    protected static string $headerContentType;
21
 
22
    /** @var string Path to the output file */
23
    private string $outputFilePath;
24
 
25
    /** @var bool Indicates whether the writer has been opened or not */
26
    private bool $isWriterOpened = false;
27
 
28
    /** @var 0|positive-int */
29
    private int $writtenRowCount = 0;
30
 
31
    final public function openToFile($outputFilePath): void
32
    {
33
        $this->outputFilePath = $outputFilePath;
34
 
35
        $errorMessage = null;
36
        set_error_handler(static function ($nr, $message) use (&$errorMessage): bool {
37
            $errorMessage = $message;
38
 
39
            return true;
40
        });
41
 
42
        $resource = fopen($this->outputFilePath, 'w');
43
        restore_error_handler();
44
        if (null !== $errorMessage) {
45
            throw new IOException("Unable to open file {$this->outputFilePath}: {$errorMessage}");
46
        }
47
        \assert(false !== $resource);
48
        $this->filePointer = $resource;
49
 
50
        $this->openWriter();
51
        $this->isWriterOpened = true;
52
    }
53
 
54
    /**
55
     * @codeCoverageIgnore
56
     *
57
     * @param mixed $outputFileName
58
     */
59
    final public function openToBrowser($outputFileName): void
60
    {
61
        $this->outputFilePath = basename($outputFileName);
62
 
63
        $resource = fopen('php://output', 'w');
64
        \assert(false !== $resource);
65
        $this->filePointer = $resource;
66
 
67
        // Clear any previous output (otherwise the generated file will be corrupted)
68
        // @see https://github.com/box/spout/issues/241
69
        if (ob_get_length() > 0) {
70
            ob_end_clean();
71
        }
72
 
73
        /*
74
         * Set headers
75
         *
76
         * For newer browsers such as Firefox, Chrome, Opera, Safari, etc., they all support and use `filename*`
77
         * specified by the new standard, even if they do not automatically decode filename; it does not matter;
78
         * and for older versions of Internet Explorer, they are not recognized `filename*`, will automatically
79
         * ignore it and use the old `filename` (the only minor flaw is that there must be an English suffix name).
80
         * In this way, the multi-browser multi-language compatibility problem is perfectly solved, which does not
81
         * require UA judgment and is more in line with the standard.
82
         *
83
         * @see https://github.com/box/spout/issues/745
84
         * @see https://tools.ietf.org/html/rfc6266
85
         * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
86
         */
87
        header('Content-Type: '.static::$headerContentType);
88
        header(
89
            'Content-Disposition: attachment; '.
90
            'filename="'.rawurlencode($this->outputFilePath).'"; '.
91
            'filename*=UTF-8\'\''.rawurlencode($this->outputFilePath)
92
        );
93
 
94
        /*
95
         * When forcing the download of a file over SSL,IE8 and lower browsers fail
96
         * if the Cache-Control and Pragma headers are not set.
97
         *
98
         * @see http://support.microsoft.com/KB/323308
99
         * @see https://github.com/liuggio/ExcelBundle/issues/45
100
         */
101
        header('Cache-Control: max-age=0');
102
        header('Pragma: public');
103
 
104
        $this->openWriter();
105
        $this->isWriterOpened = true;
106
    }
107
 
108
    final public function addRow(Row $row): void
109
    {
110
        if (!$this->isWriterOpened) {
111
            throw new WriterNotOpenedException('The writer needs to be opened before adding row.');
112
        }
113
 
114
        $this->addRowToWriter($row);
115
        ++$this->writtenRowCount;
116
    }
117
 
118
    final public function addRows(array $rows): void
119
    {
120
        foreach ($rows as $row) {
121
            $this->addRow($row);
122
        }
123
    }
124
 
125
    final public function setCreator(string $creator): void
126
    {
127
        $this->creator = $creator;
128
    }
129
 
130
    final public function getWrittenRowCount(): int
131
    {
132
        return $this->writtenRowCount;
133
    }
134
 
135
    final public function close(): void
136
    {
137
        if (!$this->isWriterOpened) {
138
            return;
139
        }
140
 
141
        $this->closeWriter();
142
 
143
        fclose($this->filePointer);
144
 
145
        $this->isWriterOpened = false;
146
    }
147
 
148
    /**
149
     * Opens the streamer and makes it ready to accept data.
150
     *
151
     * @throws IOException If the writer cannot be opened
152
     */
153
    abstract protected function openWriter(): void;
154
 
155
    /**
156
     * Adds a row to the currently opened writer.
157
     *
158
     * @param Row $row The row containing cells and styles
159
     *
160
     * @throws WriterNotOpenedException If the workbook is not created yet
161
     * @throws IOException              If unable to write data
162
     */
163
    abstract protected function addRowToWriter(Row $row): void;
164
 
165
    /**
166
     * Closes the streamer, preventing any additional writing.
167
     */
168
    abstract protected function closeWriter(): void;
169
}