Test Setup Failed
Push — feature/issue-46-add-repeatabl... ( 599383 )
by Stefan
06:26
created

Finalizer::finalizeWorkbook()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace OneSheet;
4
5
use OneSheet\Style\Styler;
6
use OneSheet\Xml\DefaultXml;
7
use OneSheet\Xml\SheetXml;
8
9
class Finalizer
10
{
11
    /**
12
     * @var Sheet
13
     */
14
    private $sheet;
15
16
    /**
17
     * @var SheetFile
18
     */
19
    private $sheetFile;
20
21
    /**
22
     * @var \ZipArchive
23
     */
24
    private $zip;
25
26
    /**
27
     * @var Styler
28
     */
29
    private $styler;
30
31
    /**
32
     * @var Workbook
33
     */
34
    private $workbook;
35
36
    /**
37
     * Finalizer constructor.
38
     *
39
     * @param Workbook $workbook
40
     * @param Sheet              $sheet
41
     * @param Styler             $styler
42
     * @param SheetFile          $sheetFile
43
     */
44
    public function __construct(Sheet $sheet, Styler $styler, SheetFile $sheetFile, Workbook $workbook)
45
    {
46
        $this->sheet = $sheet;
47
        $this->styler = $styler;
48
        $this->sheetFile = $sheetFile;
49
        $this->workbook = $workbook;
50
        $this->zip = new \ZipArchive();
51
    }
52
53
    /**
54
     * Finalize the xlsx file.
55
     *
56
     * @param resource $output
57
     */
58
    public function finalize($output)
59
    {
60
        $zipFileUrl = sys_get_temp_dir() . '/' . uniqid();
61
62
        $this->fillZipWithFileContents($zipFileUrl);
63
        if (!$this->zip->close()) {
64
            throw new \RuntimeException('Failed to close zip file!');
65
        }
66
67
        $this->copyToOutputAndCleanup($output, $zipFileUrl);
68
    }
69
70
    /**
71
     * Add all file and string contents to zip file.
72
     *
73
     * @param string $zipFileUrl
74
     */
75
    private function fillZipWithFileContents($zipFileUrl)
76
    {
77
        $this->zip->open($zipFileUrl, \ZipArchive::CREATE);
78
        $this->finalizeSheet();
79
        $this->finalizeStyles();
80
        $this->finalizeWorkbook();
81
        $this->finalizeDefaultXmls();
82
    }
83
84
    /**
85
     * Wrap up the sheet (write header, column xmls).
86
     */
87
    private function finalizeSheet()
88
    {
89
        $this->sheetFile->fwrite('</sheetData></worksheet>');
90
        $this->sheetFile->rewind();
91
        $this->sheetFile->fwrite(SheetXml::HEADER_XML);
92
        $this->sheetFile->fwrite($this->sheet->getDimensionXml());
93
        $this->sheetFile->fwrite($this->sheet->getSheetViewsXml());
94
        $this->sheetFile->fwrite($this->sheet->getColsXml());
95
        $this->zip->addFile($this->sheetFile->getFilePath(), 'xl/worksheets/sheet1.xml');
96
    }
97
98
    /**
99
     * Write style xml file.
100
     */
101
    private function finalizeStyles()
102
    {
103
        $this->zip->addFromString('xl/styles.xml', $this->styler->getStyleSheetXml());
104
    }
105
106
    /**
107
     * Write workbook file.
108
     */
109
    private function finalizeWorkbook()
110
    {
111
        $this->zip->addFromString('xl/workbook.xml', $this->workbook->getWorkbookXml());
112
    }
113
114
    /**
115
     * Add default xmls to zip archive.
116
     */
117
    private function finalizeDefaultXmls()
118
    {
119
        $this->zip->addFromString('[Content_Types].xml', DefaultXml::CONTENT_TYPES);
120
        $this->zip->addFromString('docProps/core.xml',
121
            sprintf(DefaultXml::DOCPROPS_CORE, date(DATE_ISO8601), date(DATE_ISO8601)));
122
        $this->zip->addFromString('docProps/app.xml', DefaultXml::DOCPROPS_APP);
123
        $this->zip->addFromString('_rels/.rels', DefaultXml::RELS_RELS);
124
        $this->zip->addFromString('xl/_rels/workbook.xml.rels', DefaultXml::XL_RELS_WORKBOOK);
125
    }
126
127
    /**
128
     * Write zip/xlsx contents to specified output
129
     * and unlink/delete files.
130
     *
131
     * @param resource $output
132
     * @param string   $zipFileUrl
133
     */
134
    private function copyToOutputAndCleanup($output, $zipFileUrl)
135
    {
136
        $zipFilePointer = fopen($zipFileUrl, 'r');
137
        if (!stream_copy_to_stream($zipFilePointer, $output)
138
            || !fclose($zipFilePointer)
139
            || !fclose($output)
140
            || !unlink($zipFileUrl)
141
        ) {
142
            throw new \RuntimeException("Failed to copy stream and clean up!");
143
        }
144
    }
145
}
146