Failed Conditions
Push — master ( 4b6ad7...9fab89 )
by Adrien
06:57
created

Content::writeCells()   C

Complexity

Conditions 14
Paths 67

Size

Total Lines 79
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 14.2079

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 14
eloc 59
c 3
b 0
f 0
nc 67
nop 2
dl 0
loc 79
ccs 44
cts 49
cp 0.898
crap 14.2079
rs 6.2666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Cell;
6
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
7
use PhpOffice\PhpSpreadsheet\Cell\DataType;
8
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
9
use PhpOffice\PhpSpreadsheet\Spreadsheet;
10
use PhpOffice\PhpSpreadsheet\Style\Fill;
11
use PhpOffice\PhpSpreadsheet\Style\Font;
12
use PhpOffice\PhpSpreadsheet\Worksheet\Row;
13
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
14
use PhpOffice\PhpSpreadsheet\Writer\Exception;
15
use PhpOffice\PhpSpreadsheet\Writer\Ods;
16
use PhpOffice\PhpSpreadsheet\Writer\Ods\Cell\Comment;
17
18
/**
19
 * @category   PhpSpreadsheet
20
 *
21
 * @method Ods getParentWriter
22
 *
23
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
24
 * @author     Alexander Pervakov <[email protected]>
25
 */
26
class Content extends WriterPart
27
{
28
    const NUMBER_COLS_REPEATED_MAX = 1024;
29
    const NUMBER_ROWS_REPEATED_MAX = 1048576;
30
    const CELL_STYLE_PREFIX = 'ce';
31
32
    /**
33
     * Write content.xml to XML format.
34
     *
35
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
36
     *
37
     * @return string XML Output
38
     */
39 7
    public function write()
40
    {
41 7
        $objWriter = null;
42 7
        if ($this->getParentWriter()->getUseDiskCaching()) {
43
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
44
        } else {
45 7
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
46
        }
47
48
        // XML header
49 7
        $objWriter->startDocument('1.0', 'UTF-8');
50
51
        // Content
52 7
        $objWriter->startElement('office:document-content');
53 7
        $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0');
54 7
        $objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0');
55 7
        $objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0');
56 7
        $objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0');
57 7
        $objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0');
58 7
        $objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0');
59 7
        $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
60 7
        $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/');
61 7
        $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0');
62 7
        $objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0');
63 7
        $objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0');
64 7
        $objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0');
65 7
        $objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0');
66 7
        $objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0');
67 7
        $objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML');
68 7
        $objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0');
69 7
        $objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0');
70 7
        $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office');
71 7
        $objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer');
72 7
        $objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc');
73 7
        $objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events');
74 7
        $objWriter->writeAttribute('xmlns:xforms', 'http://www.w3.org/2002/xforms');
75 7
        $objWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema');
76 7
        $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
77 7
        $objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report');
78 7
        $objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2');
79 7
        $objWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml');
80 7
        $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#');
81 7
        $objWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table');
82 7
        $objWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0');
83 7
        $objWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0');
84 7
        $objWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/');
85 7
        $objWriter->writeAttribute('office:version', '1.2');
86
87 7
        $objWriter->writeElement('office:scripts');
88 7
        $objWriter->writeElement('office:font-face-decls');
89
90
        // Styles XF
91 7
        $objWriter->startElement('office:automatic-styles');
92 7
        $this->writeXfStyles($objWriter, $this->getParentWriter()->getSpreadsheet());
93 7
        $objWriter->endElement();
94
95 7
        $objWriter->startElement('office:body');
96 7
        $objWriter->startElement('office:spreadsheet');
97 7
        $objWriter->writeElement('table:calculation-settings');
98
99 7
        $this->writeSheets($objWriter);
100
101 7
        $objWriter->writeElement('table:named-expressions');
102 7
        $objWriter->endElement();
103 7
        $objWriter->endElement();
104 7
        $objWriter->endElement();
105
106 7
        return $objWriter->getData();
107
    }
108
109
    /**
110
     * Write sheets.
111
     *
112
     * @param XMLWriter $objWriter
113
     */
114 7
    private function writeSheets(XMLWriter $objWriter)
115
    {
116 7
        $spreadsheet = $this->getParentWriter()->getSpreadsheet(); // @var $spreadsheet Spreadsheet
117
118 7
        $sheetCount = $spreadsheet->getSheetCount();
119 7
        for ($i = 0; $i < $sheetCount; ++$i) {
120 7
            $objWriter->startElement('table:table');
121 7
            $objWriter->writeAttribute('table:name', $spreadsheet->getSheet($i)->getTitle());
122 7
            $objWriter->writeElement('office:forms');
123 7
            $objWriter->startElement('table:table-column');
124 7
            $objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
125 7
            $objWriter->endElement();
126 7
            $this->writeRows($objWriter, $spreadsheet->getSheet($i));
127 7
            $objWriter->endElement();
128
        }
129 7
    }
130
131
    /**
132
     * Write rows of the specified sheet.
133
     *
134
     * @param XMLWriter $objWriter
135
     * @param Worksheet $sheet
136
     */
137 7
    private function writeRows(XMLWriter $objWriter, Worksheet $sheet)
138
    {
139 7
        $numberRowsRepeated = self::NUMBER_ROWS_REPEATED_MAX;
140 7
        $span_row = 0;
141 7
        $rows = $sheet->getRowIterator();
142 7
        while ($rows->valid()) {
143 7
            --$numberRowsRepeated;
144 7
            $row = $rows->current();
145 7
            if ($row->getCellIterator()->valid()) {
146 7
                if ($span_row) {
147
                    $objWriter->startElement('table:table-row');
148
                    if ($span_row > 1) {
149
                        $objWriter->writeAttribute('table:number-rows-repeated', $span_row);
150
                    }
151
                    $objWriter->startElement('table:table-cell');
152
                    $objWriter->writeAttribute('table:number-columns-repeated', self::NUMBER_COLS_REPEATED_MAX);
153
                    $objWriter->endElement();
154
                    $objWriter->endElement();
155
                    $span_row = 0;
156
                }
157 7
                $objWriter->startElement('table:table-row');
158 7
                $this->writeCells($objWriter, $row);
159 7
                $objWriter->endElement();
160
            } else {
161
                ++$span_row;
162
            }
163 7
            $rows->next();
164
        }
165 7
    }
166
167
    /**
168
     * Write cells of the specified row.
169
     *
170
     * @param XMLWriter $objWriter
171
     * @param Row $row
172
     *
173
     * @throws Exception
174
     */
175 7
    private function writeCells(XMLWriter $objWriter, Row $row)
176
    {
177 7
        $numberColsRepeated = self::NUMBER_COLS_REPEATED_MAX;
178 7
        $prevColumn = -1;
179 7
        $cells = $row->getCellIterator();
180 7
        while ($cells->valid()) {
181
            /** @var \PhpOffice\PhpSpreadsheet\Cell\Cell $cell */
182 7
            $cell = $cells->current();
183 7
            $column = Coordinate::columnIndexFromString($cell->getColumn()) - 1;
184
185 7
            $this->writeCellSpan($objWriter, $column, $prevColumn);
186 7
            $objWriter->startElement('table:table-cell');
187 7
            $this->writeCellMerge($objWriter, $cell);
188
189
            // Style XF
190 7
            $style = $cell->getXfIndex();
191 7
            if ($style !== null) {
192 7
                $objWriter->writeAttribute('table:style-name', self::CELL_STYLE_PREFIX . $style);
193
            }
194
195 7
            switch ($cell->getDataType()) {
196
                case DataType::TYPE_BOOL:
197 1
                    $objWriter->writeAttribute('office:value-type', 'boolean');
198 1
                    $objWriter->writeAttribute('office:value', $cell->getValue());
199 1
                    $objWriter->writeElement('text:p', $cell->getValue());
200
201 1
                    break;
202
                case DataType::TYPE_ERROR:
203
                    throw new Exception('Writing of error not implemented yet.');
204
205
                    break;
206
                case DataType::TYPE_FORMULA:
207 1
                    $formulaValue = $cell->getValue();
208 1
                    if ($this->getParentWriter()->getPreCalculateFormulas()) {
209
                        try {
210 1
                            $formulaValue = $cell->getCalculatedValue();
211
                        } catch (Exception $e) {
212
                            // don't do anything
213
                        }
214
                    }
215 1
                    $objWriter->writeAttribute('table:formula', 'of:' . $cell->getValue());
216 1
                    if (is_numeric($formulaValue)) {
217
                        $objWriter->writeAttribute('office:value-type', 'float');
218
                    } else {
219 1
                        $objWriter->writeAttribute('office:value-type', 'string');
220
                    }
221 1
                    $objWriter->writeAttribute('office:value', $formulaValue);
222 1
                    $objWriter->writeElement('text:p', $formulaValue);
223
224 1
                    break;
225
                case DataType::TYPE_INLINE:
226
                    throw new Exception('Writing of inline not implemented yet.');
227
228
                    break;
229
                case DataType::TYPE_NUMERIC:
230 4
                    $objWriter->writeAttribute('office:value-type', 'float');
231 4
                    $objWriter->writeAttribute('office:value', $cell->getValue());
232 4
                    $objWriter->writeElement('text:p', $cell->getValue());
233
234 4
                    break;
235
                case DataType::TYPE_STRING:
236 5
                    $objWriter->writeAttribute('office:value-type', 'string');
237 5
                    $objWriter->writeElement('text:p', $cell->getValue());
238
239 5
                    break;
240
            }
241 7
            Comment::write($objWriter, $cell);
242 7
            $objWriter->endElement();
243 7
            $prevColumn = $column;
244 7
            $cells->next();
245
        }
246 7
        $numberColsRepeated = $numberColsRepeated - $prevColumn - 1;
247 7
        if ($numberColsRepeated > 0) {
248 7
            if ($numberColsRepeated > 1) {
249 7
                $objWriter->startElement('table:table-cell');
250 7
                $objWriter->writeAttribute('table:number-columns-repeated', $numberColsRepeated);
251 7
                $objWriter->endElement();
252
            } else {
253
                $objWriter->writeElement('table:table-cell');
254
            }
255
        }
256 7
    }
257
258
    /**
259
     * Write span.
260
     *
261
     * @param XMLWriter $objWriter
262
     * @param int $curColumn
263
     * @param int $prevColumn
264
     */
265 7
    private function writeCellSpan(XMLWriter $objWriter, $curColumn, $prevColumn)
266
    {
267 7
        $diff = $curColumn - $prevColumn - 1;
268 7
        if (1 === $diff) {
269
            $objWriter->writeElement('table:table-cell');
270 7
        } elseif ($diff > 1) {
271
            $objWriter->startElement('table:table-cell');
272
            $objWriter->writeAttribute('table:number-columns-repeated', $diff);
273
            $objWriter->endElement();
274
        }
275 7
    }
276
277
    /**
278
     * Write XF cell styles.
279
     *
280
     * @param XMLWriter $writer
281
     * @param Spreadsheet $spreadsheet
282
     */
283 7
    private function writeXfStyles(XMLWriter $writer, Spreadsheet $spreadsheet)
284
    {
285 7
        foreach ($spreadsheet->getCellXfCollection() as $style) {
286 7
            $writer->startElement('style:style');
287 7
            $writer->writeAttribute('style:name', self::CELL_STYLE_PREFIX . $style->getIndex());
288 7
            $writer->writeAttribute('style:family', 'table-cell');
289 7
            $writer->writeAttribute('style:parent-style-name', 'Default');
290
291
            // style:text-properties
292
293
            // Font
294 7
            $writer->startElement('style:text-properties');
295
296 7
            $font = $style->getFont();
297
298 7
            if ($font->getBold()) {
299 1
                $writer->writeAttribute('fo:font-weight', 'bold');
300 1
                $writer->writeAttribute('style:font-weight-complex', 'bold');
301 1
                $writer->writeAttribute('style:font-weight-asian', 'bold');
302
            }
303
304 7
            if ($font->getItalic()) {
305 1
                $writer->writeAttribute('fo:font-style', 'italic');
306
            }
307
308 7
            if ($color = $font->getColor()) {
309 7
                $writer->writeAttribute('fo:color', sprintf('#%s', $color->getRGB()));
310
            }
311
312 7
            if ($family = $font->getName()) {
313 7
                $writer->writeAttribute('fo:font-family', $family);
314
            }
315
316 7
            if ($size = $font->getSize()) {
317 7
                $writer->writeAttribute('fo:font-size', sprintf('%.1Fpt', $size));
318
            }
319
320 7
            if ($font->getUnderline() && $font->getUnderline() != Font::UNDERLINE_NONE) {
321 1
                $writer->writeAttribute('style:text-underline-style', 'solid');
322 1
                $writer->writeAttribute('style:text-underline-width', 'auto');
323 1
                $writer->writeAttribute('style:text-underline-color', 'font-color');
324
325 1
                switch ($font->getUnderline()) {
326
                    case Font::UNDERLINE_DOUBLE:
327 1
                        $writer->writeAttribute('style:text-underline-type', 'double');
328
329 1
                        break;
330
                    case Font::UNDERLINE_SINGLE:
331 1
                        $writer->writeAttribute('style:text-underline-type', 'single');
332
333 1
                        break;
334
                }
335
            }
336
337 7
            $writer->endElement(); // Close style:text-properties
338
339
            // style:table-cell-properties
340
341 7
            $writer->startElement('style:table-cell-properties');
342 7
            $writer->writeAttribute('style:rotation-align', 'none');
343
344
            // Fill
345 7
            if ($fill = $style->getFill()) {
346 7
                switch ($fill->getFillType()) {
347
                    case Fill::FILL_SOLID:
348 1
                        $writer->writeAttribute('fo:background-color', sprintf(
349 1
                            '#%s',
350 1
                            strtolower($fill->getStartColor()->getRGB())
351
                        ));
352
353 1
                        break;
354
                    case Fill::FILL_GRADIENT_LINEAR:
355
                    case Fill::FILL_GRADIENT_PATH:
356
                        /// TODO :: To be implemented
357
                        break;
358
                    case Fill::FILL_NONE:
359
                    default:
360
                }
361
            }
362
363 7
            $writer->endElement(); // Close style:table-cell-properties
364
365
            // End
366
367 7
            $writer->endElement(); // Close style:style
368
        }
369 7
    }
370
371
    /**
372
     * Write attributes for merged cell.
373
     *
374
     * @param XMLWriter $objWriter
375
     * @param Cell $cell
376
     *
377
     * @throws \PhpOffice\PhpSpreadsheet\Exception
378
     */
379 7
    private function writeCellMerge(XMLWriter $objWriter, Cell $cell)
380
    {
381 7
        if (!$cell->isMergeRangeValueCell()) {
382 7
            return;
383
        }
384
385 1
        $mergeRange = Coordinate::splitRange($cell->getMergeRange());
386 1
        [$startCell, $endCell] = $mergeRange[0];
387 1
        $start = Coordinate::coordinateFromString($startCell);
388 1
        $end = Coordinate::coordinateFromString($endCell);
389 1
        $columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1;
390 1
        $rowSpan = $end[1] - $start[1] + 1;
391
392 1
        $objWriter->writeAttribute('table:number-columns-spanned', $columnSpan);
393 1
        $objWriter->writeAttribute('table:number-rows-spanned', $rowSpan);
394 1
    }
395
}
396