Completed
Push — develop ( 004a19...276177 )
by Adrien
21:44 queued 07:25
created

Worksheet::writeCols()   B

Complexity

Conditions 9
Paths 66

Size

Total Lines 57
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 9

Importance

Changes 0
Metric Value
cc 9
eloc 25
nc 66
nop 2
dl 0
loc 57
ccs 25
cts 25
cp 1
crap 9
rs 7.0745
c 0
b 0
f 0

How to fix   Long Method   

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\Xlsx;
4
5
/*
6
 * PhpSpreadsheet.
7
 *
8
 * Copyright (c) 2006 - 2015 PhpSpreadsheet
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
 *
24
 * @category   PhpSpreadsheet
25
 *
26
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
27
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
28
 */
29
use PhpOffice\PhpSpreadsheet\Cell;
30
use PhpOffice\PhpSpreadsheet\RichText;
31
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
32
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
33
use PhpOffice\PhpSpreadsheet\Style\Conditional;
34
use PhpOffice\PhpSpreadsheet\Worksheet as PhpspreadsheetWorksheet;
35
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
36
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
37
use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
38
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
39
40
/**
41
 * @category   PhpSpreadsheet
42
 *
43
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
44
 */
45
class Worksheet extends WriterPart
46
{
47
    /**
48
     * Write worksheet to XML format.
49
     *
50
     * @param PhpspreadsheetWorksheet $pSheet
51
     * @param string[] $pStringTable
52
     * @param bool $includeCharts Flag indicating if we should write charts
53
     *
54
     * @throws WriterException
55
     *
56
     * @return string XML Output
57
     */
58 56
    public function writeWorksheet($pSheet = null, $pStringTable = null, $includeCharts = false)
59
    {
60 56
        if (!is_null($pSheet)) {
61
            // Create XML writer
62 56
            $objWriter = null;
0 ignored issues
show
Unused Code introduced by
$objWriter is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
63 56 View Code Duplication
            if ($this->getParentWriter()->getUseDiskCaching()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
64
                $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
65
            } else {
66 56
                $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
67
            }
68
69
            // XML header
70 56
            $objWriter->startDocument('1.0', 'UTF-8', 'yes');
71
72
            // Worksheet
73 56
            $objWriter->startElement('worksheet');
74 56
            $objWriter->writeAttribute('xml:space', 'preserve');
75 56
            $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
76 56
            $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
77
78
                // sheetPr
79 56
                $this->writeSheetPr($objWriter, $pSheet);
80
81
                // Dimension
82 56
                $this->writeDimension($objWriter, $pSheet);
83
84
                // sheetViews
85 56
                $this->writeSheetViews($objWriter, $pSheet);
86
87
                // sheetFormatPr
88 56
                $this->writeSheetFormatPr($objWriter, $pSheet);
89
90
                // cols
91 56
                $this->writeCols($objWriter, $pSheet);
92
93
                // sheetData
94 56
                $this->writeSheetData($objWriter, $pSheet, $pStringTable);
0 ignored issues
show
Bug introduced by
It seems like $pStringTable defined by parameter $pStringTable on line 58 can also be of type null; however, PhpOffice\PhpSpreadsheet...sheet::writeSheetData() does only seem to accept array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
95
96
                // sheetProtection
97 56
                $this->writeSheetProtection($objWriter, $pSheet);
98
99
                // protectedRanges
100 56
                $this->writeProtectedRanges($objWriter, $pSheet);
101
102
                // autoFilter
103 56
                $this->writeAutoFilter($objWriter, $pSheet);
104
105
                // mergeCells
106 56
                $this->writeMergeCells($objWriter, $pSheet);
107
108
                // conditionalFormatting
109 56
                $this->writeConditionalFormatting($objWriter, $pSheet);
110
111
                // dataValidations
112 56
                $this->writeDataValidations($objWriter, $pSheet);
113
114
                // hyperlinks
115 56
                $this->writeHyperlinks($objWriter, $pSheet);
116
117
                // Print options
118 56
                $this->writePrintOptions($objWriter, $pSheet);
119
120
                // Page margins
121 56
                $this->writePageMargins($objWriter, $pSheet);
122
123
                // Page setup
124 56
                $this->writePageSetup($objWriter, $pSheet);
125
126
                // Header / footer
127 56
                $this->writeHeaderFooter($objWriter, $pSheet);
128
129
                // Breaks
130 56
                $this->writeBreaks($objWriter, $pSheet);
131
132
                // Drawings and/or Charts
133 56
                $this->writeDrawings($objWriter, $pSheet, $includeCharts);
134
135
                // LegacyDrawing
136 56
                $this->writeLegacyDrawing($objWriter, $pSheet);
137
138
                // LegacyDrawingHF
139 56
                $this->writeLegacyDrawingHF($objWriter, $pSheet);
140
141 56
            $objWriter->endElement();
142
143
            // Return
144 56
            return $objWriter->getData();
145
        }
146
        throw new WriterException('Invalid \\PhpOffice\\PhpSpreadsheet\\Worksheet object passed.');
147
    }
148
149
    /**
150
     * Write SheetPr.
151
     *
152
     * @param XMLWriter $objWriter XML Writer
153
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
154
     *
155
     * @throws WriterException
156
     */
157 56
    private function writeSheetPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
158
    {
159
        // sheetPr
160 56
        $objWriter->startElement('sheetPr');
161 56
        if ($pSheet->getParent()->hasMacros()) {
162
            //if the workbook have macros, we need to have codeName for the sheet
163
            if ($pSheet->hasCodeName() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
164
                $pSheet->setCodeName($pSheet->getTitle());
165
            }
166
            $objWriter->writeAttribute('codeName', $pSheet->getCodeName());
167
        }
168 56
        $autoFilterRange = $pSheet->getAutoFilter()->getRange();
169 56
        if (!empty($autoFilterRange)) {
170 3
            $objWriter->writeAttribute('filterMode', 1);
171 3
            $pSheet->getAutoFilter()->showHideRows();
172
        }
173
174
        // tabColor
175 56
        if ($pSheet->isTabColorSet()) {
176 6
            $objWriter->startElement('tabColor');
177 6
            $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB());
178 6
            $objWriter->endElement();
179
        }
180
181
        // outlinePr
182 56
        $objWriter->startElement('outlinePr');
183 56
        $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0'));
184 56
        $objWriter->writeAttribute('summaryRight', ($pSheet->getShowSummaryRight() ? '1' : '0'));
185 56
        $objWriter->endElement();
186
187
        // pageSetUpPr
188 56
        if ($pSheet->getPageSetup()->getFitToPage()) {
189
            $objWriter->startElement('pageSetUpPr');
190
            $objWriter->writeAttribute('fitToPage', '1');
191
            $objWriter->endElement();
192
        }
193
194 56
        $objWriter->endElement();
195 56
    }
196
197
    /**
198
     * Write Dimension.
199
     *
200
     * @param XMLWriter $objWriter XML Writer
201
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
202
     *
203
     * @throws WriterException
204
     */
205 56
    private function writeDimension(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
206
    {
207
        // dimension
208 56
        $objWriter->startElement('dimension');
209 56
        $objWriter->writeAttribute('ref', $pSheet->calculateWorksheetDimension());
210 56
        $objWriter->endElement();
211 56
    }
212
213
    /**
214
     * Write SheetViews.
215
     *
216
     * @param XMLWriter $objWriter XML Writer
217
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
218
     *
219
     * @throws WriterException
220
     */
221 56
    private function writeSheetViews(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
222
    {
223
        // sheetViews
224 56
        $objWriter->startElement('sheetViews');
225
226
        // Sheet selected?
227 56
        $sheetSelected = false;
228 56
        if ($this->getParentWriter()->getSpreadsheet()->getIndex($pSheet) == $this->getParentWriter()->getSpreadsheet()->getActiveSheetIndex()) {
229 56
            $sheetSelected = true;
230
        }
231
232
        // sheetView
233 56
        $objWriter->startElement('sheetView');
234 56
        $objWriter->writeAttribute('tabSelected', $sheetSelected ? '1' : '0');
235 56
        $objWriter->writeAttribute('workbookViewId', '0');
236
237
        // Zoom scales
238 56
        if ($pSheet->getSheetView()->getZoomScale() != 100) {
239
            $objWriter->writeAttribute('zoomScale', $pSheet->getSheetView()->getZoomScale());
240
        }
241 56
        if ($pSheet->getSheetView()->getZoomScaleNormal() != 100) {
242
            $objWriter->writeAttribute('zoomScaleNormal', $pSheet->getSheetView()->getZoomScaleNormal());
243
        }
244
245
        // View Layout Type
246 56
        if ($pSheet->getSheetView()->getView() !== SheetView::SHEETVIEW_NORMAL) {
247 1
            $objWriter->writeAttribute('view', $pSheet->getSheetView()->getView());
248
        }
249
250
        // Gridlines
251 56
        if ($pSheet->getShowGridlines()) {
252 56
            $objWriter->writeAttribute('showGridLines', 'true');
253
        } else {
254
            $objWriter->writeAttribute('showGridLines', 'false');
255
        }
256
257
        // Row and column headers
258 56
        if ($pSheet->getShowRowColHeaders()) {
259 56
            $objWriter->writeAttribute('showRowColHeaders', '1');
260
        } else {
261
            $objWriter->writeAttribute('showRowColHeaders', '0');
262
        }
263
264
        // Right-to-left
265 56
        if ($pSheet->getRightToLeft()) {
266
            $objWriter->writeAttribute('rightToLeft', 'true');
267
        }
268
269 56
        $activeCell = $pSheet->getActiveCell();
270
271
        // Pane
272 56
        $pane = '';
273 56
        $topLeftCell = $pSheet->getFreezePane();
274 56
        if (($topLeftCell != '') && ($topLeftCell != 'A1')) {
275 3
            $activeCell = $topLeftCell;
276
            // Calculate freeze coordinates
277 3
            $xSplit = $ySplit = 0;
278
279 3
            list($xSplit, $ySplit) = Cell::coordinateFromString($topLeftCell);
280 3
            $xSplit = Cell::columnIndexFromString($xSplit);
281
282
            // pane
283 3
            $pane = 'topRight';
284 3
            $objWriter->startElement('pane');
285 3
            if ($xSplit > 1) {
286
                $objWriter->writeAttribute('xSplit', $xSplit - 1);
287
            }
288 3
            if ($ySplit > 1) {
289 3
                $objWriter->writeAttribute('ySplit', $ySplit - 1);
290 3
                $pane = ($xSplit > 1) ? 'bottomRight' : 'bottomLeft';
291
            }
292 3
            $objWriter->writeAttribute('topLeftCell', $topLeftCell);
293 3
            $objWriter->writeAttribute('activePane', $pane);
294 3
            $objWriter->writeAttribute('state', 'frozen');
295 3
            $objWriter->endElement();
296
297 3
            if (($xSplit > 1) && ($ySplit > 1)) {
298
                //    Write additional selections if more than two panes (ie both an X and a Y split)
299
                $objWriter->startElement('selection');
300
                $objWriter->writeAttribute('pane', 'topRight');
301
                $objWriter->endElement();
302
                $objWriter->startElement('selection');
303
                $objWriter->writeAttribute('pane', 'bottomLeft');
304
                $objWriter->endElement();
305
            }
306
        }
307
308
        // Selection
309
        // Only need to write selection element if we have a split pane
310
        // We cheat a little by over-riding the active cell selection, setting it to the split cell
311 56
        $objWriter->startElement('selection');
312 56
        if ($pane != '') {
313 3
            $objWriter->writeAttribute('pane', $pane);
314
        }
315 56
        $objWriter->writeAttribute('activeCell', $activeCell);
316 56
        $objWriter->writeAttribute('sqref', $activeCell);
317 56
        $objWriter->endElement();
318
319 56
        $objWriter->endElement();
320
321 56
        $objWriter->endElement();
322 56
    }
323
324
    /**
325
     * Write SheetFormatPr.
326
     *
327
     * @param XMLWriter $objWriter XML Writer
328
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
329
     *
330
     * @throws WriterException
331
     */
332 56
    private function writeSheetFormatPr(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
333
    {
334
        // sheetFormatPr
335 56
        $objWriter->startElement('sheetFormatPr');
336
337
        // Default row height
338 56
        if ($pSheet->getDefaultRowDimension()->getRowHeight() >= 0) {
339 2
            $objWriter->writeAttribute('customHeight', 'true');
340 2
            $objWriter->writeAttribute('defaultRowHeight', StringHelper::formatNumber($pSheet->getDefaultRowDimension()->getRowHeight()));
341
        } else {
342 54
            $objWriter->writeAttribute('defaultRowHeight', '14.4');
343
        }
344
345
        // Set Zero Height row
346 56
        if ((string) $pSheet->getDefaultRowDimension()->getZeroHeight() == '1' ||
347 56
            strtolower((string) $pSheet->getDefaultRowDimension()->getZeroHeight()) == 'true') {
348
            $objWriter->writeAttribute('zeroHeight', '1');
349
        }
350
351
        // Default column width
352 56
        if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) {
353 1
            $objWriter->writeAttribute('defaultColWidth', StringHelper::formatNumber($pSheet->getDefaultColumnDimension()->getWidth()));
354
        }
355
356
        // Outline level - row
357 56
        $outlineLevelRow = 0;
358 56
        foreach ($pSheet->getRowDimensions() as $dimension) {
359 11
            if ($dimension->getOutlineLevel() > $outlineLevelRow) {
360 11
                $outlineLevelRow = $dimension->getOutlineLevel();
361
            }
362
        }
363 56
        $objWriter->writeAttribute('outlineLevelRow', (int) $outlineLevelRow);
364
365
        // Outline level - column
366 56
        $outlineLevelCol = 0;
367 56
        foreach ($pSheet->getColumnDimensions() as $dimension) {
368 21
            if ($dimension->getOutlineLevel() > $outlineLevelCol) {
369 21
                $outlineLevelCol = $dimension->getOutlineLevel();
370
            }
371
        }
372 56
        $objWriter->writeAttribute('outlineLevelCol', (int) $outlineLevelCol);
373
374 56
        $objWriter->endElement();
375 56
    }
376
377
    /**
378
     * Write Cols.
379
     *
380
     * @param XMLWriter $objWriter XML Writer
381
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
382
     *
383
     * @throws WriterException
384
     */
385 56
    private function writeCols(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
386
    {
387
        // cols
388 56
        if (count($pSheet->getColumnDimensions()) > 0) {
389 21
            $objWriter->startElement('cols');
390
391 21
            $pSheet->calculateColumnWidths();
392
393
            // Loop through column dimensions
394 21
            foreach ($pSheet->getColumnDimensions() as $colDimension) {
395
                // col
396 21
                $objWriter->startElement('col');
397 21
                $objWriter->writeAttribute('min', Cell::columnIndexFromString($colDimension->getColumnIndex()));
398 21
                $objWriter->writeAttribute('max', Cell::columnIndexFromString($colDimension->getColumnIndex()));
399
400 21
                if ($colDimension->getWidth() < 0) {
401
                    // No width set, apply default of 10
402 2
                    $objWriter->writeAttribute('width', '9.10');
403
                } else {
404
                    // Width set
405 21
                    $objWriter->writeAttribute('width', StringHelper::formatNumber($colDimension->getWidth()));
406
                }
407
408
                // Column visibility
409 21
                if ($colDimension->getVisible() == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
410 3
                    $objWriter->writeAttribute('hidden', 'true');
411
                }
412
413
                // Auto size?
414 21
                if ($colDimension->getAutoSize()) {
415 8
                    $objWriter->writeAttribute('bestFit', 'true');
416
                }
417
418
                // Custom width?
419 21
                if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) {
420 21
                    $objWriter->writeAttribute('customWidth', 'true');
421
                }
422
423
                // Collapsed
424 21
                if ($colDimension->getCollapsed() == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
425 1
                    $objWriter->writeAttribute('collapsed', 'true');
426
                }
427
428
                // Outline level
429 21
                if ($colDimension->getOutlineLevel() > 0) {
430 1
                    $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel());
431
                }
432
433
                // Style
434 21
                $objWriter->writeAttribute('style', $colDimension->getXfIndex());
435
436 21
                $objWriter->endElement();
437
            }
438
439 21
            $objWriter->endElement();
440
        }
441 56
    }
442
443
    /**
444
     * Write SheetProtection.
445
     *
446
     * @param XMLWriter $objWriter XML Writer
447
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
448
     *
449
     * @throws WriterException
450
     */
451 56
    private function writeSheetProtection(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
452
    {
453
        // sheetProtection
454 56
        $objWriter->startElement('sheetProtection');
455
456 56
        if ($pSheet->getProtection()->getPassword() != '') {
457 1
            $objWriter->writeAttribute('password', $pSheet->getProtection()->getPassword());
458
        }
459
460 56
        $objWriter->writeAttribute('sheet', ($pSheet->getProtection()->getSheet() ? 'true' : 'false'));
461 56
        $objWriter->writeAttribute('objects', ($pSheet->getProtection()->getObjects() ? 'true' : 'false'));
462 56
        $objWriter->writeAttribute('scenarios', ($pSheet->getProtection()->getScenarios() ? 'true' : 'false'));
463 56
        $objWriter->writeAttribute('formatCells', ($pSheet->getProtection()->getFormatCells() ? 'true' : 'false'));
464 56
        $objWriter->writeAttribute('formatColumns', ($pSheet->getProtection()->getFormatColumns() ? 'true' : 'false'));
465 56
        $objWriter->writeAttribute('formatRows', ($pSheet->getProtection()->getFormatRows() ? 'true' : 'false'));
466 56
        $objWriter->writeAttribute('insertColumns', ($pSheet->getProtection()->getInsertColumns() ? 'true' : 'false'));
467 56
        $objWriter->writeAttribute('insertRows', ($pSheet->getProtection()->getInsertRows() ? 'true' : 'false'));
468 56
        $objWriter->writeAttribute('insertHyperlinks', ($pSheet->getProtection()->getInsertHyperlinks() ? 'true' : 'false'));
469 56
        $objWriter->writeAttribute('deleteColumns', ($pSheet->getProtection()->getDeleteColumns() ? 'true' : 'false'));
470 56
        $objWriter->writeAttribute('deleteRows', ($pSheet->getProtection()->getDeleteRows() ? 'true' : 'false'));
471 56
        $objWriter->writeAttribute('selectLockedCells', ($pSheet->getProtection()->getSelectLockedCells() ? 'true' : 'false'));
472 56
        $objWriter->writeAttribute('sort', ($pSheet->getProtection()->getSort() ? 'true' : 'false'));
473 56
        $objWriter->writeAttribute('autoFilter', ($pSheet->getProtection()->getAutoFilter() ? 'true' : 'false'));
474 56
        $objWriter->writeAttribute('pivotTables', ($pSheet->getProtection()->getPivotTables() ? 'true' : 'false'));
475 56
        $objWriter->writeAttribute('selectUnlockedCells', ($pSheet->getProtection()->getSelectUnlockedCells() ? 'true' : 'false'));
476 56
        $objWriter->endElement();
477 56
    }
478
479
    /**
480
     * Write ConditionalFormatting.
481
     *
482
     * @param XMLWriter $objWriter XML Writer
483
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
484
     *
485
     * @throws WriterException
486
     */
487 56
    private function writeConditionalFormatting(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
488
    {
489
        // Conditional id
490 56
        $id = 1;
491
492
        // Loop through styles in the current worksheet
493 56
        foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
494 2
            foreach ($conditionalStyles as $conditional) {
495
                // WHY was this again?
496
                // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()) == '') {
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
497
                //    continue;
498
                // }
499 2
                if ($conditional->getConditionType() != Conditional::CONDITION_NONE) {
500
                    // conditionalFormatting
501 2
                    $objWriter->startElement('conditionalFormatting');
502 2
                    $objWriter->writeAttribute('sqref', $cellCoordinate);
503
504
                    // cfRule
505 2
                    $objWriter->startElement('cfRule');
506 2
                    $objWriter->writeAttribute('type', $conditional->getConditionType());
507 2
                    $objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()));
508 2
                    $objWriter->writeAttribute('priority', $id++);
509
510 2
                    if (($conditional->getConditionType() == Conditional::CONDITION_CELLIS || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT)
511 2
                        && $conditional->getOperatorType() != Conditional::OPERATOR_NONE) {
512 2
                        $objWriter->writeAttribute('operator', $conditional->getOperatorType());
513
                    }
514
515 2
                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
516 2
                        && !is_null($conditional->getText())) {
517
                        $objWriter->writeAttribute('text', $conditional->getText());
518
                    }
519
520 2
                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
521 2
                        && $conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT
522 2
                        && !is_null($conditional->getText())) {
523
                        $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))');
524 2 View Code Duplication
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
525 2
                        && $conditional->getOperatorType() == Conditional::OPERATOR_BEGINSWITH
526 2
                        && !is_null($conditional->getText())) {
527
                        $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
528 2
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
529 2
                        && $conditional->getOperatorType() == Conditional::OPERATOR_ENDSWITH
530 2
                        && !is_null($conditional->getText())) {
531
                        $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
532 2 View Code Duplication
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
533 2
                        && $conditional->getOperatorType() == Conditional::OPERATOR_NOTCONTAINS
534 2
                        && !is_null($conditional->getText())) {
535
                        $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))');
536 2
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CELLIS
537
                        || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
538 2
                        || $conditional->getConditionType() == Conditional::CONDITION_EXPRESSION) {
539 2
                        foreach ($conditional->getConditions() as $formula) {
540
                            // Formula
541 2
                            $objWriter->writeElement('formula', $formula);
542
                        }
543
                    }
544
545 2
                    $objWriter->endElement();
546
547 2
                    $objWriter->endElement();
548
                }
549
            }
550
        }
551 56
    }
552
553
    /**
554
     * Write DataValidations.
555
     *
556
     * @param XMLWriter $objWriter XML Writer
557
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
558
     *
559
     * @throws WriterException
560
     */
561 56
    private function writeDataValidations(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
562
    {
563
        // Datavalidation collection
564 56
        $dataValidationCollection = $pSheet->getDataValidationCollection();
565
566
        // Write data validations?
567 56
        if (!empty($dataValidationCollection)) {
568 2
            $dataValidationCollection = Cell::mergeRangesInCollection($dataValidationCollection);
569 2
            $objWriter->startElement('dataValidations');
570 2
            $objWriter->writeAttribute('count', count($dataValidationCollection));
571
572 2
            foreach ($dataValidationCollection as $coordinate => $dv) {
573 2
                $objWriter->startElement('dataValidation');
574
575 2
                if ($dv->getType() != '') {
576 2
                    $objWriter->writeAttribute('type', $dv->getType());
577
                }
578
579 2
                if ($dv->getErrorStyle() != '') {
580 2
                    $objWriter->writeAttribute('errorStyle', $dv->getErrorStyle());
581
                }
582
583 2
                if ($dv->getOperator() != '') {
584 2
                    $objWriter->writeAttribute('operator', $dv->getOperator());
585
                }
586
587 2
                $objWriter->writeAttribute('allowBlank', ($dv->getAllowBlank() ? '1' : '0'));
588 2
                $objWriter->writeAttribute('showDropDown', (!$dv->getShowDropDown() ? '1' : '0'));
589 2
                $objWriter->writeAttribute('showInputMessage', ($dv->getShowInputMessage() ? '1' : '0'));
590 2
                $objWriter->writeAttribute('showErrorMessage', ($dv->getShowErrorMessage() ? '1' : '0'));
591
592 2
                if ($dv->getErrorTitle() !== '') {
593 2
                    $objWriter->writeAttribute('errorTitle', $dv->getErrorTitle());
594
                }
595 2
                if ($dv->getError() !== '') {
596 2
                    $objWriter->writeAttribute('error', $dv->getError());
597
                }
598 2
                if ($dv->getPromptTitle() !== '') {
599 2
                    $objWriter->writeAttribute('promptTitle', $dv->getPromptTitle());
600
                }
601 2
                if ($dv->getPrompt() !== '') {
602 2
                    $objWriter->writeAttribute('prompt', $dv->getPrompt());
603
                }
604
605 2
                $objWriter->writeAttribute('sqref', $coordinate);
606
607 2
                if ($dv->getFormula1() !== '') {
608 2
                    $objWriter->writeElement('formula1', $dv->getFormula1());
609
                }
610 2
                if ($dv->getFormula2() !== '') {
611 1
                    $objWriter->writeElement('formula2', $dv->getFormula2());
612
                }
613
614 2
                $objWriter->endElement();
615
            }
616
617 2
            $objWriter->endElement();
618
        }
619 56
    }
620
621
    /**
622
     * Write Hyperlinks.
623
     *
624
     * @param XMLWriter $objWriter XML Writer
625
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
626
     *
627
     * @throws WriterException
628
     */
629 56
    private function writeHyperlinks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
630
    {
631
        // Hyperlink collection
632 56
        $hyperlinkCollection = $pSheet->getHyperlinkCollection();
633
634
        // Relation ID
635 56
        $relationId = 1;
636
637
        // Write hyperlinks?
638 56
        if (!empty($hyperlinkCollection)) {
639 9
            $objWriter->startElement('hyperlinks');
640
641 9
            foreach ($hyperlinkCollection as $coordinate => $hyperlink) {
642 9
                $objWriter->startElement('hyperlink');
643
644 9
                $objWriter->writeAttribute('ref', $coordinate);
645 9
                if (!$hyperlink->isInternal()) {
646 9
                    $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId);
647 9
                    ++$relationId;
648
                } else {
649 7
                    $objWriter->writeAttribute('location', str_replace('sheet://', '', $hyperlink->getUrl()));
650
                }
651
652 9
                if ($hyperlink->getTooltip() != '') {
653 6
                    $objWriter->writeAttribute('tooltip', $hyperlink->getTooltip());
654
                }
655
656 9
                $objWriter->endElement();
657
            }
658
659 9
            $objWriter->endElement();
660
        }
661 56
    }
662
663
    /**
664
     * Write ProtectedRanges.
665
     *
666
     * @param XMLWriter $objWriter XML Writer
667
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
668
     *
669
     * @throws WriterException
670
     */
671 56
    private function writeProtectedRanges(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
672
    {
673 56
        if (count($pSheet->getProtectedCells()) > 0) {
674
            // protectedRanges
675 6
            $objWriter->startElement('protectedRanges');
676
677
            // Loop protectedRanges
678 6
            foreach ($pSheet->getProtectedCells() as $protectedCell => $passwordHash) {
679
                // protectedRange
680 6
                $objWriter->startElement('protectedRange');
681 6
                $objWriter->writeAttribute('name', 'p' . md5($protectedCell));
682 6
                $objWriter->writeAttribute('sqref', $protectedCell);
683 6
                if (!empty($passwordHash)) {
684 6
                    $objWriter->writeAttribute('password', $passwordHash);
685
                }
686 6
                $objWriter->endElement();
687
            }
688
689 6
            $objWriter->endElement();
690
        }
691 56
    }
692
693
    /**
694
     * Write MergeCells.
695
     *
696
     * @param XMLWriter $objWriter XML Writer
697
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
698
     *
699
     * @throws WriterException
700
     */
701 56
    private function writeMergeCells(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
702
    {
703 56
        if (count($pSheet->getMergeCells()) > 0) {
704
            // mergeCells
705 11
            $objWriter->startElement('mergeCells');
706
707
            // Loop mergeCells
708 11
            foreach ($pSheet->getMergeCells() as $mergeCell) {
709
                // mergeCell
710 11
                $objWriter->startElement('mergeCell');
711 11
                $objWriter->writeAttribute('ref', $mergeCell);
712 11
                $objWriter->endElement();
713
            }
714
715 11
            $objWriter->endElement();
716
        }
717 56
    }
718
719
    /**
720
     * Write PrintOptions.
721
     *
722
     * @param XMLWriter $objWriter XML Writer
723
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
724
     *
725
     * @throws WriterException
726
     */
727 56
    private function writePrintOptions(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
728
    {
729
        // printOptions
730 56
        $objWriter->startElement('printOptions');
731
732 56
        $objWriter->writeAttribute('gridLines', ($pSheet->getPrintGridlines() ? 'true' : 'false'));
733 56
        $objWriter->writeAttribute('gridLinesSet', 'true');
734
735 56
        if ($pSheet->getPageSetup()->getHorizontalCentered()) {
736
            $objWriter->writeAttribute('horizontalCentered', 'true');
737
        }
738
739 56
        if ($pSheet->getPageSetup()->getVerticalCentered()) {
740
            $objWriter->writeAttribute('verticalCentered', 'true');
741
        }
742
743 56
        $objWriter->endElement();
744 56
    }
745
746
    /**
747
     * Write PageMargins.
748
     *
749
     * @param XMLWriter $objWriter XML Writer
750
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
751
     *
752
     * @throws WriterException
753
     */
754 56
    private function writePageMargins(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
755
    {
756
        // pageMargins
757 56
        $objWriter->startElement('pageMargins');
758 56
        $objWriter->writeAttribute('left', StringHelper::formatNumber($pSheet->getPageMargins()->getLeft()));
759 56
        $objWriter->writeAttribute('right', StringHelper::formatNumber($pSheet->getPageMargins()->getRight()));
760 56
        $objWriter->writeAttribute('top', StringHelper::formatNumber($pSheet->getPageMargins()->getTop()));
761 56
        $objWriter->writeAttribute('bottom', StringHelper::formatNumber($pSheet->getPageMargins()->getBottom()));
762 56
        $objWriter->writeAttribute('header', StringHelper::formatNumber($pSheet->getPageMargins()->getHeader()));
763 56
        $objWriter->writeAttribute('footer', StringHelper::formatNumber($pSheet->getPageMargins()->getFooter()));
764 56
        $objWriter->endElement();
765 56
    }
766
767
    /**
768
     * Write AutoFilter.
769
     *
770
     * @param XMLWriter $objWriter XML Writer
771
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
772
     *
773
     * @throws WriterException
774
     */
775 56
    private function writeAutoFilter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
776
    {
777 56
        $autoFilterRange = $pSheet->getAutoFilter()->getRange();
778 56
        if (!empty($autoFilterRange)) {
779
            // autoFilter
780 3
            $objWriter->startElement('autoFilter');
781
782
            // Strip any worksheet reference from the filter coordinates
783 3
            $range = Cell::splitRange($autoFilterRange);
784 3
            $range = $range[0];
785
            //    Strip any worksheet ref
786 3 View Code Duplication
            if (strpos($range[0], '!') !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
787
                list($ws, $range[0]) = explode('!', $range[0]);
0 ignored issues
show
Unused Code introduced by
The assignment to $ws is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
788
            }
789 3
            $range = implode(':', $range);
790
791 3
            $objWriter->writeAttribute('ref', str_replace('$', '', $range));
792
793 3
            $columns = $pSheet->getAutoFilter()->getColumns();
794 3
            if (count($columns) > 0) {
795 2
                foreach ($columns as $columnID => $column) {
796 2
                    $rules = $column->getRules();
797 2
                    if (count($rules) > 0) {
798 2
                        $objWriter->startElement('filterColumn');
799 2
                        $objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID));
800
801 2
                        $objWriter->startElement($column->getFilterType());
802 2
                        if ($column->getJoin() == Column::AUTOFILTER_COLUMN_JOIN_AND) {
803 1
                            $objWriter->writeAttribute('and', 1);
804
                        }
805
806 2
                        foreach ($rules as $rule) {
807 2
                            if (($column->getFilterType() === Column::AUTOFILTER_FILTERTYPE_FILTER) &&
808 2
                                ($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_EQUAL) &&
809 2
                                ($rule->getValue() === '')) {
810
                                //    Filter rule for Blanks
811 1
                                $objWriter->writeAttribute('blank', 1);
812 2
                            } elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) {
813
                                //    Dynamic Filter Rule
814 1
                                $objWriter->writeAttribute('type', $rule->getGrouping());
815 1
                                $val = $column->getAttribute('val');
816 1
                                if ($val !== null) {
817 1
                                    $objWriter->writeAttribute('val', $val);
818
                                }
819 1
                                $maxVal = $column->getAttribute('maxVal');
820 1
                                if ($maxVal !== null) {
821 1
                                    $objWriter->writeAttribute('maxVal', $maxVal);
822
                                }
823 2
                            } elseif ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) {
824
                                //    Top 10 Filter Rule
825
                                $objWriter->writeAttribute('val', $rule->getValue());
826
                                $objWriter->writeAttribute('percent', (($rule->getOperator() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0'));
827
                                $objWriter->writeAttribute('top', (($rule->getGrouping() === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1' : '0'));
828
                            } else {
829
                                //    Filter, DateGroupItem or CustomFilter
830 2
                                $objWriter->startElement($rule->getRuleType());
831
832 2
                                if ($rule->getOperator() !== Rule::AUTOFILTER_COLUMN_RULE_EQUAL) {
833 1
                                    $objWriter->writeAttribute('operator', $rule->getOperator());
834
                                }
835 2
                                if ($rule->getRuleType() === Rule::AUTOFILTER_RULETYPE_DATEGROUP) {
836
                                    // Date Group filters
837 1
                                    foreach ($rule->getValue() as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $rule->getValue() of type string is not traversable.
Loading history...
838 1
                                        if ($value > '') {
839 1
                                            $objWriter->writeAttribute($key, $value);
840
                                        }
841
                                    }
842 1
                                    $objWriter->writeAttribute('dateTimeGrouping', $rule->getGrouping());
843
                                } else {
844 2
                                    $objWriter->writeAttribute('val', $rule->getValue());
845
                                }
846
847 2
                                $objWriter->endElement();
848
                            }
849
                        }
850
851 2
                        $objWriter->endElement();
852
853 2
                        $objWriter->endElement();
854
                    }
855
                }
856
            }
857 3
            $objWriter->endElement();
858
        }
859 56
    }
860
861
    /**
862
     * Write PageSetup.
863
     *
864
     * @param XMLWriter $objWriter XML Writer
865
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
866
     *
867
     * @throws WriterException
868
     */
869 56
    private function writePageSetup(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
870
    {
871
        // pageSetup
872 56
        $objWriter->startElement('pageSetup');
873 56
        $objWriter->writeAttribute('paperSize', $pSheet->getPageSetup()->getPaperSize());
874 56
        $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation());
875
876 56
        if (!is_null($pSheet->getPageSetup()->getScale())) {
877 56
            $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale());
878
        }
879 56
        if (!is_null($pSheet->getPageSetup()->getFitToHeight())) {
880 56
            $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight());
881
        } else {
882
            $objWriter->writeAttribute('fitToHeight', '0');
883
        }
884 56
        if (!is_null($pSheet->getPageSetup()->getFitToWidth())) {
885 56
            $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth());
886
        } else {
887
            $objWriter->writeAttribute('fitToWidth', '0');
888
        }
889 56
        if (!is_null($pSheet->getPageSetup()->getFirstPageNumber())) {
890
            $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber());
891
            $objWriter->writeAttribute('useFirstPageNumber', '1');
892
        }
893
894 56
        $objWriter->endElement();
895 56
    }
896
897
    /**
898
     * Write Header / Footer.
899
     *
900
     * @param XMLWriter $objWriter XML Writer
901
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
902
     *
903
     * @throws WriterException
904
     */
905 56
    private function writeHeaderFooter(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
906
    {
907
        // headerFooter
908 56
        $objWriter->startElement('headerFooter');
909 56
        $objWriter->writeAttribute('differentOddEven', ($pSheet->getHeaderFooter()->getDifferentOddEven() ? 'true' : 'false'));
910 56
        $objWriter->writeAttribute('differentFirst', ($pSheet->getHeaderFooter()->getDifferentFirst() ? 'true' : 'false'));
911 56
        $objWriter->writeAttribute('scaleWithDoc', ($pSheet->getHeaderFooter()->getScaleWithDocument() ? 'true' : 'false'));
912 56
        $objWriter->writeAttribute('alignWithMargins', ($pSheet->getHeaderFooter()->getAlignWithMargins() ? 'true' : 'false'));
913
914 56
        $objWriter->writeElement('oddHeader', $pSheet->getHeaderFooter()->getOddHeader());
915 56
        $objWriter->writeElement('oddFooter', $pSheet->getHeaderFooter()->getOddFooter());
916 56
        $objWriter->writeElement('evenHeader', $pSheet->getHeaderFooter()->getEvenHeader());
917 56
        $objWriter->writeElement('evenFooter', $pSheet->getHeaderFooter()->getEvenFooter());
918 56
        $objWriter->writeElement('firstHeader', $pSheet->getHeaderFooter()->getFirstHeader());
919 56
        $objWriter->writeElement('firstFooter', $pSheet->getHeaderFooter()->getFirstFooter());
920 56
        $objWriter->endElement();
921 56
    }
922
923
    /**
924
     * Write Breaks.
925
     *
926
     * @param XMLWriter $objWriter XML Writer
927
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
928
     *
929
     * @throws WriterException
930
     */
931 56
    private function writeBreaks(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
932
    {
933
        // Get row and column breaks
934 56
        $aRowBreaks = [];
935 56
        $aColumnBreaks = [];
936 56
        foreach ($pSheet->getBreaks() as $cell => $breakType) {
937 1
            if ($breakType == PhpspreadsheetWorksheet::BREAK_ROW) {
938 1
                $aRowBreaks[] = $cell;
939
            } elseif ($breakType == PhpspreadsheetWorksheet::BREAK_COLUMN) {
940 1
                $aColumnBreaks[] = $cell;
941
            }
942
        }
943
944
        // rowBreaks
945 56 View Code Duplication
        if (!empty($aRowBreaks)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
946 1
            $objWriter->startElement('rowBreaks');
947 1
            $objWriter->writeAttribute('count', count($aRowBreaks));
948 1
            $objWriter->writeAttribute('manualBreakCount', count($aRowBreaks));
949
950 1
            foreach ($aRowBreaks as $cell) {
951 1
                $coords = Cell::coordinateFromString($cell);
952
953 1
                $objWriter->startElement('brk');
954 1
                $objWriter->writeAttribute('id', $coords[1]);
955 1
                $objWriter->writeAttribute('man', '1');
956 1
                $objWriter->endElement();
957
            }
958
959 1
            $objWriter->endElement();
960
        }
961
962
        // Second, write column breaks
963 56 View Code Duplication
        if (!empty($aColumnBreaks)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
964
            $objWriter->startElement('colBreaks');
965
            $objWriter->writeAttribute('count', count($aColumnBreaks));
966
            $objWriter->writeAttribute('manualBreakCount', count($aColumnBreaks));
967
968
            foreach ($aColumnBreaks as $cell) {
969
                $coords = Cell::coordinateFromString($cell);
970
971
                $objWriter->startElement('brk');
972
                $objWriter->writeAttribute('id', Cell::columnIndexFromString($coords[0]) - 1);
973
                $objWriter->writeAttribute('man', '1');
974
                $objWriter->endElement();
975
            }
976
977
            $objWriter->endElement();
978
        }
979 56
    }
980
981
    /**
982
     * Write SheetData.
983
     *
984
     * @param XMLWriter $objWriter XML Writer
985
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
986
     * @param string[] $pStringTable String table
987
     *
988
     * @throws WriterException
989
     */
990 56
    private function writeSheetData(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, array $pStringTable)
991
    {
992
        // Flipped stringtable, for faster index searching
993 56
        $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart as the method flipStringTable() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
994
995
        // sheetData
996 56
        $objWriter->startElement('sheetData');
997
998
        // Get column count
999 56
        $colCount = Cell::columnIndexFromString($pSheet->getHighestColumn());
1000
1001
        // Highest row number
1002 56
        $highestRow = $pSheet->getHighestRow();
1003
1004
        // Loop through cells
1005 56
        $cellsByRow = [];
1006 56
        foreach ($pSheet->getCoordinates() as $coordinate) {
1007 56
            $cellAddress = Cell::coordinateFromString($coordinate);
1008 56
            $cellsByRow[$cellAddress[1]][] = $coordinate;
1009
        }
1010
1011 56
        $currentRow = 0;
1012 56
        while ($currentRow++ < $highestRow) {
1013
            // Get row dimension
1014 56
            $rowDimension = $pSheet->getRowDimension($currentRow);
1015
1016
            // Write current row?
1017 56
            $writeCurrentRow = isset($cellsByRow[$currentRow]) || $rowDimension->getRowHeight() >= 0 || $rowDimension->getVisible() == false || $rowDimension->getCollapsed() == true || $rowDimension->getOutlineLevel() > 0 || $rowDimension->getXfIndex() !== null;
1018
1019 56
            if ($writeCurrentRow) {
1020
                // Start a new row
1021 56
                $objWriter->startElement('row');
1022 56
                $objWriter->writeAttribute('r', $currentRow);
1023 56
                $objWriter->writeAttribute('spans', '1:' . $colCount);
1024
1025
                // Row dimensions
1026 56
                if ($rowDimension->getRowHeight() >= 0) {
1027 5
                    $objWriter->writeAttribute('customHeight', '1');
1028 5
                    $objWriter->writeAttribute('ht', StringHelper::formatNumber($rowDimension->getRowHeight()));
1029
                }
1030
1031
                // Row visibility
1032 56
                if ($rowDimension->getVisible() == false) {
1033 2
                    $objWriter->writeAttribute('hidden', 'true');
1034
                }
1035
1036
                // Collapsed
1037 56
                if ($rowDimension->getCollapsed() == true) {
1038
                    $objWriter->writeAttribute('collapsed', 'true');
1039
                }
1040
1041
                // Outline level
1042 56
                if ($rowDimension->getOutlineLevel() > 0) {
1043
                    $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel());
1044
                }
1045
1046
                // Style
1047 56
                if ($rowDimension->getXfIndex() !== null) {
1048
                    $objWriter->writeAttribute('s', $rowDimension->getXfIndex());
1049
                    $objWriter->writeAttribute('customFormat', '1');
1050
                }
1051
1052
                // Write cells
1053 56
                if (isset($cellsByRow[$currentRow])) {
1054 56
                    foreach ($cellsByRow[$currentRow] as $cellAddress) {
1055
                        // Write cell
1056 56
                        $this->writeCell($objWriter, $pSheet, $cellAddress, $aFlippedStringTable);
1057
                    }
1058
                }
1059
1060
                // End row
1061 56
                $objWriter->endElement();
1062
            }
1063
        }
1064
1065 56
        $objWriter->endElement();
1066 56
    }
1067
1068
    /**
1069
     * Write Cell.
1070
     *
1071
     * @param XMLWriter $objWriter XML Writer
1072
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1073
     * @param Cell $pCellAddress Cell Address
1074
     * @param string[] $pStringTable String table
0 ignored issues
show
Bug introduced by
There is no parameter named $pStringTable. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1075
     * @param string[] $pFlippedStringTable String table (flipped), for faster index searching
1076
     *
1077
     * @throws WriterException
1078
     */
1079 56
    private function writeCell(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, $pCellAddress, array $pFlippedStringTable)
1080
    {
1081
        // Cell
1082 56
        $pCell = $pSheet->getCell($pCellAddress);
1083 56
        $objWriter->startElement('c');
1084 56
        $objWriter->writeAttribute('r', $pCellAddress);
1085
1086
        // Sheet styles
1087 56
        if ($pCell->getXfIndex() != '') {
1088 32
            $objWriter->writeAttribute('s', $pCell->getXfIndex());
1089
        }
1090
1091
        // If cell value is supplied, write cell value
1092 56
        $cellValue = $pCell->getValue();
1093 56
        if (is_object($cellValue) || $cellValue !== '') {
1094
            // Map type
1095 56
            $mappedType = $pCell->getDataType();
1096
1097
            // Write data type depending on its type
1098 56
            switch (strtolower($mappedType)) {
1099 56
                case 'inlinestr':    // Inline string
1100 55
                case 's':            // String
1101 48
                case 'b':            // Boolean
1102 51
                    $objWriter->writeAttribute('t', $mappedType);
1103 51
                    break;
1104 46
                case 'f':            // Formula
1105 18
                    $calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ?
1106 18
                        $pCell->getCalculatedValue() : $cellValue;
1107 18
                    if (is_string($calculatedValue)) {
1108 13
                        $objWriter->writeAttribute('t', 'str');
1109
                    }
1110 18
                    break;
1111 45
                case 'e':            // Error
1112
                    $objWriter->writeAttribute('t', $mappedType);
1113
            }
1114
1115
            // Write data depending on its type
1116 56
            switch (strtolower($mappedType)) {
1117 56
                case 'inlinestr':    // Inline string
1118 8
                    if (!$cellValue instanceof RichText) {
1119
                        $objWriter->writeElement('t', StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue)));
1120
                    } elseif ($cellValue instanceof RichText) {
1121 8
                        $objWriter->startElement('is');
1122 8
                        $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart as the method writeRichText() does only exist in the following sub-classes of PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart: PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
1123 8
                        $objWriter->endElement();
1124
                    }
1125
1126 8
                    break;
1127 55
                case 's':            // String
1128 50
                    if (!$cellValue instanceof RichText) {
1129 50
                        if (isset($pFlippedStringTable[$cellValue])) {
1130 50
                            $objWriter->writeElement('v', $pFlippedStringTable[$cellValue]);
1131
                        }
1132
                    } elseif ($cellValue instanceof RichText) {
1133 2
                        $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]);
1134
                    }
1135
1136 50
                    break;
1137 48
                case 'f':            // Formula
1138 18
                    $attributes = $pCell->getFormulaAttributes();
1139 18
                    if ($attributes['t'] == 'array') {
1140
                        $objWriter->startElement('f');
1141
                        $objWriter->writeAttribute('t', 'array');
1142
                        $objWriter->writeAttribute('ref', $pCellAddress);
1143
                        $objWriter->writeAttribute('aca', '1');
1144
                        $objWriter->writeAttribute('ca', '1');
1145
                        $objWriter->text(substr($cellValue, 1));
1146
                        $objWriter->endElement();
1147
                    } else {
1148 18
                        $objWriter->writeElement('f', substr($cellValue, 1));
1149
                    }
1150 18
                    if ($this->getParentWriter()->getOffice2003Compatibility() === false) {
1151 18
                        if ($this->getParentWriter()->getPreCalculateFormulas()) {
1152 18
                            if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') {
1153 18
                                $objWriter->writeElement('v', StringHelper::formatNumber($calculatedValue));
0 ignored issues
show
Bug introduced by
The variable $calculatedValue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1154
                            } else {
1155 18
                                $objWriter->writeElement('v', '0');
1156
                            }
1157
                        } else {
1158
                            $objWriter->writeElement('v', '0');
1159
                        }
1160
                    }
1161 18
                    break;
1162 47
                case 'n':            // Numeric
1163
                    // force point as decimal separator in case current locale uses comma
1164 39
                    $objWriter->writeElement('v', str_replace(',', '.', $cellValue));
1165 39
                    break;
1166 26
                case 'b':            // Boolean
1167 8
                    $objWriter->writeElement('v', ($cellValue ? '1' : '0'));
1168 8
                    break;
1169 22
                case 'e':            // Error
1170
                    if (substr($cellValue, 0, 1) == '=') {
1171
                        $objWriter->writeElement('f', substr($cellValue, 1));
1172
                        $objWriter->writeElement('v', substr($cellValue, 1));
1173
                    } else {
1174
                        $objWriter->writeElement('v', $cellValue);
1175
                    }
1176
1177
                    break;
1178
            }
1179
        }
1180
1181 56
        $objWriter->endElement();
1182 56
    }
1183
1184
    /**
1185
     * Write Drawings.
1186
     *
1187
     * @param XMLWriter $objWriter XML Writer
1188
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1189
     * @param bool $includeCharts Flag indicating if we should include drawing details for charts
1190
     *
1191
     * @throws WriterException
1192
     */
1193 56
    private function writeDrawings(XMLWriter $objWriter = null, PhpspreadsheetWorksheet $pSheet = null, $includeCharts = false)
1194
    {
1195 56
        $chartCount = ($includeCharts) ? $pSheet->getChartCollection()->count() : 0;
0 ignored issues
show
Bug introduced by
It seems like $pSheet is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
1196
        // If sheet contains drawings, add the relationships
1197 56
        if (($pSheet->getDrawingCollection()->count() > 0) ||
1198 56
            ($chartCount > 0)) {
1199 22
            $objWriter->startElement('drawing');
0 ignored issues
show
Bug introduced by
It seems like $objWriter is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
1200 22
            $objWriter->writeAttribute('r:id', 'rId1');
1201 22
            $objWriter->endElement();
1202
        }
1203 56
    }
1204
1205
    /**
1206
     * Write LegacyDrawing.
1207
     *
1208
     * @param XMLWriter $objWriter XML Writer
1209
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1210
     *
1211
     * @throws WriterException
1212
     */
1213 56
    private function writeLegacyDrawing(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
1214
    {
1215
        // If sheet contains comments, add the relationships
1216 56
        if (count($pSheet->getComments()) > 0) {
1217 9
            $objWriter->startElement('legacyDrawing');
1218 9
            $objWriter->writeAttribute('r:id', 'rId_comments_vml1');
1219 9
            $objWriter->endElement();
1220
        }
1221 56
    }
1222
1223
    /**
1224
     * Write LegacyDrawingHF.
1225
     *
1226
     * @param XMLWriter $objWriter XML Writer
1227
     * @param PhpspreadsheetWorksheet $pSheet Worksheet
1228
     *
1229
     * @throws WriterException
1230
     */
1231 56
    private function writeLegacyDrawingHF(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
1232
    {
1233
        // If sheet contains images, add the relationships
1234 56
        if (count($pSheet->getHeaderFooter()->getImages()) > 0) {
1235 1
            $objWriter->startElement('legacyDrawingHF');
1236 1
            $objWriter->writeAttribute('r:id', 'rId_headerfooter_vml1');
1237 1
            $objWriter->endElement();
1238
        }
1239 56
    }
1240
}
1241