Completed
Pull Request — master (#54)
by Stefan
05:14 queued 03:10
created

Finalizer   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 96.3%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 4
dl 0
loc 141
ccs 52
cts 54
cp 0.963
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A finalize() 0 11 2
A fillZipWithFileContents() 0 10 2
A finalizeSheet() 0 11 1
A finalizeStyles() 0 4 1
A finalizeWorkbook() 0 5 1
A finalizeDefaultXmls() 0 8 1
A copyToOutputAndCleanup() 0 11 5
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 $sheets;
15
16
    /**
17
     * @var SheetFile[]
18
     */
19
    private $sheetFiles;
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
     * @param Workbook    $workbook
38
     * @param Sheet[]     $sheets
39
     * @param Styler      $styler
40
     * @param SheetFile[] $sheetFiles
41
     */
42 4
    public function __construct(array $sheets, Styler $styler, array $sheetFiles, Workbook $workbook)
43
    {
44 4
        $this->sheets = $sheets;
45 4
        $this->styler = $styler;
46 4
        $this->sheetFiles = $sheetFiles;
47 4
        $this->workbook = $workbook;
48 4
        $this->zip = new \ZipArchive();
49 4
    }
50
51
    /**
52
     * Finalize the xlsx file.
53
     *
54
     * @param resource $output
55
     */
56 4
    public function finalize($output)
57
    {
58 4
        $zipFileUrl = sys_get_temp_dir() . '/' . uniqid();
59
60 4
        $this->fillZipWithFileContents($zipFileUrl);
61 4
        if (!$this->zip->close()) {
62
            throw new \RuntimeException('Failed to close zip file!');
63
        }
64
65 4
        $this->copyToOutputAndCleanup($output, $zipFileUrl);
66 4
    }
67
68
    /**
69
     * Add all file and string contents to zip file.
70
     *
71
     * @param string $zipFileUrl
72
     */
73 4
    private function fillZipWithFileContents($zipFileUrl)
74
    {
75 4
        $this->zip->open($zipFileUrl, \ZipArchive::CREATE);
76 4
        foreach ($this->sheets as $sheetName => $sheet) {
77 4
            $this->finalizeSheet($this->sheetFiles[$sheetName], $sheet, $sheetName);
78
        }
79 4
        $this->finalizeWorkbook(array_keys($this->sheets));
80 4
        $this->finalizeStyles();
81 4
        $this->finalizeDefaultXmls();
82 4
    }
83
84
    /**
85
     * @param SheetFile $sheetFile
86
     * @param Sheet     $sheet
87
     * @param string    $sheetName
88
     */
89 4
    private function finalizeSheet($sheetFile, $sheet, $sheetName)
90
    {
91 4
        $sheetFile->fwrite('</sheetData></worksheet>');
92 4
        $sheetFile->rewind();
93 4
        $sheetFile->fwrite(SheetXml::HEADER_XML);
94 4
        $sheetFile->fwrite($sheet->getDimensionXml());
95 4
        $sheetFile->fwrite($sheet->getSheetViewsXml());
96 4
        $sheetFile->fwrite($sheet->getColsXml());
97 4
        $this->zip->addFile($sheetFile->getFilePath(),
98 4
            sprintf("xl/worksheets/%s.xml", $sheetName));
99 4
    }
100
101
    /**
102
     * Write style xml file.
103
     */
104 4
    private function finalizeStyles()
105
    {
106 4
        $this->zip->addFromString('xl/styles.xml', $this->styler->getStyleSheetXml());
107 4
    }
108
109
    /**
110
     * Write workbook file.
111
     * @param string[] $sheetNames
112
     */
113 4
    private function finalizeWorkbook(array $sheetNames)
114
    {
115 4
        $this->zip->addFromString('xl/workbook.xml', $this->workbook->getWorkbookXml($sheetNames));
116 4
        $this->zip->addFromString('xl/_rels/workbook.xml.rels', $this->workbook->getWorkbookRelsXml($sheetNames));
117 4
    }
118
119
    /**
120
     * Add default xmls to zip archive.
121
     */
122 4
    private function finalizeDefaultXmls()
123
    {
124 4
        $this->zip->addFromString('[Content_Types].xml', DefaultXml::CONTENT_TYPES);
125 4
        $this->zip->addFromString('docProps/core.xml',
126 4
            sprintf(DefaultXml::DOCPROPS_CORE, date(DATE_W3C), date(DATE_W3C)));
127 4
        $this->zip->addFromString('docProps/app.xml', DefaultXml::DOCPROPS_APP);
128 4
        $this->zip->addFromString('_rels/.rels', DefaultXml::RELS_RELS);
129 4
    }
130
131
    /**
132
     * Write zip/xlsx contents to specified output
133
     * and unlink/delete files.
134
     *
135
     * @param resource $output
136
     * @param string   $zipFileUrl
137
     */
138 4
    private function copyToOutputAndCleanup($output, $zipFileUrl)
139
    {
140 4
        $zipFilePointer = fopen($zipFileUrl, 'r');
141 4
        if (!stream_copy_to_stream($zipFilePointer, $output)
142 4
            || !fclose($zipFilePointer)
143 4
            || !fclose($output)
144 4
            || !unlink($zipFileUrl)
145
        ) {
146
            throw new \RuntimeException("Failed to copy stream and clean up!");
147
        }
148 4
    }
149
}
150