Completed
Push — develop ( 714dc2...c2b38b )
by Adrien
31:27
created

Worksheet::writeDefaultRowHeight()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 0
dl 0
loc 18
ccs 11
cts 11
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
4
5
/**
6
 * Copyright (c) 2006 - 2015 PhpSpreadsheet.
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 *
22
 * @category   PhpSpreadsheet
23
 *
24
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
25
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
26
 */
27
28
// Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class):
29
// -----------------------------------------------------------------------------------------
30
// /*
31
// *  Module written/ported by Xavier Noguer <[email protected]>
32
// *
33
// *  The majority of this is _NOT_ my code.  I simply ported it from the
34
// *  PERL Spreadsheet::WriteExcel module.
35
// *
36
// *  The author of the Spreadsheet::WriteExcel module is John McNamara
37
// *  <[email protected]>
38
// *
39
// *  I _DO_ maintain this code, and John McNamara has nothing to do with the
40
// *  porting of this code to PHP.  Any questions directly related to this
41
// *  class library should be directed to me.
42
// *
43
// *  License Information:
44
// *
45
// *    Spreadsheet_Excel_Writer:  A library for generating Excel Spreadsheets
46
// *    Copyright (c) 2002-2003 Xavier Noguer [email protected]
47
// *
48
// *    This library is free software; you can redistribute it and/or
49
// *    modify it under the terms of the GNU Lesser General Public
50
// *    License as published by the Free Software Foundation; either
51
// *    version 2.1 of the License, or (at your option) any later version.
52
// *
53
// *    This library is distributed in the hope that it will be useful,
54
// *    but WITHOUT ANY WARRANTY; without even the implied warranty of
55
// *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56
// *    Lesser General Public License for more details.
57
// *
58
// *    You should have received a copy of the GNU Lesser General Public
59
// *    License along with this library; if not, write to the Free Software
60
// *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
61
// */
62
class Worksheet extends BIFFwriter
63
{
64
    /**
65
     * Formula parser.
66
     *
67
     * @var \PhpOffice\PhpSpreadsheet\Writer\Xls\Parser
68
     */
69
    private $parser;
70
71
    /**
72
     * Maximum number of characters for a string (LABEL record in BIFF5).
73
     *
74
     * @var int
75
     */
76
    private $xlsStringMaxLength;
77
78
    /**
79
     * Array containing format information for columns.
80
     *
81
     * @var array
82
     */
83
    private $columnInfo;
84
85
    /**
86
     * Array containing the selected area for the worksheet.
87
     *
88
     * @var array
89
     */
90
    private $selection;
91
92
    /**
93
     * The active pane for the worksheet.
94
     *
95
     * @var int
96
     */
97
    private $activePane;
98
99
    /**
100
     * Whether to use outline.
101
     *
102
     * @var int
103
     */
104
    private $outlineOn;
105
106
    /**
107
     * Auto outline styles.
108
     *
109
     * @var bool
110
     */
111
    private $outlineStyle;
112
113
    /**
114
     * Whether to have outline summary below.
115
     *
116
     * @var bool
117
     */
118
    private $outlineBelow;
119
120
    /**
121
     * Whether to have outline summary at the right.
122
     *
123
     * @var bool
124
     */
125
    private $outlineRight;
126
127
    /**
128
     * Reference to the total number of strings in the workbook.
129
     *
130
     * @var int
131
     */
132
    private $stringTotal;
133
134
    /**
135
     * Reference to the number of unique strings in the workbook.
136
     *
137
     * @var int
138
     */
139
    private $stringUnique;
140
141
    /**
142
     * Reference to the array containing all the unique strings in the workbook.
143
     *
144
     * @var array
145
     */
146
    private $stringTable;
147
148
    /**
149
     * Color cache.
150
     */
151
    private $colors;
152
153
    /**
154
     * Index of first used row (at least 0).
155
     *
156
     * @var int
157
     */
158
    private $firstRowIndex;
159
160
    /**
161
     * Index of last used row. (no used rows means -1).
162
     *
163
     * @var int
164
     */
165
    private $lastRowIndex;
166
167
    /**
168
     * Index of first used column (at least 0).
169
     *
170
     * @var int
171
     */
172
    private $firstColumnIndex;
173
174
    /**
175
     * Index of last used column (no used columns means -1).
176
     *
177
     * @var int
178
     */
179
    private $lastColumnIndex;
180
181
    /**
182
     * Sheet object.
183
     *
184
     * @var \PhpOffice\PhpSpreadsheet\Worksheet
185
     */
186
    public $phpSheet;
187
188
    /**
189
     * Count cell style Xfs.
190
     *
191
     * @var int
192
     */
193
    private $countCellStyleXfs;
194
195
    /**
196
     * Escher object corresponding to MSODRAWING.
197
     *
198
     * @var \PhpOffice\PhpSpreadsheet\Shared\Escher
199
     */
200
    private $escher;
201
202
    /**
203
     * Array of font hashes associated to FONT records index.
204
     *
205
     * @var array
206
     */
207
    public $fontHashIndex;
208
209
    /**
210
     * @var bool
211
     */
212
    private $preCalculateFormulas;
213
214
    /**
215
     * @var int
216
     */
217
    private $printHeaders;
218
219
    /**
220
     * Constructor.
221
     *
222
     * @param int &$str_total Total number of strings
223
     * @param int &$str_unique Total number of unique strings
224
     * @param array &$str_table String Table
225
     * @param array &$colors Colour Table
226
     * @param mixed $parser The formula parser created for the Workbook
227
     * @param bool $preCalculateFormulas Flag indicating whether formulas should be calculated or just written
228
     * @param string $phpSheet The worksheet to write
229
     * @param \PhpOffice\PhpSpreadsheet\Worksheet $phpSheet
230
     */
231 38
    public function __construct(&$str_total, &$str_unique, &$str_table, &$colors, $parser, $preCalculateFormulas, $phpSheet)
232
    {
233
        // It needs to call its parent's constructor explicitly
234 38
        parent::__construct();
235
236 38
        $this->preCalculateFormulas = $preCalculateFormulas;
237 38
        $this->stringTotal = &$str_total;
238 38
        $this->stringUnique = &$str_unique;
239 38
        $this->stringTable = &$str_table;
240 38
        $this->colors = &$colors;
241 38
        $this->parser = $parser;
242
243 38
        $this->phpSheet = $phpSheet;
0 ignored issues
show
Documentation Bug introduced by
It seems like $phpSheet of type string is incompatible with the declared type object<PhpOffice\PhpSpreadsheet\Worksheet> of property $phpSheet.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
244
245 38
        $this->xlsStringMaxLength = 255;
246 38
        $this->columnInfo = [];
247 38
        $this->selection = [0, 0, 0, 0];
248 38
        $this->activePane = 3;
249
250 38
        $this->printHeaders = 0;
251
252 38
        $this->outlineStyle = 0;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineStyle was declared of type boolean, but 0 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
253 38
        $this->outlineBelow = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineBelow was declared of type boolean, but 1 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
254 38
        $this->outlineRight = 1;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineRight was declared of type boolean, but 1 is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
255 38
        $this->outlineOn = 1;
256
257 38
        $this->fontHashIndex = [];
258
259
        // calculate values for DIMENSIONS record
260 38
        $minR = 1;
0 ignored issues
show
Unused Code introduced by
$minR 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...
261 38
        $minC = 'A';
262
263 38
        $maxR = $this->phpSheet->getHighestRow();
0 ignored issues
show
Bug introduced by
The method getHighestRow cannot be called on $this->phpSheet (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
264 38
        $maxC = $this->phpSheet->getHighestColumn();
0 ignored issues
show
Bug introduced by
The method getHighestColumn cannot be called on $this->phpSheet (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
265
266
        // Determine lowest and highest column and row
267 38
        $this->lastRowIndex = ($maxR > 65535) ? 65535 : $maxR;
268
269 38
        $this->firstColumnIndex = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($minC);
270 38
        $this->lastColumnIndex = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($maxC);
271
272
//        if ($this->firstColumnIndex > 255) $this->firstColumnIndex = 255;
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% 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...
273 38
        if ($this->lastColumnIndex > 255) {
274
            $this->lastColumnIndex = 255;
275
        }
276
277 38
        $this->countCellStyleXfs = count($phpSheet->getParent()->getCellStyleXfCollection());
0 ignored issues
show
Bug introduced by
The method getParent cannot be called on $phpSheet (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
278 38
    }
279
280
    /**
281
     * Add data to the beginning of the workbook (note the reverse order)
282
     * and to the end of the workbook.
283
     *
284
     * @see \PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook::storeWorkbook()
285
     */
286 38
    public function close()
287
    {
288 38
        $phpSheet = $this->phpSheet;
289
290 38
        $num_sheets = $phpSheet->getParent()->getSheetCount();
0 ignored issues
show
Unused Code introduced by
$num_sheets 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...
291
292
        // Write BOF record
293 38
        $this->storeBof(0x0010);
294
295
        // Write PRINTHEADERS
296 38
        $this->writePrintHeaders();
297
298
        // Write PRINTGRIDLINES
299 38
        $this->writePrintGridlines();
300
301
        // Write GRIDSET
302 38
        $this->writeGridset();
303
304
        // Calculate column widths
305 38
        $phpSheet->calculateColumnWidths();
306
307
        // Column dimensions
308 38
        if (($defaultWidth = $phpSheet->getDefaultColumnDimension()->getWidth()) < 0) {
309 38
            $defaultWidth = \PhpOffice\PhpSpreadsheet\Shared\Font::getDefaultColumnWidthByFont($phpSheet->getParent()->getDefaultStyle()->getFont());
310
        }
311
312 38
        $columnDimensions = $phpSheet->getColumnDimensions();
313 38
        $maxCol = $this->lastColumnIndex - 1;
314 38
        for ($i = 0; $i <= $maxCol; ++$i) {
315 38
            $hidden = 0;
316 38
            $level = 0;
317 38
            $xfIndex = 15; // there are 15 cell style Xfs
318
319 38
            $width = $defaultWidth;
320
321 38
            $columnLetter = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($i);
322 38
            if (isset($columnDimensions[$columnLetter])) {
323 19
                $columnDimension = $columnDimensions[$columnLetter];
324 19
                if ($columnDimension->getWidth() >= 0) {
325 19
                    $width = $columnDimension->getWidth();
326
                }
327 19
                $hidden = $columnDimension->getVisible() ? 0 : 1;
328 19
                $level = $columnDimension->getOutlineLevel();
329 19
                $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs
330
            }
331
332
            // Components of columnInfo:
333
            // $firstcol first column on the range
334
            // $lastcol  last column on the range
335
            // $width    width to set
336
            // $xfIndex  The optional cell style Xf index to apply to the columns
337
            // $hidden   The optional hidden atribute
338
            // $level    The optional outline level
339 38
            $this->columnInfo[] = [$i, $i, $width, $xfIndex, $hidden, $level];
340
        }
341
342
        // Write GUTS
343 38
        $this->writeGuts();
344
345
        // Write DEFAULTROWHEIGHT
346 38
        $this->writeDefaultRowHeight();
347
        // Write WSBOOL
348 38
        $this->writeWsbool();
349
        // Write horizontal and vertical page breaks
350 38
        $this->writeBreaks();
351
        // Write page header
352 38
        $this->writeHeader();
353
        // Write page footer
354 38
        $this->writeFooter();
355
        // Write page horizontal centering
356 38
        $this->writeHcenter();
357
        // Write page vertical centering
358 38
        $this->writeVcenter();
359
        // Write left margin
360 38
        $this->writeMarginLeft();
361
        // Write right margin
362 38
        $this->writeMarginRight();
363
        // Write top margin
364 38
        $this->writeMarginTop();
365
        // Write bottom margin
366 38
        $this->writeMarginBottom();
367
        // Write page setup
368 38
        $this->writeSetup();
369
        // Write sheet protection
370 38
        $this->writeProtect();
371
        // Write SCENPROTECT
372 38
        $this->writeScenProtect();
373
        // Write OBJECTPROTECT
374 38
        $this->writeObjectProtect();
375
        // Write sheet password
376 38
        $this->writePassword();
377
        // Write DEFCOLWIDTH record
378 38
        $this->writeDefcol();
379
380
        // Write the COLINFO records if they exist
381 38
        if (!empty($this->columnInfo)) {
382 38
            $colcount = count($this->columnInfo);
383 38
            for ($i = 0; $i < $colcount; ++$i) {
384 38
                $this->writeColinfo($this->columnInfo[$i]);
385
            }
386
        }
387 38
        $autoFilterRange = $phpSheet->getAutoFilter()->getRange();
388 38
        if (!empty($autoFilterRange)) {
389
            // Write AUTOFILTERINFO
390 3
            $this->writeAutoFilterInfo();
391
        }
392
393
        // Write sheet dimensions
394 38
        $this->writeDimensions();
395
396
        // Row dimensions
397 38
        foreach ($phpSheet->getRowDimensions() as $rowDimension) {
398 37
            $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs
399 37
            $this->writeRow($rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel());
0 ignored issues
show
Documentation introduced by
$rowDimension->getVisible() ? '0' : '1' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
400
        }
401
402
        // Write Cells
403 38
        foreach ($phpSheet->getCellCollection() as $cellID) {
404 38
            $cell = $phpSheet->getCell($cellID);
405 38
            $row = $cell->getRow() - 1;
406 38
            $column = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($cell->getColumn()) - 1;
407
408
            // Don't break Excel!
409
//            if ($row + 1 > 65536 or $column + 1 > 256) {
410 38
            if ($row > 65535 || $column > 255) {
411
                break;
412
            }
413
414
            // Write cell value
415 38
            $xfIndex = $cell->getXfIndex() + 15; // there are 15 cell style Xfs
416
417 38
            $cVal = $cell->getValue();
418 38
            if ($cVal instanceof \PhpOffice\PhpSpreadsheet\RichText) {
419 9
                $arrcRun = [];
420 9
                $str_len = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($cVal->getPlainText(), 'UTF-8');
0 ignored issues
show
Unused Code introduced by
$str_len 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...
421 9
                $str_pos = 0;
422 9
                $elements = $cVal->getRichTextElements();
423 9
                foreach ($elements as $element) {
424
                    // FONT Index
425 9
                    if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
426 9
                        $str_fontidx = $this->fontHashIndex[$element->getFont()->getHashCode()];
427
                    } else {
428 8
                        $str_fontidx = 0;
429
                    }
430 9
                    $arrcRun[] = ['strlen' => $str_pos, 'fontidx' => $str_fontidx];
431
                    // Position FROM
432 9
                    $str_pos += \PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($element->getText(), 'UTF-8');
433
                }
434 9
                $this->writeRichTextString($row, $column, $cVal->getPlainText(), $xfIndex, $arrcRun);
435
            } else {
436 37
                switch ($cell->getDatatype()) {
437 37
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING:
438 30
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NULL:
439 35
                        if ($cVal === '' || $cVal === null) {
440 18
                            $this->writeBlank($row, $column, $xfIndex);
441
                        } else {
442 33
                            $this->writeString($row, $column, $cVal, $xfIndex);
443
                        }
444 35
                        break;
445 26
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC:
446 23
                        $this->writeNumber($row, $column, $cVal, $xfIndex);
447 23
                        break;
448 18
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_FORMULA:
449 16
                        $calculatedValue = $this->preCalculateFormulas ?
450 16
                            $cell->getCalculatedValue() : null;
451 16
                        $this->writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue);
452 16
                        break;
453 8
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_BOOL:
454 8
                        $this->writeBoolErr($row, $column, $cVal, 0, $xfIndex);
0 ignored issues
show
Documentation introduced by
0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
455 8
                        break;
456
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_ERROR:
457
                        $this->writeBoolErr($row, $column, self::mapErrorCode($cVal), 1, $xfIndex);
0 ignored issues
show
Documentation introduced by
1 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
458 37
                        break;
459
                }
460
            }
461
        }
462
463
        // Append
464 38
        $this->writeMsoDrawing();
465
466
        // Write WINDOW2 record
467 38
        $this->writeWindow2();
468
469
        // Write PLV record
470 38
        $this->writePageLayoutView();
471
472
        // Write ZOOM record
473 38
        $this->writeZoom();
474 38
        if ($phpSheet->getFreezePane()) {
475 3
            $this->writePanes();
476
        }
477
478
        // Write SELECTION record
479 38
        $this->writeSelection();
480
481
        // Write MergedCellsTable Record
482 38
        $this->writeMergedCells();
483
484
        // Hyperlinks
485 38
        foreach ($phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) {
486 8
            list($column, $row) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($coordinate);
487
488 8
            $url = $hyperlink->getUrl();
489
490 8
            if (strpos($url, 'sheet://') !== false) {
491
                // internal to current workbook
492 6
                $url = str_replace('sheet://', 'internal:', $url);
493 8
            } elseif (preg_match('/^(http:|https:|ftp:|mailto:)/', $url)) {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
494
                // URL
495
            } else {
496
                // external (local file)
497
                $url = 'external:' . $url;
498
            }
499
500 8
            $this->writeUrl($row - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($column) - 1, $url);
501
        }
502
503 38
        $this->writeDataValidity();
504 38
        $this->writeSheetLayout();
505
506
        // Write SHEETPROTECTION record
507 38
        $this->writeSheetProtection();
508 38
        $this->writeRangeProtection();
509
510 38
        $arrConditionalStyles = $phpSheet->getConditionalStylesCollection();
511 38
        if (!empty($arrConditionalStyles)) {
512 2
            $arrConditional = [];
513
            // @todo CFRule & CFHeader
514
            // Write CFHEADER record
515 2
            $this->writeCFHeader();
516
            // Write ConditionalFormattingTable records
517 2
            foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) {
518 2
                foreach ($conditionalStyles as $conditional) {
519 2
                    if ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION
520 2
                        || $conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
521 2
                        if (!isset($arrConditional[$conditional->getHashCode()])) {
522
                            // This hash code has been handled
523 2
                            $arrConditional[$conditional->getHashCode()] = true;
524
525
                            // Write CFRULE record
526 2
                            $this->writeCFRule($conditional);
527
                        }
528
                    }
529
                }
530
            }
531
        }
532
533 38
        $this->storeEof();
534 38
    }
535
536
    /**
537
     * Write a cell range address in BIFF8
538
     * always fixed range
539
     * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format.
540
     *
541
     * @param string $range E.g. 'A1' or 'A1:B6'
542
     *
543
     * @return string Binary data
544
     */
545 7
    private function writeBIFF8CellRangeAddressFixed($range = 'A1')
546
    {
547 7
        $explodes = explode(':', $range);
548
549
        // extract first cell, e.g. 'A1'
550 7
        $firstCell = $explodes[0];
551
552
        // extract last cell, e.g. 'B6'
553 7
        if (count($explodes) == 1) {
554 2
            $lastCell = $firstCell;
555
        } else {
556 5
            $lastCell = $explodes[1];
557
        }
558
559 7
        $firstCellCoordinates = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($firstCell); // e.g. array(0, 1)
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% 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...
560 7
        $lastCellCoordinates = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($lastCell); // e.g. array(1, 6)
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% 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...
561
562 7
        return pack('vvvv', $firstCellCoordinates[1] - 1, $lastCellCoordinates[1] - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($firstCellCoordinates[0]) - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($lastCellCoordinates[0]) - 1);
563
    }
564
565
    /**
566
     * Retrieves data from memory in one chunk, or from disk in $buffer
567
     * sized chunks.
568
     *
569
     * @return string The data
570
     */
571 38
    public function getData()
572
    {
573 38
        $buffer = 4096;
0 ignored issues
show
Unused Code introduced by
$buffer 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...
574
575
        // Return data stored in memory
576 38
        if (isset($this->_data)) {
577 38
            $tmp = $this->_data;
578 38
            unset($this->_data);
579
580 38
            return $tmp;
581
        }
582
        // No data to return
583
        return false;
584
    }
585
586
    /**
587
     * Set the option to print the row and column headers on the printed page.
588
     *
589
     * @param int $print Whether to print the headers or not. Defaults to 1 (print).
590
     */
591
    public function printRowColHeaders($print = 1)
592
    {
593
        $this->printHeaders = $print;
594
    }
595
596
    /**
597
     * This method sets the properties for outlining and grouping. The defaults
598
     * correspond to Excel's defaults.
599
     *
600
     * @param bool $visible
601
     * @param bool $symbols_below
602
     * @param bool $symbols_right
603
     * @param bool $auto_style
604
     */
605
    public function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false)
606
    {
607
        $this->outlineOn = $visible;
0 ignored issues
show
Documentation Bug introduced by
The property $outlineOn was declared of type integer, but $visible is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
608
        $this->outlineBelow = $symbols_below;
609
        $this->outlineRight = $symbols_right;
610
        $this->outlineStyle = $auto_style;
611
612
        // Ensure this is a boolean vale for Window2
613
        if ($this->outlineOn) {
614
            $this->outlineOn = 1;
615
        }
616
    }
617
618
    /**
619
     * Write a double to the specified row and column (zero indexed).
620
     * An integer can be written as a double. Excel will display an
621
     * integer. $format is optional.
622
     *
623
     * Returns  0 : normal termination
624
     *         -2 : row or column out of range
625
     *
626
     * @param int $row Zero indexed row
627
     * @param int $col Zero indexed column
628
     * @param float $num The number to write
629
     * @param mixed $xfIndex The optional XF format
630
     *
631
     * @return int
632
     */
633 23
    private function writeNumber($row, $col, $num, $xfIndex)
634
    {
635 23
        $record = 0x0203; // Record identifier
636 23
        $length = 0x000E; // Number of bytes to follow
637
638 23
        $header = pack('vv', $record, $length);
639 23
        $data = pack('vvv', $row, $col, $xfIndex);
640 23
        $xl_double = pack('d', $num);
641 23
        if (self::getByteOrder()) { // if it's Big Endian
642
            $xl_double = strrev($xl_double);
643
        }
644
645 23
        $this->append($header . $data . $xl_double);
646
647 23
        return 0;
648
    }
649
650
    /**
651
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version.
652
     *
653
     * @param int $row Row index (0-based)
654
     * @param int $col Column index (0-based)
655
     * @param string $str The string
656
     * @param int $xfIndex Index to XF record
657
     */
658 33
    private function writeString($row, $col, $str, $xfIndex)
659
    {
660 33
        $this->writeLabelSst($row, $col, $str, $xfIndex);
661 33
    }
662
663
    /**
664
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
665
     * It differs from writeString by the writing of rich text strings.
666
     *
667
     * @param int $row Row index (0-based)
668
     * @param int $col Column index (0-based)
669
     * @param string $str The string
670
     * @param int $xfIndex The XF format index for the cell
671
     * @param array $arrcRun Index to Font record and characters beginning
672
     */
673 9 View Code Duplication
    private function writeRichTextString($row, $col, $str, $xfIndex, $arrcRun)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
674
    {
675 9
        $record = 0x00FD; // Record identifier
676 9
        $length = 0x000A; // Bytes to follow
677 9
        $str = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeShort($str, $arrcRun);
678
679
        /* check if string is already present */
680 9
        if (!isset($this->stringTable[$str])) {
681 9
            $this->stringTable[$str] = $this->stringUnique++;
682
        }
683 9
        ++$this->stringTotal;
684
685 9
        $header = pack('vv', $record, $length);
686 9
        $data = pack('vvvV', $row, $col, $xfIndex, $this->stringTable[$str]);
687 9
        $this->append($header . $data);
688 9
    }
689
690
    /**
691
     * Write a string to the specified row and column (zero indexed).
692
     * NOTE: there is an Excel 5 defined limit of 255 characters.
693
     * $format is optional.
694
     * Returns  0 : normal termination
695
     *         -2 : row or column out of range
696
     *         -3 : long string truncated to 255 chars.
697
     *
698
     * @param int $row Zero indexed row
699
     * @param int $col Zero indexed column
700
     * @param string $str The string to write
701
     * @param mixed $xfIndex The XF format index for the cell
702
     *
703
     * @return int
704
     */
705
    private function writeLabel($row, $col, $str, $xfIndex)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
706
    {
707
        $strlen = strlen($str);
708
        $record = 0x0204; // Record identifier
709
        $length = 0x0008 + $strlen; // Bytes to follow
710
711
        $str_error = 0;
712
713
        if ($strlen > $this->xlsStringMaxLength) { // LABEL must be < 255 chars
714
            $str = substr($str, 0, $this->xlsStringMaxLength);
715
            $length = 0x0008 + $this->xlsStringMaxLength;
716
            $strlen = $this->xlsStringMaxLength;
717
            $str_error = -3;
718
        }
719
720
        $header = pack('vv', $record, $length);
721
        $data = pack('vvvv', $row, $col, $xfIndex, $strlen);
722
        $this->append($header . $data . $str);
723
724
        return $str_error;
725
    }
726
727
    /**
728
     * Write a string to the specified row and column (zero indexed).
729
     * This is the BIFF8 version (no 255 chars limit).
730
     * $format is optional.
731
     * Returns  0 : normal termination
732
     *         -2 : row or column out of range
733
     *         -3 : long string truncated to 255 chars.
734
     *
735
     * @param int $row Zero indexed row
736
     * @param int $col Zero indexed column
737
     * @param string $str The string to write
738
     * @param mixed $xfIndex The XF format index for the cell
739
     *
740
     * @return int
741
     */
742 33 View Code Duplication
    private function writeLabelSst($row, $col, $str, $xfIndex)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
743
    {
744 33
        $record = 0x00FD; // Record identifier
745 33
        $length = 0x000A; // Bytes to follow
746
747 33
        $str = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($str);
748
749
        /* check if string is already present */
750 33
        if (!isset($this->stringTable[$str])) {
751 33
            $this->stringTable[$str] = $this->stringUnique++;
752
        }
753 33
        ++$this->stringTotal;
754
755 33
        $header = pack('vv', $record, $length);
756 33
        $data = pack('vvvV', $row, $col, $xfIndex, $this->stringTable[$str]);
757 33
        $this->append($header . $data);
758 33
    }
759
760
    /**
761
     * Writes a note associated with the cell given by the row and column.
762
     * NOTE records don't have a length limit.
763
     *
764
     * @param int $row Zero indexed row
765
     * @param int $col Zero indexed column
766
     * @param string $note The note to write
767
     */
768
    private function writeNote($row, $col, $note)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
769
    {
770
        $note_length = strlen($note);
771
        $record = 0x001C; // Record identifier
772
        $max_length = 2048; // Maximun length for a NOTE record
773
774
        // Length for this record is no more than 2048 + 6
775
        $length = 0x0006 + min($note_length, 2048);
776
        $header = pack('vv', $record, $length);
777
        $data = pack('vvv', $row, $col, $note_length);
778
        $this->append($header . $data . substr($note, 0, 2048));
779
780
        for ($i = $max_length; $i < $note_length; $i += $max_length) {
781
            $chunk = substr($note, $i, $max_length);
782
            $length = 0x0006 + strlen($chunk);
783
            $header = pack('vv', $record, $length);
784
            $data = pack('vvv', -1, 0, strlen($chunk));
785
            $this->append($header . $data . $chunk);
786
        }
787
788
        return 0;
789
    }
790
791
    /**
792
     * Write a blank cell to the specified row and column (zero indexed).
793
     * A blank cell is used to specify formatting without adding a string
794
     * or a number.
795
     *
796
     * A blank cell without a format serves no purpose. Therefore, we don't write
797
     * a BLANK record unless a format is specified.
798
     *
799
     * Returns  0 : normal termination (including no format)
800
     *         -1 : insufficient number of arguments
801
     *         -2 : row or column out of range
802
     *
803
     * @param int $row Zero indexed row
804
     * @param int $col Zero indexed column
805
     * @param mixed $xfIndex The XF format index
806
     */
807 18 View Code Duplication
    public function writeBlank($row, $col, $xfIndex)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
808
    {
809 18
        $record = 0x0201; // Record identifier
810 18
        $length = 0x0006; // Number of bytes to follow
811
812 18
        $header = pack('vv', $record, $length);
813 18
        $data = pack('vvv', $row, $col, $xfIndex);
814 18
        $this->append($header . $data);
815
816 18
        return 0;
817
    }
818
819
    /**
820
     * Write a boolean or an error type to the specified row and column (zero indexed).
821
     *
822
     * @param int $row Row index (0-based)
823
     * @param int $col Column index (0-based)
824
     * @param int $value
825
     * @param bool $isError Error or Boolean?
826
     * @param int $xfIndex
827
     */
828 8 View Code Duplication
    private function writeBoolErr($row, $col, $value, $isError, $xfIndex)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
829
    {
830 8
        $record = 0x0205;
831 8
        $length = 8;
832
833 8
        $header = pack('vv', $record, $length);
834 8
        $data = pack('vvvCC', $row, $col, $xfIndex, $value, $isError);
835 8
        $this->append($header . $data);
836
837 8
        return 0;
838
    }
839
840
    /**
841
     * Write a formula to the specified row and column (zero indexed).
842
     * The textual representation of the formula is passed to the parser in
843
     * Parser.php which returns a packed binary string.
844
     *
845
     * Returns  0 : normal termination
846
     *         -1 : formula errors (bad formula)
847
     *         -2 : row or column out of range
848
     *
849
     * @param int $row Zero indexed row
850
     * @param int $col Zero indexed column
851
     * @param string $formula The formula text string
852
     * @param mixed $xfIndex The XF format index
853
     * @param mixed $calculatedValue Calculated value
854
     *
855
     * @return int
856
     */
857 16
    private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue)
858
    {
859 16
        $record = 0x0006; // Record identifier
860
861
        // Initialize possible additional value for STRING record that should be written after the FORMULA record?
862 16
        $stringValue = null;
863
864
        // calculated value
865 16
        if (isset($calculatedValue)) {
866
            // Since we can't yet get the data type of the calculated value,
867
            // we use best effort to determine data type
868 16
            if (is_bool($calculatedValue)) {
869
                // Boolean value
870 3
                $num = pack('CCCvCv', 0x01, 0x00, (int) $calculatedValue, 0x00, 0x00, 0xFFFF);
871 16
            } elseif (is_int($calculatedValue) || is_float($calculatedValue)) {
872
                // Numeric value
873 14
                $num = pack('d', $calculatedValue);
874 12
            } elseif (is_string($calculatedValue)) {
875 12
                $errorCodes = \PhpOffice\PhpSpreadsheet\Cell\DataType::getErrorCodes();
876 12
                if (isset($errorCodes[$calculatedValue])) {
877
                    // Error value
878 4
                    $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF);
879 12
                } elseif ($calculatedValue === '') {
880
                    // Empty string (and BIFF8)
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% 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...
881 5
                    $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF);
882
                } else {
883
                    // Non-empty string value (or empty string BIFF5)
884 7
                    $stringValue = $calculatedValue;
885 7
                    $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF);
886
                }
887
            } else {
888
                // We are really not supposed to reach here
889
                $num = pack('d', 0x00);
890
            }
891
        } else {
892
            $num = pack('d', 0x00);
893
        }
894
895 16
        $grbit = 0x03; // Option flags
896 16
        $unknown = 0x0000; // Must be zero
897
898
        // Strip the '=' or '@' sign at the beginning of the formula string
899 16
        if ($formula[0] == '=') {
900 16
            $formula = substr($formula, 1);
901
        } else {
902
            // Error handling
903
            $this->writeString($row, $col, 'Unrecognised character for formula');
0 ignored issues
show
Bug introduced by
The call to writeString() misses a required argument $xfIndex.

This check looks for function calls that miss required arguments.

Loading history...
904
905
            return -1;
906
        }
907
908
        // Parse the formula using the parser in Parser.php
909
        try {
910 16
            $error = $this->parser->parse($formula);
0 ignored issues
show
Unused Code introduced by
$error 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...
911 16
            $formula = $this->parser->toReversePolish();
912
913 16
            $formlen = strlen($formula); // Length of the binary string
914 16
            $length = 0x16 + $formlen; // Length of the record data
915
916 16
            $header = pack('vv', $record, $length);
917
918 16
            $data = pack('vvv', $row, $col, $xfIndex)
919 16
                        . $num
920 16
                        . pack('vVv', $grbit, $unknown, $formlen);
921 16
            $this->append($header . $data . $formula);
922
923
            // Append also a STRING record if necessary
924 16
            if ($stringValue !== null) {
925 7
                $this->writeStringRecord($stringValue);
926
            }
927
928 16
            return 0;
929 5
        } catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
930
            // do nothing
931
        }
932 5
    }
933
934
    /**
935
     * Write a STRING record. This.
936
     *
937
     * @param string $stringValue
938
     */
939 7 View Code Duplication
    private function writeStringRecord($stringValue)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
940
    {
941 7
        $record = 0x0207; // Record identifier
942 7
        $data = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($stringValue);
943
944 7
        $length = strlen($data);
945 7
        $header = pack('vv', $record, $length);
946
947 7
        $this->append($header . $data);
948 7
    }
949
950
    /**
951
     * Write a hyperlink.
952
     * This is comprised of two elements: the visible label and
953
     * the invisible link. The visible label is the same as the link unless an
954
     * alternative string is specified. The label is written using the
955
     * writeString() method. Therefore the 255 characters string limit applies.
956
     * $string and $format are optional.
957
     *
958
     * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external
959
     * directory url.
960
     *
961
     * Returns  0 : normal termination
962
     *         -2 : row or column out of range
963
     *         -3 : long string truncated to 255 chars
964
     *
965
     * @param int $row Row
966
     * @param int $col Column
967
     * @param string $url URL string
968
     *
969
     * @return int
970
     */
971 8
    private function writeUrl($row, $col, $url)
972
    {
973
        // Add start row and col to arg list
974 8
        return $this->writeUrlRange($row, $col, $row, $col, $url);
975
    }
976
977
    /**
978
     * This is the more general form of writeUrl(). It allows a hyperlink to be
979
     * written to a range of cells. This function also decides the type of hyperlink
980
     * to be written. These are either, Web (http, ftp, mailto), Internal
981
     * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1').
982
     *
983
     * @see writeUrl()
984
     *
985
     * @param int $row1 Start row
986
     * @param int $col1 Start column
987
     * @param int $row2 End row
988
     * @param int $col2 End column
989
     * @param string $url URL string
990
     *
991
     * @return int
992
     */
993 8
    public function writeUrlRange($row1, $col1, $row2, $col2, $url)
994
    {
995
        // Check for internal/external sheet links or default to web link
996 8
        if (preg_match('[^internal:]', $url)) {
997 6
            return $this->writeUrlInternal($row1, $col1, $row2, $col2, $url);
998
        }
999 8
        if (preg_match('[^external:]', $url)) {
1000
            return $this->writeUrlExternal($row1, $col1, $row2, $col2, $url);
1001
        }
1002
1003 8
        return $this->writeUrlWeb($row1, $col1, $row2, $col2, $url);
1004
    }
1005
1006
    /**
1007
     * Used to write http, ftp and mailto hyperlinks.
1008
     * The link type ($options) is 0x03 is the same as absolute dir ref without
1009
     * sheet. However it is differentiated by the $unknown2 data stream.
1010
     *
1011
     * @see writeUrl()
1012
     *
1013
     * @param int $row1 Start row
1014
     * @param int $col1 Start column
1015
     * @param int $row2 End row
1016
     * @param int $col2 End column
1017
     * @param string $url URL string
1018
     *
1019
     * @return int
1020
     */
1021 8
    public function writeUrlWeb($row1, $col1, $row2, $col2, $url)
1022
    {
1023 8
        $record = 0x01B8; // Record identifier
1024 8
        $length = 0x00000; // Bytes to follow
0 ignored issues
show
Unused Code introduced by
$length 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...
1025
1026
        // Pack the undocumented parts of the hyperlink stream
1027 8
        $unknown1 = pack('H*', 'D0C9EA79F9BACE118C8200AA004BA90B02000000');
1028 8
        $unknown2 = pack('H*', 'E0C9EA79F9BACE118C8200AA004BA90B');
1029
1030
        // Pack the option flags
1031 8
        $options = pack('V', 0x03);
1032
1033
        // Convert URL to a null terminated wchar string
1034 8
        $url = implode("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY));
1035 8
        $url = $url . "\0\0\0";
1036
1037
        // Pack the length of the URL
1038 8
        $url_len = pack('V', strlen($url));
1039
1040
        // Calculate the data length
1041 8
        $length = 0x34 + strlen($url);
1042
1043
        // Pack the header data
1044 8
        $header = pack('vv', $record, $length);
1045 8
        $data = pack('vvvv', $row1, $row2, $col1, $col2);
1046
1047
        // Write the packed data
1048 8
        $this->append($header . $data . $unknown1 . $options . $unknown2 . $url_len . $url);
1049
1050 8
        return 0;
1051
    }
1052
1053
    /**
1054
     * Used to write internal reference hyperlinks such as "Sheet1!A1".
1055
     *
1056
     * @see writeUrl()
1057
     *
1058
     * @param int $row1 Start row
1059
     * @param int $col1 Start column
1060
     * @param int $row2 End row
1061
     * @param int $col2 End column
1062
     * @param string $url URL string
1063
     *
1064
     * @return int
1065
     */
1066 6
    public function writeUrlInternal($row1, $col1, $row2, $col2, $url)
1067
    {
1068 6
        $record = 0x01B8; // Record identifier
1069 6
        $length = 0x00000; // Bytes to follow
0 ignored issues
show
Unused Code introduced by
$length 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...
1070
1071
        // Strip URL type
1072 6
        $url = preg_replace('/^internal:/', '', $url);
1073
1074
        // Pack the undocumented parts of the hyperlink stream
1075 6
        $unknown1 = pack('H*', 'D0C9EA79F9BACE118C8200AA004BA90B02000000');
1076
1077
        // Pack the option flags
1078 6
        $options = pack('V', 0x08);
1079
1080
        // Convert the URL type and to a null terminated wchar string
1081 6
        $url .= "\0";
1082
1083
        // character count
1084 6
        $url_len = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($url);
1085 6
        $url_len = pack('V', $url_len);
1086
1087 6
        $url = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::convertEncoding($url, 'UTF-16LE', 'UTF-8');
1088
1089
        // Calculate the data length
1090 6
        $length = 0x24 + strlen($url);
1091
1092
        // Pack the header data
1093 6
        $header = pack('vv', $record, $length);
1094 6
        $data = pack('vvvv', $row1, $row2, $col1, $col2);
1095
1096
        // Write the packed data
1097 6
        $this->append($header . $data . $unknown1 . $options . $url_len . $url);
1098
1099 6
        return 0;
1100
    }
1101
1102
    /**
1103
     * Write links to external directory names such as 'c:\foo.xls',
1104
     * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'.
1105
     *
1106
     * Note: Excel writes some relative links with the $dir_long string. We ignore
1107
     * these cases for the sake of simpler code.
1108
     *
1109
     * @see writeUrl()
1110
     *
1111
     * @param int $row1 Start row
1112
     * @param int $col1 Start column
1113
     * @param int $row2 End row
1114
     * @param int $col2 End column
1115
     * @param string $url URL string
1116
     *
1117
     * @return int
1118
     */
1119
    public function writeUrlExternal($row1, $col1, $row2, $col2, $url)
1120
    {
1121
        // Network drives are different. We will handle them separately
1122
        // MS/Novell network drives and shares start with \\
1123
        if (preg_match('[^external:\\\\]', $url)) {
1124
            return; //($this->writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format));
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
1125
        }
1126
1127
        $record = 0x01B8; // Record identifier
1128
        $length = 0x00000; // Bytes to follow
0 ignored issues
show
Unused Code introduced by
$length 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...
1129
1130
        // Strip URL type and change Unix dir separator to Dos style (if needed)
1131
        //
1132
        $url = preg_replace('/^external:/', '', $url);
1133
        $url = preg_replace('/\//', '\\', $url);
1134
1135
        // Determine if the link is relative or absolute:
1136
        //   relative if link contains no dir separator, "somefile.xls"
1137
        //   relative if link starts with up-dir, "..\..\somefile.xls"
1138
        //   otherwise, absolute
1139
1140
        $absolute = 0x00; // relative path
1141
        if (preg_match('/^[A-Z]:/', $url)) {
1142
            $absolute = 0x02; // absolute path on Windows, e.g. C:\...
1143
        }
1144
        $link_type = 0x01 | $absolute;
1145
1146
        // Determine if the link contains a sheet reference and change some of the
1147
        // parameters accordingly.
1148
        // Split the dir name and sheet name (if it exists)
1149
        $dir_long = $url;
1150
        if (preg_match("/\#/", $url)) {
1151
            $link_type |= 0x08;
1152
        }
1153
1154
        // Pack the link type
1155
        $link_type = pack('V', $link_type);
1156
1157
        // Calculate the up-level dir count e.g.. (..\..\..\ == 3)
1158
        $up_count = preg_match_all("/\.\.\\\/", $dir_long, $useless);
1159
        $up_count = pack('v', $up_count);
1160
1161
        // Store the short dos dir name (null terminated)
1162
        $dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0";
1163
1164
        // Store the long dir name as a wchar string (non-null terminated)
1165
        $dir_long = $dir_long . "\0";
1166
1167
        // Pack the lengths of the dir strings
1168
        $dir_short_len = pack('V', strlen($dir_short));
1169
        $dir_long_len = pack('V', strlen($dir_long));
0 ignored issues
show
Unused Code introduced by
$dir_long_len 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...
1170
        $stream_len = pack('V', 0); //strlen($dir_long) + 0x06);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
1171
1172
        // Pack the undocumented parts of the hyperlink stream
1173
        $unknown1 = pack('H*', 'D0C9EA79F9BACE118C8200AA004BA90B02000000');
1174
        $unknown2 = pack('H*', '0303000000000000C000000000000046');
1175
        $unknown3 = pack('H*', 'FFFFADDE000000000000000000000000000000000000000');
1176
        $unknown4 = pack('v', 0x03);
0 ignored issues
show
Unused Code introduced by
$unknown4 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...
1177
1178
        // Pack the main data stream
1179
        $data = pack('vvvv', $row1, $row2, $col1, $col2) .
1180
                          $unknown1 .
1181
                          $link_type .
1182
                          $unknown2 .
1183
                          $up_count .
1184
                          $dir_short_len .
1185
                          $dir_short .
1186
                          $unknown3 .
1187
                          $stream_len; /*.
1188
                          $dir_long_len .
1189
                          $unknown4     .
1190
                          $dir_long     .
1191
                          $sheet_len    .
1192
                          $sheet        ;*/
1193
1194
        // Pack the header data
1195
        $length = strlen($data);
1196
        $header = pack('vv', $record, $length);
1197
1198
        // Write the packed data
1199
        $this->append($header . $data);
1200
1201
        return 0;
1202
    }
1203
1204
    /**
1205
     * This method is used to set the height and format for a row.
1206
     *
1207
     * @param int $row The row to set
1208
     * @param int $height Height we are giving to the row.
1209
     *                        Use null to set XF without setting height
1210
     * @param int $xfIndex The optional cell style Xf index to apply to the columns
1211
     * @param bool $hidden The optional hidden attribute
1212
     * @param int $level The optional outline level for row, in range [0,7]
1213
     */
1214 37
    private function writeRow($row, $height, $xfIndex, $hidden = false, $level = 0)
1215
    {
1216 37
        $record = 0x0208; // Record identifier
1217 37
        $length = 0x0010; // Number of bytes to follow
1218
1219 37
        $colMic = 0x0000; // First defined column
1220 37
        $colMac = 0x0000; // Last defined column
1221 37
        $irwMac = 0x0000; // Used by Excel to optimise loading
1222 37
        $reserved = 0x0000; // Reserved
1223 37
        $grbit = 0x0000; // Option flags
1224 37
        $ixfe = $xfIndex;
1225
1226 37
        if ($height < 0) {
1227 36
            $height = null;
1228
        }
1229
1230
        // Use writeRow($row, null, $XF) to set XF format without setting height
1231 37
        if ($height != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $height of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
1232 6
            $miyRw = $height * 20; // row height
1233
        } else {
1234 36
            $miyRw = 0xff; // default row height is 256
1235
        }
1236
1237
        // Set the options flags. fUnsynced is used to show that the font and row
1238
        // heights are not compatible. This is usually the case for WriteExcel.
1239
        // The collapsed flag 0x10 doesn't seem to be used to indicate that a row
1240
        // is collapsed. Instead it is used to indicate that the previous row is
1241
        // collapsed. The zero height flag, 0x20, is used to collapse a row.
1242
1243 37
        $grbit |= $level;
1244 37
        if ($hidden) {
1245 2
            $grbit |= 0x0030;
1246
        }
1247 37
        if ($height !== null) {
1248 6
            $grbit |= 0x0040; // fUnsynced
1249
        }
1250 37
        if ($xfIndex !== 0xF) {
1251
            $grbit |= 0x0080;
1252
        }
1253 37
        $grbit |= 0x0100;
1254
1255 37
        $header = pack('vv', $record, $length);
1256 37
        $data = pack('vvvvvvvv', $row, $colMic, $colMac, $miyRw, $irwMac, $reserved, $grbit, $ixfe);
1257 37
        $this->append($header . $data);
1258 37
    }
1259
1260
    /**
1261
     * Writes Excel DIMENSIONS to define the area in which there is data.
1262
     */
1263 38
    private function writeDimensions()
1264
    {
1265 38
        $record = 0x0200; // Record identifier
1266
1267 38
        $length = 0x000E;
1268 38
        $data = pack('VVvvv', $this->firstRowIndex, $this->lastRowIndex + 1, $this->firstColumnIndex, $this->lastColumnIndex + 1, 0x0000); // reserved
1269
1270 38
        $header = pack('vv', $record, $length);
1271 38
        $this->append($header . $data);
1272 38
    }
1273
1274
    /**
1275
     * Write BIFF record Window2.
1276
     */
1277 38
    private function writeWindow2()
1278
    {
1279 38
        $record = 0x023E; // Record identifier
1280 38
        $length = 0x0012;
1281
1282 38
        $grbit = 0x00B6; // Option flags
0 ignored issues
show
Unused Code introduced by
$grbit 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...
1283 38
        $rwTop = 0x0000; // Top row visible in window
1284 38
        $colLeft = 0x0000; // Leftmost column visible in window
1285
1286
        // The options flags that comprise $grbit
1287 38
        $fDspFmla = 0; // 0 - bit
1288 38
        $fDspGrid = $this->phpSheet->getShowGridlines() ? 1 : 0; // 1
1289 38
        $fDspRwCol = $this->phpSheet->getShowRowColHeaders() ? 1 : 0; // 2
1290 38
        $fFrozen = $this->phpSheet->getFreezePane() ? 1 : 0; // 3
1291 38
        $fDspZeros = 1; // 4
1292 38
        $fDefaultHdr = 1; // 5
1293 38
        $fArabic = $this->phpSheet->getRightToLeft() ? 1 : 0; // 6
1294 38
        $fDspGuts = $this->outlineOn; // 7
1295 38
        $fFrozenNoSplit = 0; // 0 - bit
1296
        // no support in PhpSpreadsheet for selected sheet, therefore sheet is only selected if it is the active sheet
1297 38
        $fSelected = ($this->phpSheet === $this->phpSheet->getParent()->getActiveSheet()) ? 1 : 0;
1298 38
        $fPaged = 1; // 2
1299 38
        $fPageBreakPreview = $this->phpSheet->getSheetView()->getView() === \PhpOffice\PhpSpreadsheet\Worksheet\SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW;
1300
1301 38
        $grbit = $fDspFmla;
1302 38
        $grbit |= $fDspGrid << 1;
1303 38
        $grbit |= $fDspRwCol << 2;
1304 38
        $grbit |= $fFrozen << 3;
1305 38
        $grbit |= $fDspZeros << 4;
1306 38
        $grbit |= $fDefaultHdr << 5;
1307 38
        $grbit |= $fArabic << 6;
1308 38
        $grbit |= $fDspGuts << 7;
1309 38
        $grbit |= $fFrozenNoSplit << 8;
1310 38
        $grbit |= $fSelected << 9;
1311 38
        $grbit |= $fPaged << 10;
1312 38
        $grbit |= $fPageBreakPreview << 11;
1313
1314 38
        $header = pack('vv', $record, $length);
1315 38
        $data = pack('vvv', $grbit, $rwTop, $colLeft);
1316
1317
        // FIXME !!!
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
1318 38
        $rgbHdr = 0x0040; // Row/column heading and gridline color index
1319 38
        $zoom_factor_page_break = ($fPageBreakPreview ? $this->phpSheet->getSheetView()->getZoomScale() : 0x0000);
1320 38
        $zoom_factor_normal = $this->phpSheet->getSheetView()->getZoomScaleNormal();
1321
1322 38
        $data .= pack('vvvvV', $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000);
1323
1324 38
        $this->append($header . $data);
1325 38
    }
1326
1327
    /**
1328
     * Write BIFF record DEFAULTROWHEIGHT.
1329
     */
1330 38
    private function writeDefaultRowHeight()
1331
    {
1332 38
        $defaultRowHeight = $this->phpSheet->getDefaultRowDimension()->getRowHeight();
1333
1334 38
        if ($defaultRowHeight < 0) {
1335 35
            return;
1336
        }
1337
1338
        // convert to twips
1339 3
        $defaultRowHeight = (int) 20 * $defaultRowHeight;
1340
1341 3
        $record = 0x0225; // Record identifier
1342 3
        $length = 0x0004; // Number of bytes to follow
1343
1344 3
        $header = pack('vv', $record, $length);
1345 3
        $data = pack('vv', 1, $defaultRowHeight);
1346 3
        $this->append($header . $data);
1347 3
    }
1348
1349
    /**
1350
     * Write BIFF record DEFCOLWIDTH if COLINFO records are in use.
1351
     */
1352 38
    private function writeDefcol()
1353
    {
1354 38
        $defaultColWidth = 8;
1355
1356 38
        $record = 0x0055; // Record identifier
1357 38
        $length = 0x0002; // Number of bytes to follow
1358
1359 38
        $header = pack('vv', $record, $length);
1360 38
        $data = pack('v', $defaultColWidth);
1361 38
        $this->append($header . $data);
1362 38
    }
1363
1364
    /**
1365
     * Write BIFF record COLINFO to define column widths.
1366
     *
1367
     * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C
1368
     * length record.
1369
     *
1370
     * @param array $col_array This is the only parameter received and is composed of the following:
1371
     *                0 => First formatted column,
1372
     *                1 => Last formatted column,
1373
     *                2 => Col width (8.43 is Excel default),
1374
     *                3 => The optional XF format of the column,
1375
     *                4 => Option flags.
1376
     *                5 => Optional outline level
1377
     */
1378 38
    private function writeColinfo($col_array)
1379
    {
1380 38
        if (isset($col_array[0])) {
1381 38
            $colFirst = $col_array[0];
1382
        }
1383 38
        if (isset($col_array[1])) {
1384 38
            $colLast = $col_array[1];
1385
        }
1386 38
        if (isset($col_array[2])) {
1387 38
            $coldx = $col_array[2];
1388
        } else {
1389
            $coldx = 8.43;
1390
        }
1391 38
        if (isset($col_array[3])) {
1392 38
            $xfIndex = $col_array[3];
1393
        } else {
1394
            $xfIndex = 15;
1395
        }
1396 38
        if (isset($col_array[4])) {
1397 38
            $grbit = $col_array[4];
1398
        } else {
1399
            $grbit = 0;
1400
        }
1401 38
        if (isset($col_array[5])) {
1402 38
            $level = $col_array[5];
1403
        } else {
1404
            $level = 0;
1405
        }
1406 38
        $record = 0x007D; // Record identifier
1407 38
        $length = 0x000C; // Number of bytes to follow
1408
1409 38
        $coldx *= 256; // Convert to units of 1/256 of a char
1410
1411 38
        $ixfe = $xfIndex;
1412 38
        $reserved = 0x0000; // Reserved
1413
1414 38
        $level = max(0, min($level, 7));
1415 38
        $grbit |= $level << 8;
1416
1417 38
        $header = pack('vv', $record, $length);
1418 38
        $data = pack('vvvvvv', $colFirst, $colLast, $coldx, $ixfe, $grbit, $reserved);
0 ignored issues
show
Bug introduced by
The variable $colFirst 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...
Bug introduced by
The variable $colLast 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...
1419 38
        $this->append($header . $data);
1420 38
    }
1421
1422
    /**
1423
     * Write BIFF record SELECTION.
1424
     */
1425 38
    private function writeSelection()
1426
    {
1427
        // look up the selected cell range
1428 38
        $selectedCells = $this->phpSheet->getSelectedCells();
0 ignored issues
show
Unused Code introduced by
$selectedCells 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...
1429 38
        $selectedCells = \PhpOffice\PhpSpreadsheet\Cell::splitRange($this->phpSheet->getSelectedCells());
1430 38
        $selectedCells = $selectedCells[0];
1431 38
        if (count($selectedCells) == 2) {
1432 13
            list($first, $last) = $selectedCells;
1433
        } else {
1434 31
            $first = $selectedCells[0];
1435 31
            $last = $selectedCells[0];
1436
        }
1437
1438 38
        list($colFirst, $rwFirst) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($first);
1439 38
        $colFirst = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($colFirst) - 1; // base 0 column index
1440 38
        --$rwFirst; // base 0 row index
1441
1442 38
        list($colLast, $rwLast) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($last);
1443 38
        $colLast = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($colLast) - 1; // base 0 column index
1444 38
        --$rwLast; // base 0 row index
1445
1446
        // make sure we are not out of bounds
1447 38
        $colFirst = min($colFirst, 255);
1448 38
        $colLast = min($colLast, 255);
1449
1450 38
        $rwFirst = min($rwFirst, 65535);
1451 38
        $rwLast = min($rwLast, 65535);
1452
1453 38
        $record = 0x001D; // Record identifier
1454 38
        $length = 0x000F; // Number of bytes to follow
1455
1456 38
        $pnn = $this->activePane; // Pane position
1457 38
        $rwAct = $rwFirst; // Active row
1458 38
        $colAct = $colFirst; // Active column
1459 38
        $irefAct = 0; // Active cell ref
1460 38
        $cref = 1; // Number of refs
1461
1462 38
        if (!isset($rwLast)) {
1463
            $rwLast = $rwFirst; // Last  row in reference
1464
        }
1465 38
        if (!isset($colLast)) {
1466
            $colLast = $colFirst; // Last  col in reference
1467
        }
1468
1469
        // Swap last row/col for first row/col as necessary
1470 38
        if ($rwFirst > $rwLast) {
1471
            list($rwFirst, $rwLast) = [$rwLast, $rwFirst];
1472
        }
1473
1474 38
        if ($colFirst > $colLast) {
1475
            list($colFirst, $colLast) = [$colLast, $colFirst];
1476
        }
1477
1478 38
        $header = pack('vv', $record, $length);
1479 38
        $data = pack('CvvvvvvCC', $pnn, $rwAct, $colAct, $irefAct, $cref, $rwFirst, $rwLast, $colFirst, $colLast);
1480 38
        $this->append($header . $data);
1481 38
    }
1482
1483
    /**
1484
     * Store the MERGEDCELLS records for all ranges of merged cells.
1485
     */
1486 38
    private function writeMergedCells()
1487
    {
1488 38
        $mergeCells = $this->phpSheet->getMergeCells();
1489 38
        $countMergeCells = count($mergeCells);
1490
1491 38
        if ($countMergeCells == 0) {
1492 37
            return;
1493
        }
1494
1495
        // maximum allowed number of merged cells per record
1496 9
        $maxCountMergeCellsPerRecord = 1027;
1497
1498
        // record identifier
1499 9
        $record = 0x00E5;
1500
1501
        // counter for total number of merged cells treated so far by the writer
1502 9
        $i = 0;
1503
1504
        // counter for number of merged cells written in record currently being written
1505 9
        $j = 0;
1506
1507
        // initialize record data
1508 9
        $recordData = '';
1509
1510
        // loop through the merged cells
1511 9
        foreach ($mergeCells as $mergeCell) {
1512 9
            ++$i;
1513 9
            ++$j;
1514
1515
            // extract the row and column indexes
1516 9
            $range = \PhpOffice\PhpSpreadsheet\Cell::splitRange($mergeCell);
0 ignored issues
show
Documentation introduced by
$mergeCell is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1517 9
            list($first, $last) = $range[0];
1518 9
            list($firstColumn, $firstRow) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($first);
1519 9
            list($lastColumn, $lastRow) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($last);
1520
1521 9
            $recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($firstColumn) - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($lastColumn) - 1);
1522
1523
            // flush record if we have reached limit for number of merged cells, or reached final merged cell
1524 9
            if ($j == $maxCountMergeCellsPerRecord or $i == $countMergeCells) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
1525 9
                $recordData = pack('v', $j) . $recordData;
1526 9
                $length = strlen($recordData);
1527 9
                $header = pack('vv', $record, $length);
1528 9
                $this->append($header . $recordData);
1529
1530
                // initialize for next record, if any
1531 9
                $recordData = '';
1532 9
                $j = 0;
1533
            }
1534
        }
1535 9
    }
1536
1537
    /**
1538
     * Write SHEETLAYOUT record.
1539
     */
1540 38
    private function writeSheetLayout()
1541
    {
1542 38
        if (!$this->phpSheet->isTabColorSet()) {
1543 38
            return;
1544
        }
1545
1546 5
        $recordData = pack(
1547 5
            'vvVVVvv',
1548 5
            0x0862,
1549 5
            0x0000, // unused
1550 5
            0x00000000, // unused
1551 5
            0x00000000, // unused
1552 5
            0x00000014, // size of record data
1553 5
            $this->colors[$this->phpSheet->getTabColor()->getRGB()], // color index
1554 5
            0x0000        // unused
1555
        );
1556
1557 5
        $length = strlen($recordData);
1558
1559 5
        $record = 0x0862; // Record identifier
1560 5
        $header = pack('vv', $record, $length);
1561 5
        $this->append($header . $recordData);
1562 5
    }
1563
1564
    /**
1565
     * Write SHEETPROTECTION.
1566
     */
1567 38
    private function writeSheetProtection()
1568
    {
1569
        // record identifier
1570 38
        $record = 0x0867;
1571
1572
        // prepare options
1573 38
        $options = (int) !$this->phpSheet->getProtection()->getObjects()
1574 38
                    | (int) !$this->phpSheet->getProtection()->getScenarios() << 1
1575 38
                    | (int) !$this->phpSheet->getProtection()->getFormatCells() << 2
1576 38
                    | (int) !$this->phpSheet->getProtection()->getFormatColumns() << 3
1577 38
                    | (int) !$this->phpSheet->getProtection()->getFormatRows() << 4
1578 38
                    | (int) !$this->phpSheet->getProtection()->getInsertColumns() << 5
1579 38
                    | (int) !$this->phpSheet->getProtection()->getInsertRows() << 6
1580 38
                    | (int) !$this->phpSheet->getProtection()->getInsertHyperlinks() << 7
1581 38
                    | (int) !$this->phpSheet->getProtection()->getDeleteColumns() << 8
1582 38
                    | (int) !$this->phpSheet->getProtection()->getDeleteRows() << 9
1583 38
                    | (int) !$this->phpSheet->getProtection()->getSelectLockedCells() << 10
1584 38
                    | (int) !$this->phpSheet->getProtection()->getSort() << 11
1585 38
                    | (int) !$this->phpSheet->getProtection()->getAutoFilter() << 12
1586 38
                    | (int) !$this->phpSheet->getProtection()->getPivotTables() << 13
1587 38
                    | (int) !$this->phpSheet->getProtection()->getSelectUnlockedCells() << 14;
1588
1589
        // record data
1590 38
        $recordData = pack(
1591 38
            'vVVCVVvv',
1592 38
            0x0867, // repeated record identifier
1593 38
            0x0000, // not used
1594 38
            0x0000, // not used
1595 38
            0x00, // not used
1596 38
            0x01000200, // unknown data
1597 38
            0xFFFFFFFF, // unknown data
1598
            $options, // options
1599 38
            0x0000 // not used
1600
        );
1601
1602 38
        $length = strlen($recordData);
1603 38
        $header = pack('vv', $record, $length);
1604
1605 38
        $this->append($header . $recordData);
1606 38
    }
1607
1608
    /**
1609
     * Write BIFF record RANGEPROTECTION.
1610
     *
1611
     * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records
1612
     * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records
1613
     */
1614 38
    private function writeRangeProtection()
1615
    {
1616 38
        foreach ($this->phpSheet->getProtectedCells() as $range => $password) {
1617
            // number of ranges, e.g. 'A1:B3 C20:D25'
1618 5
            $cellRanges = explode(' ', $range);
1619 5
            $cref = count($cellRanges);
1620
1621 5
            $recordData = pack(
1622 5
                'vvVVvCVvVv',
1623 5
                0x0868,
1624 5
                0x00,
1625 5
                0x0000,
1626 5
                0x0000,
1627 5
                0x02,
1628 5
                0x0,
1629 5
                0x0000,
1630
                $cref,
1631 5
                0x0000,
1632 5
                0x00
1633
            );
1634
1635 5
            foreach ($cellRanges as $cellRange) {
1636 5
                $recordData .= $this->writeBIFF8CellRangeAddressFixed($cellRange);
1637
            }
1638
1639
            // the rgbFeat structure
1640 5
            $recordData .= pack(
1641 5
                'VV',
1642 5
                0x0000,
1643
                hexdec($password)
1644
            );
1645
1646 5
            $recordData .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong('p' . md5($recordData));
1647
1648 5
            $length = strlen($recordData);
1649
1650 5
            $record = 0x0868; // Record identifier
1651 5
            $header = pack('vv', $record, $length);
1652 5
            $this->append($header . $recordData);
1653
        }
1654 38
    }
1655
1656
    /**
1657
     * Write BIFF record EXTERNCOUNT to indicate the number of external sheet
1658
     * references in a worksheet.
1659
     *
1660
     * Excel only stores references to external sheets that are used in formulas.
1661
     * For simplicity we store references to all the sheets in the workbook
1662
     * regardless of whether they are used or not. This reduces the overall
1663
     * complexity and eliminates the need for a two way dialogue between the formula
1664
     * parser the worksheet objects.
1665
     *
1666
     * @param int $count The number of external sheet references in this worksheet
1667
     */
1668 View Code Duplication
    private function writeExterncount($count)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
Duplication introduced by
This method seems to be duplicated in 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...
1669
    {
1670
        $record = 0x0016; // Record identifier
1671
        $length = 0x0002; // Number of bytes to follow
1672
1673
        $header = pack('vv', $record, $length);
1674
        $data = pack('v', $count);
1675
        $this->append($header . $data);
1676
    }
1677
1678
    /**
1679
     * Writes the Excel BIFF EXTERNSHEET record. These references are used by
1680
     * formulas. A formula references a sheet name via an index. Since we store a
1681
     * reference to all of the external worksheets the EXTERNSHEET index is the same
1682
     * as the worksheet index.
1683
     *
1684
     * @param string $sheetname The name of a external worksheet
1685
     */
1686
    private function writeExternsheet($sheetname)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
1687
    {
1688
        $record = 0x0017; // Record identifier
1689
1690
        // References to the current sheet are encoded differently to references to
1691
        // external sheets.
1692
        //
1693
        if ($this->phpSheet->getTitle() == $sheetname) {
1694
            $sheetname = '';
1695
            $length = 0x02; // The following 2 bytes
1696
            $cch = 1; // The following byte
1697
            $rgch = 0x02; // Self reference
1698
        } else {
1699
            $length = 0x02 + strlen($sheetname);
1700
            $cch = strlen($sheetname);
1701
            $rgch = 0x03; // Reference to a sheet in the current workbook
1702
        }
1703
1704
        $header = pack('vv', $record, $length);
1705
        $data = pack('CC', $cch, $rgch);
1706
        $this->append($header . $data . $sheetname);
1707
    }
1708
1709
    /**
1710
     * Writes the Excel BIFF PANE record.
1711
     * The panes can either be frozen or thawed (unfrozen).
1712
     * Frozen panes are specified in terms of an integer number of rows and columns.
1713
     * Thawed panes are specified in terms of Excel's units for rows and columns.
1714
     */
1715 3
    private function writePanes()
1716
    {
1717 3
        $panes = [];
1718 3
        if ($freezePane = $this->phpSheet->getFreezePane()) {
1719 3
            list($column, $row) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($freezePane);
1720 3
            $panes[0] = $row - 1;
1721 3
            $panes[1] = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($column) - 1;
1722
        } else {
1723
            // thaw panes
1724
            return;
1725
        }
1726
1727 3
        $y = isset($panes[0]) ? $panes[0] : null;
1728 3
        $x = isset($panes[1]) ? $panes[1] : null;
1729 3
        $rwTop = isset($panes[2]) ? $panes[2] : null;
1730 3
        $colLeft = isset($panes[3]) ? $panes[3] : null;
1731 3
        if (count($panes) > 4) { // if Active pane was received
1732
            $pnnAct = $panes[4];
1733
        } else {
1734 3
            $pnnAct = null;
1735
        }
1736 3
        $record = 0x0041; // Record identifier
1737 3
        $length = 0x000A; // Number of bytes to follow
1738
1739
        // Code specific to frozen or thawed panes.
1740 3
        if ($this->phpSheet->getFreezePane()) {
1741
            // Set default values for $rwTop and $colLeft
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
1742 3
            if (!isset($rwTop)) {
1743 3
                $rwTop = $y;
1744
            }
1745 3
            if (!isset($colLeft)) {
1746 3
                $colLeft = $x;
1747
            }
1748
        } else {
1749
            // Set default values for $rwTop and $colLeft
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
1750
            if (!isset($rwTop)) {
1751
                $rwTop = 0;
1752
            }
1753
            if (!isset($colLeft)) {
1754
                $colLeft = 0;
1755
            }
1756
1757
            // Convert Excel's row and column units to the internal units.
1758
            // The default row height is 12.75
1759
            // The default column width is 8.43
1760
            // The following slope and intersection values were interpolated.
1761
            //
1762
            $y = 20 * $y + 255;
1763
            $x = 113.879 * $x + 390;
1764
        }
1765
1766
        // Determine which pane should be active. There is also the undocumented
1767
        // option to override this should it be necessary: may be removed later.
1768
        //
1769 3
        if (!isset($pnnAct)) {
1770 3
            if ($x != 0 && $y != 0) {
1771
                $pnnAct = 0; // Bottom right
1772
            }
1773 3
            if ($x != 0 && $y == 0) {
1774
                $pnnAct = 1; // Top right
1775
            }
1776 3
            if ($x == 0 && $y != 0) {
1777 3
                $pnnAct = 2; // Bottom left
1778
            }
1779 3
            if ($x == 0 && $y == 0) {
1780
                $pnnAct = 3; // Top left
1781
            }
1782
        }
1783
1784 3
        $this->activePane = $pnnAct; // Used in writeSelection
1785
1786 3
        $header = pack('vv', $record, $length);
1787 3
        $data = pack('vvvvv', $x, $y, $rwTop, $colLeft, $pnnAct);
1788 3
        $this->append($header . $data);
1789 3
    }
1790
1791
    /**
1792
     * Store the page setup SETUP BIFF record.
1793
     */
1794 38
    private function writeSetup()
1795
    {
1796 38
        $record = 0x00A1; // Record identifier
1797 38
        $length = 0x0022; // Number of bytes to follow
1798
1799 38
        $iPaperSize = $this->phpSheet->getPageSetup()->getPaperSize(); // Paper size
1800
1801 38
        $iScale = $this->phpSheet->getPageSetup()->getScale() ?
1802 38
            $this->phpSheet->getPageSetup()->getScale() : 100; // Print scaling factor
1803
1804 38
        $iPageStart = 0x01; // Starting page number
1805 38
        $iFitWidth = (int) $this->phpSheet->getPageSetup()->getFitToWidth(); // Fit to number of pages wide
1806 38
        $iFitHeight = (int) $this->phpSheet->getPageSetup()->getFitToHeight(); // Fit to number of pages high
1807 38
        $grbit = 0x00; // Option flags
0 ignored issues
show
Unused Code introduced by
$grbit 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...
1808 38
        $iRes = 0x0258; // Print resolution
1809 38
        $iVRes = 0x0258; // Vertical print resolution
1810
1811 38
        $numHdr = $this->phpSheet->getPageMargins()->getHeader(); // Header Margin
1812
1813 38
        $numFtr = $this->phpSheet->getPageMargins()->getFooter(); // Footer Margin
1814 38
        $iCopies = 0x01; // Number of copies
1815
1816 38
        $fLeftToRight = 0x0; // Print over then down
1817
1818
        // Page orientation
1819 38
        $fLandscape = ($this->phpSheet->getPageSetup()->getOrientation() == \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE) ?
1820 38
            0x0 : 0x1;
1821
1822 38
        $fNoPls = 0x0; // Setup not read from printer
1823 38
        $fNoColor = 0x0; // Print black and white
1824 38
        $fDraft = 0x0; // Print draft quality
1825 38
        $fNotes = 0x0; // Print notes
1826 38
        $fNoOrient = 0x0; // Orientation not set
1827 38
        $fUsePage = 0x0; // Use custom starting page
1828
1829 38
        $grbit = $fLeftToRight;
1830 38
        $grbit |= $fLandscape << 1;
1831 38
        $grbit |= $fNoPls << 2;
1832 38
        $grbit |= $fNoColor << 3;
1833 38
        $grbit |= $fDraft << 4;
1834 38
        $grbit |= $fNotes << 5;
1835 38
        $grbit |= $fNoOrient << 6;
1836 38
        $grbit |= $fUsePage << 7;
1837
1838 38
        $numHdr = pack('d', $numHdr);
1839 38
        $numFtr = pack('d', $numFtr);
1840 38
        if (self::getByteOrder()) { // if it's Big Endian
1841
            $numHdr = strrev($numHdr);
1842
            $numFtr = strrev($numFtr);
1843
        }
1844
1845 38
        $header = pack('vv', $record, $length);
1846 38
        $data1 = pack('vvvvvvvv', $iPaperSize, $iScale, $iPageStart, $iFitWidth, $iFitHeight, $grbit, $iRes, $iVRes);
1847 38
        $data2 = $numHdr . $numFtr;
1848 38
        $data3 = pack('v', $iCopies);
1849 38
        $this->append($header . $data1 . $data2 . $data3);
1850 38
    }
1851
1852
    /**
1853
     * Store the header caption BIFF record.
1854
     */
1855 38 View Code Duplication
    private function writeHeader()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1856
    {
1857 38
        $record = 0x0014; // Record identifier
1858
1859
        /* removing for now
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% 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...
1860
        // need to fix character count (multibyte!)
1861
        if (strlen($this->phpSheet->getHeaderFooter()->getOddHeader()) <= 255) {
1862
            $str      = $this->phpSheet->getHeaderFooter()->getOddHeader();       // header string
1863
        } else {
1864
            $str = '';
1865
        }
1866
        */
1867
1868 38
        $recordData = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($this->phpSheet->getHeaderFooter()->getOddHeader());
1869 38
        $length = strlen($recordData);
1870
1871 38
        $header = pack('vv', $record, $length);
1872
1873 38
        $this->append($header . $recordData);
1874 38
    }
1875
1876
    /**
1877
     * Store the footer caption BIFF record.
1878
     */
1879 38 View Code Duplication
    private function writeFooter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1880
    {
1881 38
        $record = 0x0015; // Record identifier
1882
1883
        /* removing for now
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% 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...
1884
        // need to fix character count (multibyte!)
1885
        if (strlen($this->phpSheet->getHeaderFooter()->getOddFooter()) <= 255) {
1886
            $str = $this->phpSheet->getHeaderFooter()->getOddFooter();
1887
        } else {
1888
            $str = '';
1889
        }
1890
        */
1891
1892 38
        $recordData = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($this->phpSheet->getHeaderFooter()->getOddFooter());
1893 38
        $length = strlen($recordData);
1894
1895 38
        $header = pack('vv', $record, $length);
1896
1897 38
        $this->append($header . $recordData);
1898 38
    }
1899
1900
    /**
1901
     * Store the horizontal centering HCENTER BIFF record.
1902
     */
1903 38 View Code Duplication
    private function writeHcenter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1904
    {
1905 38
        $record = 0x0083; // Record identifier
1906 38
        $length = 0x0002; // Bytes to follow
1907
1908 38
        $fHCenter = $this->phpSheet->getPageSetup()->getHorizontalCentered() ? 1 : 0; // Horizontal centering
1909
1910 38
        $header = pack('vv', $record, $length);
1911 38
        $data = pack('v', $fHCenter);
1912
1913 38
        $this->append($header . $data);
1914 38
    }
1915
1916
    /**
1917
     * Store the vertical centering VCENTER BIFF record.
1918
     */
1919 38 View Code Duplication
    private function writeVcenter()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1920
    {
1921 38
        $record = 0x0084; // Record identifier
1922 38
        $length = 0x0002; // Bytes to follow
1923
1924 38
        $fVCenter = $this->phpSheet->getPageSetup()->getVerticalCentered() ? 1 : 0; // Horizontal centering
1925
1926 38
        $header = pack('vv', $record, $length);
1927 38
        $data = pack('v', $fVCenter);
1928 38
        $this->append($header . $data);
1929 38
    }
1930
1931
    /**
1932
     * Store the LEFTMARGIN BIFF record.
1933
     */
1934 38 View Code Duplication
    private function writeMarginLeft()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1935
    {
1936 38
        $record = 0x0026; // Record identifier
1937 38
        $length = 0x0008; // Bytes to follow
1938
1939 38
        $margin = $this->phpSheet->getPageMargins()->getLeft(); // Margin in inches
1940
1941 38
        $header = pack('vv', $record, $length);
1942 38
        $data = pack('d', $margin);
1943 38
        if (self::getByteOrder()) { // if it's Big Endian
1944
            $data = strrev($data);
1945
        }
1946
1947 38
        $this->append($header . $data);
1948 38
    }
1949
1950
    /**
1951
     * Store the RIGHTMARGIN BIFF record.
1952
     */
1953 38 View Code Duplication
    private function writeMarginRight()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1954
    {
1955 38
        $record = 0x0027; // Record identifier
1956 38
        $length = 0x0008; // Bytes to follow
1957
1958 38
        $margin = $this->phpSheet->getPageMargins()->getRight(); // Margin in inches
1959
1960 38
        $header = pack('vv', $record, $length);
1961 38
        $data = pack('d', $margin);
1962 38
        if (self::getByteOrder()) { // if it's Big Endian
1963
            $data = strrev($data);
1964
        }
1965
1966 38
        $this->append($header . $data);
1967 38
    }
1968
1969
    /**
1970
     * Store the TOPMARGIN BIFF record.
1971
     */
1972 38 View Code Duplication
    private function writeMarginTop()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1973
    {
1974 38
        $record = 0x0028; // Record identifier
1975 38
        $length = 0x0008; // Bytes to follow
1976
1977 38
        $margin = $this->phpSheet->getPageMargins()->getTop(); // Margin in inches
1978
1979 38
        $header = pack('vv', $record, $length);
1980 38
        $data = pack('d', $margin);
1981 38
        if (self::getByteOrder()) { // if it's Big Endian
1982
            $data = strrev($data);
1983
        }
1984
1985 38
        $this->append($header . $data);
1986 38
    }
1987
1988
    /**
1989
     * Store the BOTTOMMARGIN BIFF record.
1990
     */
1991 38 View Code Duplication
    private function writeMarginBottom()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1992
    {
1993 38
        $record = 0x0029; // Record identifier
1994 38
        $length = 0x0008; // Bytes to follow
1995
1996 38
        $margin = $this->phpSheet->getPageMargins()->getBottom(); // Margin in inches
1997
1998 38
        $header = pack('vv', $record, $length);
1999 38
        $data = pack('d', $margin);
2000 38
        if (self::getByteOrder()) { // if it's Big Endian
2001
            $data = strrev($data);
2002
        }
2003
2004 38
        $this->append($header . $data);
2005 38
    }
2006
2007
    /**
2008
     * Write the PRINTHEADERS BIFF record.
2009
     */
2010 38 View Code Duplication
    private function writePrintHeaders()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2011
    {
2012 38
        $record = 0x002a; // Record identifier
2013 38
        $length = 0x0002; // Bytes to follow
2014
2015 38
        $fPrintRwCol = $this->printHeaders; // Boolean flag
2016
2017 38
        $header = pack('vv', $record, $length);
2018 38
        $data = pack('v', $fPrintRwCol);
2019 38
        $this->append($header . $data);
2020 38
    }
2021
2022
    /**
2023
     * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the
2024
     * GRIDSET record.
2025
     */
2026 38 View Code Duplication
    private function writePrintGridlines()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2027
    {
2028 38
        $record = 0x002b; // Record identifier
2029 38
        $length = 0x0002; // Bytes to follow
2030
2031 38
        $fPrintGrid = $this->phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag
2032
2033 38
        $header = pack('vv', $record, $length);
2034 38
        $data = pack('v', $fPrintGrid);
2035 38
        $this->append($header . $data);
2036 38
    }
2037
2038
    /**
2039
     * Write the GRIDSET BIFF record. Must be used in conjunction with the
2040
     * PRINTGRIDLINES record.
2041
     */
2042 38
    private function writeGridset()
2043
    {
2044 38
        $record = 0x0082; // Record identifier
2045 38
        $length = 0x0002; // Bytes to follow
2046
2047 38
        $fGridSet = !$this->phpSheet->getPrintGridlines(); // Boolean flag
2048
2049 38
        $header = pack('vv', $record, $length);
2050 38
        $data = pack('v', $fGridSet);
2051 38
        $this->append($header . $data);
2052 38
    }
2053
2054
    /**
2055
     * Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet.
2056
     */
2057 3
    private function writeAutoFilterInfo()
2058
    {
2059 3
        $record = 0x009D; // Record identifier
2060 3
        $length = 0x0002; // Bytes to follow
2061
2062 3
        $rangeBounds = \PhpOffice\PhpSpreadsheet\Cell::rangeBoundaries($this->phpSheet->getAutoFilter()->getRange());
2063 3
        $iNumFilters = 1 + $rangeBounds[1][0] - $rangeBounds[0][0];
2064
2065 3
        $header = pack('vv', $record, $length);
2066 3
        $data = pack('v', $iNumFilters);
2067 3
        $this->append($header . $data);
2068 3
    }
2069
2070
    /**
2071
     * Write the GUTS BIFF record. This is used to configure the gutter margins
2072
     * where Excel outline symbols are displayed. The visibility of the gutters is
2073
     * controlled by a flag in WSBOOL.
2074
     *
2075
     * @see writeWsbool()
2076
     */
2077 38
    private function writeGuts()
2078
    {
2079 38
        $record = 0x0080; // Record identifier
2080 38
        $length = 0x0008; // Bytes to follow
2081
2082 38
        $dxRwGut = 0x0000; // Size of row gutter
2083 38
        $dxColGut = 0x0000; // Size of col gutter
2084
2085
        // determine maximum row outline level
2086 38
        $maxRowOutlineLevel = 0;
2087 38
        foreach ($this->phpSheet->getRowDimensions() as $rowDimension) {
2088 37
            $maxRowOutlineLevel = max($maxRowOutlineLevel, $rowDimension->getOutlineLevel());
2089
        }
2090
2091 38
        $col_level = 0;
2092
2093
        // Calculate the maximum column outline level. The equivalent calculation
2094
        // for the row outline level is carried out in writeRow().
2095 38
        $colcount = count($this->columnInfo);
2096 38
        for ($i = 0; $i < $colcount; ++$i) {
2097 38
            $col_level = max($this->columnInfo[$i][5], $col_level);
2098
        }
2099
2100
        // Set the limits for the outline levels (0 <= x <= 7).
2101 38
        $col_level = max(0, min($col_level, 7));
2102
2103
        // The displayed level is one greater than the max outline levels
2104 38
        if ($maxRowOutlineLevel) {
2105
            ++$maxRowOutlineLevel;
2106
        }
2107 38
        if ($col_level) {
2108 1
            ++$col_level;
2109
        }
2110
2111 38
        $header = pack('vv', $record, $length);
2112 38
        $data = pack('vvvv', $dxRwGut, $dxColGut, $maxRowOutlineLevel, $col_level);
2113
2114 38
        $this->append($header . $data);
2115 38
    }
2116
2117
    /**
2118
     * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction
2119
     * with the SETUP record.
2120
     */
2121 38
    private function writeWsbool()
2122
    {
2123 38
        $record = 0x0081; // Record identifier
2124 38
        $length = 0x0002; // Bytes to follow
2125 38
        $grbit = 0x0000;
2126
2127
        // The only option that is of interest is the flag for fit to page. So we
2128
        // set all the options in one go.
2129
        //
2130
        // Set the option flags
2131 38
        $grbit |= 0x0001; // Auto page breaks visible
2132 38
        if ($this->outlineStyle) {
2133
            $grbit |= 0x0020; // Auto outline styles
2134
        }
2135 38
        if ($this->phpSheet->getShowSummaryBelow()) {
2136 38
            $grbit |= 0x0040; // Outline summary below
2137
        }
2138 38
        if ($this->phpSheet->getShowSummaryRight()) {
2139 38
            $grbit |= 0x0080; // Outline summary right
2140
        }
2141 38
        if ($this->phpSheet->getPageSetup()->getFitToPage()) {
2142
            $grbit |= 0x0100; // Page setup fit to page
2143
        }
2144 38
        if ($this->outlineOn) {
2145 38
            $grbit |= 0x0400; // Outline symbols displayed
2146
        }
2147
2148 38
        $header = pack('vv', $record, $length);
2149 38
        $data = pack('v', $grbit);
2150 38
        $this->append($header . $data);
2151 38
    }
2152
2153
    /**
2154
     * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records.
2155
     */
2156 38
    private function writeBreaks()
2157
    {
2158
        // initialize
2159 38
        $vbreaks = [];
2160 38
        $hbreaks = [];
2161
2162 38
        foreach ($this->phpSheet->getBreaks() as $cell => $breakType) {
2163
            // Fetch coordinates
2164 1
            $coordinates = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($cell);
2165
2166
            // Decide what to do by the type of break
2167
            switch ($breakType) {
2168 1
                case \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_COLUMN:
2169
                    // Add to list of vertical breaks
2170
                    $vbreaks[] = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($coordinates[0]) - 1;
2171
                    break;
2172 1
                case \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_ROW:
2173
                    // Add to list of horizontal breaks
2174 1
                    $hbreaks[] = $coordinates[1];
2175 1
                    break;
2176
                case \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_NONE:
2177
                default:
2178
                    // Nothing to do
2179
                    break;
2180
            }
2181
        }
2182
2183
        //horizontal page breaks
2184 38
        if (!empty($hbreaks)) {
2185
            // Sort and filter array of page breaks
2186 1
            sort($hbreaks, SORT_NUMERIC);
2187 1
            if ($hbreaks[0] == 0) { // don't use first break if it's 0
2188
                array_shift($hbreaks);
2189
            }
2190
2191 1
            $record = 0x001b; // Record identifier
2192 1
            $cbrk = count($hbreaks); // Number of page breaks
2193 1
            $length = 2 + 6 * $cbrk; // Bytes to follow
2194
2195 1
            $header = pack('vv', $record, $length);
2196 1
            $data = pack('v', $cbrk);
2197
2198
            // Append each page break
2199 1
            foreach ($hbreaks as $hbreak) {
2200 1
                $data .= pack('vvv', $hbreak, 0x0000, 0x00ff);
2201
            }
2202
2203 1
            $this->append($header . $data);
2204
        }
2205
2206
        // vertical page breaks
2207 38
        if (!empty($vbreaks)) {
2208
            // 1000 vertical pagebreaks appears to be an internal Excel 5 limit.
2209
            // It is slightly higher in Excel 97/200, approx. 1026
2210
            $vbreaks = array_slice($vbreaks, 0, 1000);
2211
2212
            // Sort and filter array of page breaks
2213
            sort($vbreaks, SORT_NUMERIC);
2214
            if ($vbreaks[0] == 0) { // don't use first break if it's 0
2215
                array_shift($vbreaks);
2216
            }
2217
2218
            $record = 0x001a; // Record identifier
2219
            $cbrk = count($vbreaks); // Number of page breaks
2220
            $length = 2 + 6 * $cbrk; // Bytes to follow
2221
2222
            $header = pack('vv', $record, $length);
2223
            $data = pack('v', $cbrk);
2224
2225
            // Append each page break
2226
            foreach ($vbreaks as $vbreak) {
2227
                $data .= pack('vvv', $vbreak, 0x0000, 0xffff);
2228
            }
2229
2230
            $this->append($header . $data);
2231
        }
2232 38
    }
2233
2234
    /**
2235
     * Set the Biff PROTECT record to indicate that the worksheet is protected.
2236
     */
2237 38 View Code Duplication
    private function writeProtect()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2238
    {
2239
        // Exit unless sheet protection has been specified
2240 38
        if (!$this->phpSheet->getProtection()->getSheet()) {
2241 36
            return;
2242
        }
2243
2244 7
        $record = 0x0012; // Record identifier
2245 7
        $length = 0x0002; // Bytes to follow
2246
2247 7
        $fLock = 1; // Worksheet is protected
2248
2249 7
        $header = pack('vv', $record, $length);
2250 7
        $data = pack('v', $fLock);
2251
2252 7
        $this->append($header . $data);
2253 7
    }
2254
2255
    /**
2256
     * Write SCENPROTECT.
2257
     */
2258 38 View Code Duplication
    private function writeScenProtect()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2259
    {
2260
        // Exit if sheet protection is not active
2261 38
        if (!$this->phpSheet->getProtection()->getSheet()) {
2262 36
            return;
2263
        }
2264
2265
        // Exit if scenarios are not protected
2266 7
        if (!$this->phpSheet->getProtection()->getScenarios()) {
2267 7
            return;
2268
        }
2269
2270
        $record = 0x00DD; // Record identifier
2271
        $length = 0x0002; // Bytes to follow
2272
2273
        $header = pack('vv', $record, $length);
2274
        $data = pack('v', 1);
2275
2276
        $this->append($header . $data);
2277
    }
2278
2279
    /**
2280
     * Write OBJECTPROTECT.
2281
     */
2282 38 View Code Duplication
    private function writeObjectProtect()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2283
    {
2284
        // Exit if sheet protection is not active
2285 38
        if (!$this->phpSheet->getProtection()->getSheet()) {
2286 36
            return;
2287
        }
2288
2289
        // Exit if objects are not protected
2290 7
        if (!$this->phpSheet->getProtection()->getObjects()) {
2291 7
            return;
2292
        }
2293
2294
        $record = 0x0063; // Record identifier
2295
        $length = 0x0002; // Bytes to follow
2296
2297
        $header = pack('vv', $record, $length);
2298
        $data = pack('v', 1);
2299
2300
        $this->append($header . $data);
2301
    }
2302
2303
    /**
2304
     * Write the worksheet PASSWORD record.
2305
     */
2306 38
    private function writePassword()
2307
    {
2308
        // Exit unless sheet protection and password have been specified
2309 38
        if (!$this->phpSheet->getProtection()->getSheet() || !$this->phpSheet->getProtection()->getPassword()) {
2310 37
            return;
2311
        }
2312
2313 1
        $record = 0x0013; // Record identifier
2314 1
        $length = 0x0002; // Bytes to follow
2315
2316 1
        $wPassword = hexdec($this->phpSheet->getProtection()->getPassword()); // Encoded password
2317
2318 1
        $header = pack('vv', $record, $length);
2319 1
        $data = pack('v', $wPassword);
2320
2321 1
        $this->append($header . $data);
2322 1
    }
2323
2324
    /**
2325
     * Insert a 24bit bitmap image in a worksheet.
2326
     *
2327
     * @param int $row The row we are going to insert the bitmap into
2328
     * @param int $col The column we are going to insert the bitmap into
2329
     * @param mixed $bitmap The bitmap filename or GD-image resource
2330
     * @param int $x the horizontal position (offset) of the image inside the cell
2331
     * @param int $y the vertical position (offset) of the image inside the cell
2332
     * @param float $scale_x The horizontal scale
2333
     * @param float $scale_y The vertical scale
2334
     */
2335
    public function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1)
2336
    {
2337
        $bitmap_array = (is_resource($bitmap) ? $this->processBitmapGd($bitmap) : $this->processBitmap($bitmap));
2338
        list($width, $height, $size, $data) = $bitmap_array;
2339
2340
        // Scale the frame of the image.
2341
        $width *= $scale_x;
2342
        $height *= $scale_y;
2343
2344
        // Calculate the vertices of the image and write the OBJ record
2345
        $this->positionImage($col, $row, $x, $y, $width, $height);
2346
2347
        // Write the IMDATA record to store the bitmap data
2348
        $record = 0x007f;
2349
        $length = 8 + $size;
2350
        $cf = 0x09;
2351
        $env = 0x01;
2352
        $lcb = $size;
2353
2354
        $header = pack('vvvvV', $record, $length, $cf, $env, $lcb);
2355
        $this->append($header . $data);
2356
    }
2357
2358
    /**
2359
     * Calculate the vertices that define the position of the image as required by
2360
     * the OBJ record.
2361
     *
2362
     *         +------------+------------+
2363
     *         |     A      |      B     |
2364
     *   +-----+------------+------------+
2365
     *   |     |(x1,y1)     |            |
2366
     *   |  1  |(A1)._______|______      |
2367
     *   |     |    |              |     |
2368
     *   |     |    |              |     |
2369
     *   +-----+----|    BITMAP    |-----+
2370
     *   |     |    |              |     |
2371
     *   |  2  |    |______________.     |
2372
     *   |     |            |        (B2)|
2373
     *   |     |            |     (x2,y2)|
2374
     *   +---- +------------+------------+
2375
     *
2376
     * Example of a bitmap that covers some of the area from cell A1 to cell B2.
2377
     *
2378
     * Based on the width and height of the bitmap we need to calculate 8 vars:
2379
     *     $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
2380
     * The width and height of the cells are also variable and have to be taken into
2381
     * account.
2382
     * The values of $col_start and $row_start are passed in from the calling
2383
     * function. The values of $col_end and $row_end are calculated by subtracting
2384
     * the width and height of the bitmap from the width and height of the
2385
     * underlying cells.
2386
     * The vertices are expressed as a percentage of the underlying cell width as
2387
     * follows (rhs values are in pixels):
2388
     *
2389
     *       x1 = X / W *1024
2390
     *       y1 = Y / H *256
2391
     *       x2 = (X-1) / W *1024
2392
     *       y2 = (Y-1) / H *256
2393
     *
2394
     *       Where:  X is distance from the left side of the underlying cell
2395
     *               Y is distance from the top of the underlying cell
2396
     *               W is the width of the cell
2397
     *               H is the height of the cell
2398
     * The SDK incorrectly states that the height should be expressed as a
2399
     *        percentage of 1024.
2400
     *
2401
     * @param int $col_start Col containing upper left corner of object
2402
     * @param int $row_start Row containing top left corner of object
2403
     * @param int $x1 Distance to left side of object
2404
     * @param int $y1 Distance to top of object
2405
     * @param int $width Width of image frame
2406
     * @param int $height Height of image frame
2407
     */
2408
    public function positionImage($col_start, $row_start, $x1, $y1, $width, $height)
2409
    {
2410
        // Initialise end cell to the same as the start cell
2411
        $col_end = $col_start; // Col containing lower right corner of object
2412
        $row_end = $row_start; // Row containing bottom right corner of object
2413
2414
        // Zero the specified offset if greater than the cell dimensions
2415
        if ($x1 >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_start))) {
2416
            $x1 = 0;
2417
        }
2418
        if ($y1 >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_start + 1)) {
2419
            $y1 = 0;
2420
        }
2421
2422
        $width = $width + $x1 - 1;
2423
        $height = $height + $y1 - 1;
2424
2425
        // Subtract the underlying cell widths to find the end cell of the image
2426
        while ($width >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end))) {
2427
            $width -= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end));
2428
            ++$col_end;
2429
        }
2430
2431
        // Subtract the underlying cell heights to find the end cell of the image
2432
        while ($height >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1)) {
2433
            $height -= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1);
2434
            ++$row_end;
2435
        }
2436
2437
        // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
2438
        // with zero eight or width.
2439
        //
2440
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_start)) == 0) {
2441
            return;
2442
        }
2443
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end)) == 0) {
2444
            return;
2445
        }
2446
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_start + 1) == 0) {
2447
            return;
2448
        }
2449
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1) == 0) {
2450
            return;
2451
        }
2452
2453
        // Convert the pixel values to the percentage value expected by Excel
2454
        $x1 = $x1 / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_start)) * 1024;
2455
        $y1 = $y1 / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_start + 1) * 256;
2456
        $x2 = $width / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object
2457
        $y2 = $height / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1) * 256; // Distance to bottom of object
2458
2459
        $this->writeObjPicture($col_start, $x1, $row_start, $y1, $col_end, $x2, $row_end, $y2);
2460
    }
2461
2462
    /**
2463
     * Store the OBJ record that precedes an IMDATA record. This could be generalise
2464
     * to support other Excel objects.
2465
     *
2466
     * @param int $colL Column containing upper left corner of object
2467
     * @param int $dxL Distance from left side of cell
2468
     * @param int $rwT Row containing top left corner of object
2469
     * @param int $dyT Distance from top of cell
2470
     * @param int $colR Column containing lower right corner of object
2471
     * @param int $dxR Distance from right of cell
2472
     * @param int $rwB Row containing bottom right corner of object
2473
     * @param int $dyB Distance from bottom of cell
2474
     */
2475
    private function writeObjPicture($colL, $dxL, $rwT, $dyT, $colR, $dxR, $rwB, $dyB)
2476
    {
2477
        $record = 0x005d; // Record identifier
2478
        $length = 0x003c; // Bytes to follow
2479
2480
        $cObj = 0x0001; // Count of objects in file (set to 1)
2481
        $OT = 0x0008; // Object type. 8 = Picture
2482
        $id = 0x0001; // Object ID
2483
        $grbit = 0x0614; // Option flags
2484
2485
        $cbMacro = 0x0000; // Length of FMLA structure
2486
        $Reserved1 = 0x0000; // Reserved
2487
        $Reserved2 = 0x0000; // Reserved
2488
2489
        $icvBack = 0x09; // Background colour
2490
        $icvFore = 0x09; // Foreground colour
2491
        $fls = 0x00; // Fill pattern
2492
        $fAuto = 0x00; // Automatic fill
2493
        $icv = 0x08; // Line colour
2494
        $lns = 0xff; // Line style
2495
        $lnw = 0x01; // Line weight
2496
        $fAutoB = 0x00; // Automatic border
2497
        $frs = 0x0000; // Frame style
2498
        $cf = 0x0009; // Image format, 9 = bitmap
2499
        $Reserved3 = 0x0000; // Reserved
2500
        $cbPictFmla = 0x0000; // Length of FMLA structure
2501
        $Reserved4 = 0x0000; // Reserved
2502
        $grbit2 = 0x0001; // Option flags
2503
        $Reserved5 = 0x0000; // Reserved
2504
2505
        $header = pack('vv', $record, $length);
2506
        $data = pack('V', $cObj);
2507
        $data .= pack('v', $OT);
2508
        $data .= pack('v', $id);
2509
        $data .= pack('v', $grbit);
2510
        $data .= pack('v', $colL);
2511
        $data .= pack('v', $dxL);
2512
        $data .= pack('v', $rwT);
2513
        $data .= pack('v', $dyT);
2514
        $data .= pack('v', $colR);
2515
        $data .= pack('v', $dxR);
2516
        $data .= pack('v', $rwB);
2517
        $data .= pack('v', $dyB);
2518
        $data .= pack('v', $cbMacro);
2519
        $data .= pack('V', $Reserved1);
2520
        $data .= pack('v', $Reserved2);
2521
        $data .= pack('C', $icvBack);
2522
        $data .= pack('C', $icvFore);
2523
        $data .= pack('C', $fls);
2524
        $data .= pack('C', $fAuto);
2525
        $data .= pack('C', $icv);
2526
        $data .= pack('C', $lns);
2527
        $data .= pack('C', $lnw);
2528
        $data .= pack('C', $fAutoB);
2529
        $data .= pack('v', $frs);
2530
        $data .= pack('V', $cf);
2531
        $data .= pack('v', $Reserved3);
2532
        $data .= pack('v', $cbPictFmla);
2533
        $data .= pack('v', $Reserved4);
2534
        $data .= pack('v', $grbit2);
2535
        $data .= pack('V', $Reserved5);
2536
2537
        $this->append($header . $data);
2538
    }
2539
2540
    /**
2541
     * Convert a GD-image into the internal format.
2542
     *
2543
     * @param resource $image The image to process
2544
     *
2545
     * @return array Array with data and properties of the bitmap
2546
     */
2547
    public function processBitmapGd($image)
2548
    {
2549
        $width = imagesx($image);
2550
        $height = imagesy($image);
2551
2552
        $data = pack('Vvvvv', 0x000c, $width, $height, 0x01, 0x18);
2553
        for ($j = $height; --$j;) {
2554
            for ($i = 0; $i < $width; ++$i) {
2555
                $color = imagecolorsforindex($image, imagecolorat($image, $i, $j));
2556
                foreach (['red', 'green', 'blue'] as $key) {
2557
                    $color[$key] = $color[$key] + round((255 - $color[$key]) * $color['alpha'] / 127);
2558
                }
2559
                $data .= chr($color['blue']) . chr($color['green']) . chr($color['red']);
2560
            }
2561
            if (3 * $width % 4) {
2562
                $data .= str_repeat("\x00", 4 - 3 * $width % 4);
2563
            }
2564
        }
2565
2566
        return [$width, $height, strlen($data), $data];
2567
    }
2568
2569
    /**
2570
     * Convert a 24 bit bitmap into the modified internal format used by Windows.
2571
     * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
2572
     * MSDN library.
2573
     *
2574
     * @param string $bitmap The bitmap to process
2575
     *
2576
     * @return array Array with data and properties of the bitmap
2577
     */
2578
    public function processBitmap($bitmap)
2579
    {
2580
        // Open file.
2581
        $bmp_fd = @fopen($bitmap, 'rb');
2582
        if (!$bmp_fd) {
2583
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("Couldn't import $bitmap");
2584
        }
2585
2586
        // Slurp the file into a string.
2587
        $data = fread($bmp_fd, filesize($bitmap));
2588
2589
        // Check that the file is big enough to be a bitmap.
2590
        if (strlen($data) <= 0x36) {
2591
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap doesn't contain enough data.\n");
2592
        }
2593
2594
        // The first 2 bytes are used to identify the bitmap.
2595
        $identity = unpack('A2ident', $data);
2596
        if ($identity['ident'] != 'BM') {
2597
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap doesn't appear to be a valid bitmap image.\n");
2598
        }
2599
2600
        // Remove bitmap data: ID.
2601
        $data = substr($data, 2);
2602
2603
        // Read and remove the bitmap size. This is more reliable than reading
2604
        // the data size at offset 0x22.
2605
        //
2606
        $size_array = unpack('Vsa', substr($data, 0, 4));
2607
        $size = $size_array['sa'];
2608
        $data = substr($data, 4);
2609
        $size -= 0x36; // Subtract size of bitmap header.
2610
        $size += 0x0C; // Add size of BIFF header.
2611
2612
        // Remove bitmap data: reserved, offset, header length.
2613
        $data = substr($data, 12);
2614
2615
        // Read and remove the bitmap width and height. Verify the sizes.
2616
        $width_and_height = unpack('V2', substr($data, 0, 8));
2617
        $width = $width_and_height[1];
2618
        $height = $width_and_height[2];
2619
        $data = substr($data, 8);
2620
        if ($width > 0xFFFF) {
2621
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: largest image width supported is 65k.\n");
2622
        }
2623
        if ($height > 0xFFFF) {
2624
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: largest image height supported is 65k.\n");
2625
        }
2626
2627
        // Read and remove the bitmap planes and bpp data. Verify them.
2628
        $planes_and_bitcount = unpack('v2', substr($data, 0, 4));
2629
        $data = substr($data, 4);
2630
        if ($planes_and_bitcount[2] != 24) { // Bitcount
2631
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap isn't a 24bit true color bitmap.\n");
2632
        }
2633
        if ($planes_and_bitcount[1] != 1) {
2634
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: only 1 plane supported in bitmap image.\n");
2635
        }
2636
2637
        // Read and remove the bitmap compression. Verify compression.
2638
        $compression = unpack('Vcomp', substr($data, 0, 4));
2639
        $data = substr($data, 4);
2640
2641
        if ($compression['comp'] != 0) {
2642
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: compression not supported in bitmap image.\n");
2643
        }
2644
2645
        // Remove bitmap data: data size, hres, vres, colours, imp. colours.
2646
        $data = substr($data, 20);
2647
2648
        // Add the BITMAPCOREHEADER data
2649
        $header = pack('Vvvvv', 0x000c, $width, $height, 0x01, 0x18);
2650
        $data = $header . $data;
2651
2652
        return [$width, $height, $size, $data];
2653
    }
2654
2655
    /**
2656
     * Store the window zoom factor. This should be a reduced fraction but for
2657
     * simplicity we will store all fractions with a numerator of 100.
2658
     */
2659 38 View Code Duplication
    private function writeZoom()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2660
    {
2661
        // If scale is 100 we don't need to write a record
2662 38
        if ($this->phpSheet->getSheetView()->getZoomScale() == 100) {
2663 38
            return;
2664
        }
2665
2666
        $record = 0x00A0; // Record identifier
2667
        $length = 0x0004; // Bytes to follow
2668
2669
        $header = pack('vv', $record, $length);
2670
        $data = pack('vv', $this->phpSheet->getSheetView()->getZoomScale(), 100);
2671
        $this->append($header . $data);
2672
    }
2673
2674
    /**
2675
     * Get Escher object.
2676
     *
2677
     * @return \PhpOffice\PhpSpreadsheet\Shared\Escher
2678
     */
2679
    public function getEscher()
2680
    {
2681
        return $this->escher;
2682
    }
2683
2684
    /**
2685
     * Set Escher object.
2686
     *
2687
     * @param \PhpOffice\PhpSpreadsheet\Shared\Escher $pValue
2688
     */
2689 10
    public function setEscher(\PhpOffice\PhpSpreadsheet\Shared\Escher $pValue = null)
2690
    {
2691 10
        $this->escher = $pValue;
2692 10
    }
2693
2694
    /**
2695
     * Write MSODRAWING record.
2696
     */
2697 38
    private function writeMsoDrawing()
2698
    {
2699
        // write the Escher stream if necessary
2700 38
        if (isset($this->escher)) {
2701 10
            $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls\Escher($this->escher);
2702 10
            $data = $writer->close();
2703 10
            $spOffsets = $writer->getSpOffsets();
2704 10
            $spTypes = $writer->getSpTypes();
2705
            // write the neccesary MSODRAWING, OBJ records
2706
2707
            // split the Escher stream
2708 10
            $spOffsets[0] = 0;
2709 10
            $nm = count($spOffsets) - 1; // number of shapes excluding first shape
2710 10
            for ($i = 1; $i <= $nm; ++$i) {
2711
                // MSODRAWING record
2712 10
                $record = 0x00EC; // Record identifier
2713
2714
                // chunk of Escher stream for one shape
2715 10
                $dataChunk = substr($data, $spOffsets[$i - 1], $spOffsets[$i] - $spOffsets[$i - 1]);
2716
2717 10
                $length = strlen($dataChunk);
2718 10
                $header = pack('vv', $record, $length);
2719
2720 10
                $this->append($header . $dataChunk);
2721
2722
                // OBJ record
2723 10
                $record = 0x005D; // record identifier
2724 10
                $objData = '';
2725
2726
                // ftCmo
2727 10
                if ($spTypes[$i] == 0x00C9) {
2728
                    // Add ftCmo (common object data) subobject
2729
                    $objData .=
2730 3
                        pack(
2731 3
                            'vvvvvVVV',
2732 3
                            0x0015, // 0x0015 = ftCmo
2733 3
                            0x0012, // length of ftCmo data
2734 3
                            0x0014, // object type, 0x0014 = filter
2735
                            $i, // object id number, Excel seems to use 1-based index, local for the sheet
2736 3
                            0x2101, // option flags, 0x2001 is what OpenOffice.org uses
2737 3
                            0, // reserved
2738 3
                            0, // reserved
2739 3
                            0  // reserved
2740
                        );
2741
2742
                    // Add ftSbs Scroll bar subobject
2743 3
                    $objData .= pack('vv', 0x00C, 0x0014);
2744 3
                    $objData .= pack('H*', '0000000000000000640001000A00000010000100');
2745
                    // Add ftLbsData (List box data) subobject
2746 3
                    $objData .= pack('vv', 0x0013, 0x1FEE);
2747 3
                    $objData .= pack('H*', '00000000010001030000020008005700');
2748
                } else {
2749
                    // Add ftCmo (common object data) subobject
2750
                    $objData .=
2751 7
                        pack(
2752 7
                            'vvvvvVVV',
2753 7
                            0x0015, // 0x0015 = ftCmo
2754 7
                            0x0012, // length of ftCmo data
2755 7
                            0x0008, // object type, 0x0008 = picture
2756
                            $i, // object id number, Excel seems to use 1-based index, local for the sheet
2757 7
                            0x6011, // option flags, 0x6011 is what OpenOffice.org uses
2758 7
                            0, // reserved
2759 7
                            0, // reserved
2760 7
                            0  // reserved
2761
                        );
2762
                }
2763
2764
                // ftEnd
2765
                $objData .=
2766 10
                    pack(
2767 10
                        'vv',
2768 10
                        0x0000, // 0x0000 = ftEnd
2769 10
                        0x0000  // length of ftEnd data
2770
                    );
2771
2772 10
                $length = strlen($objData);
2773 10
                $header = pack('vv', $record, $length);
2774 10
                $this->append($header . $objData);
2775
            }
2776
        }
2777 38
    }
2778
2779
    /**
2780
     * Store the DATAVALIDATIONS and DATAVALIDATION records.
2781
     */
2782 38
    private function writeDataValidity()
2783
    {
2784
        // Datavalidation collection
2785 38
        $dataValidationCollection = $this->phpSheet->getDataValidationCollection();
2786
2787
        // Write data validations?
2788 38
        if (!empty($dataValidationCollection)) {
2789
            // DATAVALIDATIONS record
2790 2
            $record = 0x01B2; // Record identifier
2791 2
            $length = 0x0012; // Bytes to follow
2792
2793 2
            $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records
2794 2
            $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position
2795 2
            $verPos = 0x00000000; // Vertical position of prompt box, if fixed position
2796 2
            $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible
2797
2798 2
            $header = pack('vv', $record, $length);
2799 2
            $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, count($dataValidationCollection));
2800 2
            $this->append($header . $data);
2801
2802
            // DATAVALIDATION records
2803 2
            $record = 0x01BE; // Record identifier
2804
2805 2
            foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) {
2806
                // initialize record data
2807 2
                $data = '';
0 ignored issues
show
Unused Code introduced by
$data 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...
2808
2809
                // options
2810 2
                $options = 0x00000000;
2811
2812
                // data type
2813 2
                $type = $dataValidation->getType();
2814 View Code Duplication
                switch ($type) {
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...
2815 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_NONE:
2816
                        $type = 0x00;
2817
                        break;
2818 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_WHOLE:
2819 1
                        $type = 0x01;
2820 1
                        break;
2821 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_DECIMAL:
2822
                        $type = 0x02;
2823
                        break;
2824 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST:
2825 2
                        $type = 0x03;
2826 2
                        break;
2827
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_DATE:
2828
                        $type = 0x04;
2829
                        break;
2830
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_TIME:
2831
                        $type = 0x05;
2832
                        break;
2833
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_TEXTLENGTH:
2834
                        $type = 0x06;
2835
                        break;
2836
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_CUSTOM:
2837
                        $type = 0x07;
2838
                        break;
2839
                }
2840
2841 2
                $options |= $type << 0;
2842
2843
                // error style
2844 2
                $errorStyle = $dataValidation->getErrorStyle();
2845 View Code Duplication
                switch ($errorStyle) {
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...
2846 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_STOP:
2847 1
                        $errorStyle = 0x00;
2848 1
                        break;
2849 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_WARNING:
2850
                        $errorStyle = 0x01;
2851
                        break;
2852 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION:
2853 2
                        $errorStyle = 0x02;
2854 2
                        break;
2855
                }
2856
2857 2
                $options |= $errorStyle << 4;
2858
2859
                // explicit formula?
2860 2
                if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) {
2861 1
                    $options |= 0x01 << 7;
2862
                }
2863
2864
                // empty cells allowed
2865 2
                $options |= $dataValidation->getAllowBlank() << 8;
2866
2867
                // show drop down
2868 2
                $options |= (!$dataValidation->getShowDropDown()) << 9;
2869
2870
                // show input message
2871 2
                $options |= $dataValidation->getShowInputMessage() << 18;
2872
2873
                // show error message
2874 2
                $options |= $dataValidation->getShowErrorMessage() << 19;
2875
2876
                // condition operator
2877 2
                $operator = $dataValidation->getOperator();
2878 View Code Duplication
                switch ($operator) {
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...
2879 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_BETWEEN:
2880 2
                        $operator = 0x00;
2881 2
                        break;
2882
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_NOTBETWEEN:
2883
                        $operator = 0x01;
2884
                        break;
2885
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_EQUAL:
2886
                        $operator = 0x02;
2887
                        break;
2888
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_NOTEQUAL:
2889
                        $operator = 0x03;
2890
                        break;
2891
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_GREATERTHAN:
2892
                        $operator = 0x04;
2893
                        break;
2894
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_LESSTHAN:
2895
                        $operator = 0x05;
2896
                        break;
2897
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_GREATERTHANOREQUAL:
2898
                        $operator = 0x06;
2899
                        break;
2900
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_LESSTHANOREQUAL:
2901
                        $operator = 0x07;
2902
                        break;
2903
                }
2904
2905 2
                $options |= $operator << 20;
2906
2907 2
                $data = pack('V', $options);
2908
2909
                // prompt title
2910 2
                $promptTitle = $dataValidation->getPromptTitle() !== '' ?
2911 2
                    $dataValidation->getPromptTitle() : chr(0);
2912 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($promptTitle);
2913
2914
                // error title
2915 2
                $errorTitle = $dataValidation->getErrorTitle() !== '' ?
2916 2
                    $dataValidation->getErrorTitle() : chr(0);
2917 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($errorTitle);
2918
2919
                // prompt text
2920 2
                $prompt = $dataValidation->getPrompt() !== '' ?
2921 2
                    $dataValidation->getPrompt() : chr(0);
2922 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($prompt);
2923
2924
                // error text
2925 2
                $error = $dataValidation->getError() !== '' ?
2926 2
                    $dataValidation->getError() : chr(0);
2927 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($error);
2928
2929
                // formula 1
2930
                try {
2931 2
                    $formula1 = $dataValidation->getFormula1();
2932 2
                    if ($type == 0x03) { // list type
2933 2
                        $formula1 = str_replace(',', chr(0), $formula1);
2934
                    }
2935 2
                    $this->parser->parse($formula1);
2936 1
                    $formula1 = $this->parser->toReversePolish();
2937 1
                    $sz1 = strlen($formula1);
2938 2
                } catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
2939 2
                    $sz1 = 0;
2940 2
                    $formula1 = '';
2941
                }
2942 2
                $data .= pack('vv', $sz1, 0x0000);
2943 2
                $data .= $formula1;
2944
2945
                // formula 2
2946
                try {
2947 2
                    $formula2 = $dataValidation->getFormula2();
2948 2
                    if ($formula2 === '') {
2949 2
                        throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('No formula2');
2950
                    }
2951 1
                    $this->parser->parse($formula2);
2952
                    $formula2 = $this->parser->toReversePolish();
2953
                    $sz2 = strlen($formula2);
2954 2
                } catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
2955 2
                    $sz2 = 0;
2956 2
                    $formula2 = '';
2957
                }
2958 2
                $data .= pack('vv', $sz2, 0x0000);
2959 2
                $data .= $formula2;
2960
2961
                // cell range address list
2962 2
                $data .= pack('v', 0x0001);
2963 2
                $data .= $this->writeBIFF8CellRangeAddressFixed($cellCoordinate);
2964
2965 2
                $length = strlen($data);
2966 2
                $header = pack('vv', $record, $length);
2967
2968 2
                $this->append($header . $data);
2969
            }
2970
        }
2971 38
    }
2972
2973
    /**
2974
     * Map Error code.
2975
     *
2976
     * @param string $errorCode
2977
     *
2978
     * @return int
2979
     */
2980 4
    private static function mapErrorCode($errorCode)
2981
    {
2982
        switch ($errorCode) {
2983 4
            case '#NULL!':
2984
                return 0x00;
2985 4
            case '#DIV/0!':
2986 3
                return 0x07;
2987 2
            case '#VALUE!':
2988 1
                return 0x0F;
2989 1
            case '#REF!':
2990
                return 0x17;
2991 1
            case '#NAME?':
2992
                return 0x1D;
2993 1
            case '#NUM!':
2994
                return 0x24;
2995 1
            case '#N/A':
2996 1
                return 0x2A;
2997
        }
2998
2999
        return 0;
3000
    }
3001
3002
    /**
3003
     * Write PLV Record.
3004
     */
3005 38
    private function writePageLayoutView()
3006
    {
3007 38
        $record = 0x088B; // Record identifier
3008 38
        $length = 0x0010; // Bytes to follow
3009
3010 38
        $rt = 0x088B; // 2
3011 38
        $grbitFrt = 0x0000; // 2
3012 38
        $reserved = 0x0000000000000000; // 8
0 ignored issues
show
Unused Code introduced by
$reserved 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...
3013 38
        $wScalvePLV = $this->phpSheet->getSheetView()->getZoomScale(); // 2
3014
3015
        // The options flags that comprise $grbit
3016 38
        if ($this->phpSheet->getSheetView()->getView() == \PhpOffice\PhpSpreadsheet\Worksheet\SheetView::SHEETVIEW_PAGE_LAYOUT) {
3017 1
            $fPageLayoutView = 1;
3018
        } else {
3019 37
            $fPageLayoutView = 0;
3020
        }
3021 38
        $fRulerVisible = 0;
3022 38
        $fWhitespaceHidden = 0;
3023
3024 38
        $grbit = $fPageLayoutView; // 2
3025 38
        $grbit |= $fRulerVisible << 1;
3026 38
        $grbit |= $fWhitespaceHidden << 3;
3027
3028 38
        $header = pack('vv', $record, $length);
3029 38
        $data = pack('vvVVvv', $rt, $grbitFrt, 0x00000000, 0x00000000, $wScalvePLV, $grbit);
3030 38
        $this->append($header . $data);
3031 38
    }
3032
3033
    /**
3034
     * Write CFRule Record.
3035
     *
3036
     * @param \PhpOffice\PhpSpreadsheet\Style\Conditional $conditional
3037
     */
3038 2
    private function writeCFRule(\PhpOffice\PhpSpreadsheet\Style\Conditional $conditional)
3039
    {
3040 2
        $record = 0x01B1; // Record identifier
3041
3042
        // $type : Type of the CF
3043
        // $operatorType : Comparison operator
3044 2
        if ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION) {
3045
            $type = 0x02;
3046
            $operatorType = 0x00;
3047 2
        } elseif ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
3048 2
            $type = 0x01;
3049
3050 2
            switch ($conditional->getOperatorType()) {
3051 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_NONE:
3052
                    $operatorType = 0x00;
3053
                    break;
3054 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_EQUAL:
3055
                    $operatorType = 0x03;
3056
                    break;
3057 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHAN:
3058
                    $operatorType = 0x05;
3059
                    break;
3060 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHANOREQUAL:
3061 2
                    $operatorType = 0x07;
3062 2
                    break;
3063 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN:
3064 2
                    $operatorType = 0x06;
3065 2
                    break;
3066 1
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHANOREQUAL:
3067
                    $operatorType = 0x08;
3068
                    break;
3069 1
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_NOTEQUAL:
3070
                    $operatorType = 0x04;
3071
                    break;
3072 1
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_BETWEEN:
3073 1
                    $operatorType = 0x01;
3074 1
                    break;
3075
                    // not OPERATOR_NOTBETWEEN 0x02
3076
            }
3077
        }
3078
3079
        // $szValue1 : size of the formula data for first value or formula
3080
        // $szValue2 : size of the formula data for second value or formula
3081 2
        $arrConditions = $conditional->getConditions();
3082 2
        $numConditions = count($arrConditions);
3083 2
        if ($numConditions == 1) {
3084 2
            $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
3085 2
            $szValue2 = 0x0000;
3086 2
            $operand1 = pack('Cv', 0x1E, $arrConditions[0]);
3087 2
            $operand2 = null;
3088 1
        } elseif ($numConditions == 2 && ($conditional->getOperatorType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_BETWEEN)) {
3089 1
            $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
3090 1
            $szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000);
3091 1
            $operand1 = pack('Cv', 0x1E, $arrConditions[0]);
3092 1
            $operand2 = pack('Cv', 0x1E, $arrConditions[1]);
3093
        } else {
3094
            $szValue1 = 0x0000;
3095
            $szValue2 = 0x0000;
3096
            $operand1 = null;
3097
            $operand2 = null;
3098
        }
3099
3100
        // $flags : Option flags
3101
        // Alignment
3102 2
        $bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null ? 1 : 0);
3103 2
        $bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null ? 1 : 0);
3104 2
        $bAlignWrapTx = ($conditional->getStyle()->getAlignment()->getWrapText() == false ? 1 : 0);
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...
3105 2
        $bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null ? 1 : 0);
3106 2
        $bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0 ? 1 : 0);
3107 2
        $bShrinkToFit = ($conditional->getStyle()->getAlignment()->getShrinkToFit() == false ? 1 : 0);
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...
3108 2
        if ($bAlignHz == 0 || $bAlignVt == 0 || $bAlignWrapTx == 0 || $bTxRotation == 0 || $bIndent == 0 || $bShrinkToFit == 0) {
3109
            $bFormatAlign = 1;
3110
        } else {
3111 2
            $bFormatAlign = 0;
3112
        }
3113
        // Protection
3114 2
        $bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null ? 1 : 0);
3115 2
        $bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null ? 1 : 0);
3116 2
        if ($bProtLocked == 0 || $bProtHidden == 0) {
3117
            $bFormatProt = 1;
3118
        } else {
3119 2
            $bFormatProt = 0;
3120
        }
3121
        // Border
3122 2
        $bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3123 2
                        && $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3124 2
        $bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3125 2
                        && $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3126 2
        $bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3127 2
                        && $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3128 2
        $bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3129 2
                        && $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3130 2
        if ($bBorderLeft == 0 || $bBorderRight == 0 || $bBorderTop == 0 || $bBorderBottom == 0) {
3131
            $bFormatBorder = 1;
3132
        } else {
3133 2
            $bFormatBorder = 0;
3134
        }
3135
        // Pattern
3136 2
        $bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null ? 0 : 1);
3137 2
        $bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null ? 0 : 1);
3138 2
        $bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null ? 0 : 1);
3139 2
        if ($bFillStyle == 0 || $bFillColor == 0 || $bFillColorBg == 0) {
3140 2
            $bFormatFill = 1;
3141
        } else {
3142
            $bFormatFill = 0;
3143
        }
3144
        // Font
3145 2
        if ($conditional->getStyle()->getFont()->getName() != null
3146 2
            || $conditional->getStyle()->getFont()->getSize() != null
3147 2
            || $conditional->getStyle()->getFont()->getBold() != null
3148 2
            || $conditional->getStyle()->getFont()->getItalic() != null
3149 1
            || $conditional->getStyle()->getFont()->getSuperScript() != null
3150 1
            || $conditional->getStyle()->getFont()->getSubScript() != null
3151 1
            || $conditional->getStyle()->getFont()->getUnderline() != null
3152 1
            || $conditional->getStyle()->getFont()->getStrikethrough() != null
3153 1
            || $conditional->getStyle()->getFont()->getColor()->getARGB() != null) {
3154 2
            $bFormatFont = 1;
3155
        } else {
3156
            $bFormatFont = 0;
3157
        }
3158
        // Alignment
3159 2
        $flags = 0;
3160 2
        $flags |= (1 == $bAlignHz ? 0x00000001 : 0);
3161 2
        $flags |= (1 == $bAlignVt ? 0x00000002 : 0);
3162 2
        $flags |= (1 == $bAlignWrapTx ? 0x00000004 : 0);
3163 2
        $flags |= (1 == $bTxRotation ? 0x00000008 : 0);
3164
        // Justify last line flag
3165 2
        $flags |= (1 == 1 ? 0x00000010 : 0);
3166 2
        $flags |= (1 == $bIndent ? 0x00000020 : 0);
3167 2
        $flags |= (1 == $bShrinkToFit ? 0x00000040 : 0);
3168
        // Default
3169 2
        $flags |= (1 == 1 ? 0x00000080 : 0);
3170
        // Protection
3171 2
        $flags |= (1 == $bProtLocked ? 0x00000100 : 0);
3172 2
        $flags |= (1 == $bProtHidden ? 0x00000200 : 0);
3173
        // Border
3174 2
        $flags |= (1 == $bBorderLeft ? 0x00000400 : 0);
3175 2
        $flags |= (1 == $bBorderRight ? 0x00000800 : 0);
3176 2
        $flags |= (1 == $bBorderTop ? 0x00001000 : 0);
3177 2
        $flags |= (1 == $bBorderBottom ? 0x00002000 : 0);
3178 2
        $flags |= (1 == 1 ? 0x00004000 : 0); // Top left to Bottom right border
3179 2
        $flags |= (1 == 1 ? 0x00008000 : 0); // Bottom left to Top right border
3180
        // Pattern
3181 2
        $flags |= (1 == $bFillStyle ? 0x00010000 : 0);
3182 2
        $flags |= (1 == $bFillColor ? 0x00020000 : 0);
3183 2
        $flags |= (1 == $bFillColorBg ? 0x00040000 : 0);
3184 2
        $flags |= (1 == 1 ? 0x00380000 : 0);
3185
        // Font
3186 2
        $flags |= (1 == $bFormatFont ? 0x04000000 : 0);
3187
        // Alignment:
3188 2
        $flags |= (1 == $bFormatAlign ? 0x08000000 : 0);
3189
        // Border
3190 2
        $flags |= (1 == $bFormatBorder ? 0x10000000 : 0);
3191
        // Pattern
3192 2
        $flags |= (1 == $bFormatFill ? 0x20000000 : 0);
3193
        // Protection
3194 2
        $flags |= (1 == $bFormatProt ? 0x40000000 : 0);
3195
        // Text direction
3196 2
        $flags |= (1 == 0 ? 0x80000000 : 0);
3197
3198
        // Data Blocks
3199 2
        if ($bFormatFont == 1) {
3200
            // Font Name
3201 2
            if ($conditional->getStyle()->getFont()->getName() == null) {
3202 2
                $dataBlockFont = pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
3203 2
                $dataBlockFont .= pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
3204
            } else {
3205
                $dataBlockFont = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName());
3206
            }
3207
            // Font Size
3208 2
            if ($conditional->getStyle()->getFont()->getSize() == null) {
3209 2
                $dataBlockFont .= pack('V', 20 * 11);
3210
            } else {
3211
                $dataBlockFont .= pack('V', 20 * $conditional->getStyle()->getFont()->getSize());
3212
            }
3213
            // Font Options
3214 2
            $dataBlockFont .= pack('V', 0);
3215
            // Font weight
3216 2
            if ($conditional->getStyle()->getFont()->getBold() == 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...
3217 1
                $dataBlockFont .= pack('v', 0x02BC);
3218
            } else {
3219 2
                $dataBlockFont .= pack('v', 0x0190);
3220
            }
3221
            // Escapement type
3222 2
            if ($conditional->getStyle()->getFont()->getSubScript() == 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...
3223
                $dataBlockFont .= pack('v', 0x02);
3224
                $fontEscapement = 0;
3225 2
            } elseif ($conditional->getStyle()->getFont()->getSuperScript() == 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...
3226
                $dataBlockFont .= pack('v', 0x01);
3227
                $fontEscapement = 0;
3228
            } else {
3229 2
                $dataBlockFont .= pack('v', 0x00);
3230 2
                $fontEscapement = 1;
3231
            }
3232
            // Underline type
3233 2
            switch ($conditional->getStyle()->getFont()->getUnderline()) {
3234 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_NONE:
3235
                    $dataBlockFont .= pack('C', 0x00);
3236
                    $fontUnderline = 0;
3237
                    break;
3238 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLE:
3239
                    $dataBlockFont .= pack('C', 0x02);
3240
                    $fontUnderline = 0;
3241
                    break;
3242 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLEACCOUNTING:
3243
                    $dataBlockFont .= pack('C', 0x22);
3244
                    $fontUnderline = 0;
3245
                    break;
3246 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE:
3247
                    $dataBlockFont .= pack('C', 0x01);
3248
                    $fontUnderline = 0;
3249
                    break;
3250 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLEACCOUNTING:
3251
                    $dataBlockFont .= pack('C', 0x21);
3252
                    $fontUnderline = 0;
3253
                    break;
3254
                default:
3255 2
                    $dataBlockFont .= pack('C', 0x00);
3256 2
                    $fontUnderline = 1;
3257 2
                    break;
3258
            }
3259
            // Not used (3)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
3260 2
            $dataBlockFont .= pack('vC', 0x0000, 0x00);
3261
            // Font color index
3262 2 View Code Duplication
            switch ($conditional->getStyle()->getFont()->getColor()->getRGB()) {
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...
3263 2
                case '000000':
3264
                    $colorIdx = 0x08;
3265
                    break;
3266 2
                case 'FFFFFF':
3267
                    $colorIdx = 0x09;
3268
                    break;
3269 2
                case 'FF0000':
3270 2
                    $colorIdx = 0x0A;
3271 2
                    break;
3272 2
                case '00FF00':
3273 2
                    $colorIdx = 0x0B;
3274 2
                    break;
3275 1
                case '0000FF':
3276
                    $colorIdx = 0x0C;
3277
                    break;
3278 1
                case 'FFFF00':
3279 1
                    $colorIdx = 0x0D;
3280 1
                    break;
3281
                case 'FF00FF':
3282
                    $colorIdx = 0x0E;
3283
                    break;
3284
                case '00FFFF':
3285
                    $colorIdx = 0x0F;
3286
                    break;
3287
                case '800000':
3288
                    $colorIdx = 0x10;
3289
                    break;
3290
                case '008000':
3291
                    $colorIdx = 0x11;
3292
                    break;
3293
                case '000080':
3294
                    $colorIdx = 0x12;
3295
                    break;
3296
                case '808000':
3297
                    $colorIdx = 0x13;
3298
                    break;
3299
                case '800080':
3300
                    $colorIdx = 0x14;
3301
                    break;
3302
                case '008080':
3303
                    $colorIdx = 0x15;
3304
                    break;
3305
                case 'C0C0C0':
3306
                    $colorIdx = 0x16;
3307
                    break;
3308
                case '808080':
3309
                    $colorIdx = 0x17;
3310
                    break;
3311
                case '9999FF':
3312
                    $colorIdx = 0x18;
3313
                    break;
3314
                case '993366':
3315
                    $colorIdx = 0x19;
3316
                    break;
3317
                case 'FFFFCC':
3318
                    $colorIdx = 0x1A;
3319
                    break;
3320
                case 'CCFFFF':
3321
                    $colorIdx = 0x1B;
3322
                    break;
3323
                case '660066':
3324
                    $colorIdx = 0x1C;
3325
                    break;
3326
                case 'FF8080':
3327
                    $colorIdx = 0x1D;
3328
                    break;
3329
                case '0066CC':
3330
                    $colorIdx = 0x1E;
3331
                    break;
3332
                case 'CCCCFF':
3333
                    $colorIdx = 0x1F;
3334
                    break;
3335
                case '000080':
3336
                    $colorIdx = 0x20;
3337
                    break;
3338
                case 'FF00FF':
3339
                    $colorIdx = 0x21;
3340
                    break;
3341
                case 'FFFF00':
3342
                    $colorIdx = 0x22;
3343
                    break;
3344
                case '00FFFF':
3345
                    $colorIdx = 0x23;
3346
                    break;
3347
                case '800080':
3348
                    $colorIdx = 0x24;
3349
                    break;
3350
                case '800000':
3351
                    $colorIdx = 0x25;
3352
                    break;
3353
                case '008080':
3354
                    $colorIdx = 0x26;
3355
                    break;
3356
                case '0000FF':
3357
                    $colorIdx = 0x27;
3358
                    break;
3359
                case '00CCFF':
3360
                    $colorIdx = 0x28;
3361
                    break;
3362
                case 'CCFFFF':
3363
                    $colorIdx = 0x29;
3364
                    break;
3365
                case 'CCFFCC':
3366
                    $colorIdx = 0x2A;
3367
                    break;
3368
                case 'FFFF99':
3369
                    $colorIdx = 0x2B;
3370
                    break;
3371
                case '99CCFF':
3372
                    $colorIdx = 0x2C;
3373
                    break;
3374
                case 'FF99CC':
3375
                    $colorIdx = 0x2D;
3376
                    break;
3377
                case 'CC99FF':
3378
                    $colorIdx = 0x2E;
3379
                    break;
3380
                case 'FFCC99':
3381
                    $colorIdx = 0x2F;
3382
                    break;
3383
                case '3366FF':
3384
                    $colorIdx = 0x30;
3385
                    break;
3386
                case '33CCCC':
3387
                    $colorIdx = 0x31;
3388
                    break;
3389
                case '99CC00':
3390
                    $colorIdx = 0x32;
3391
                    break;
3392
                case 'FFCC00':
3393
                    $colorIdx = 0x33;
3394
                    break;
3395
                case 'FF9900':
3396
                    $colorIdx = 0x34;
3397
                    break;
3398
                case 'FF6600':
3399
                    $colorIdx = 0x35;
3400
                    break;
3401
                case '666699':
3402
                    $colorIdx = 0x36;
3403
                    break;
3404
                case '969696':
3405
                    $colorIdx = 0x37;
3406
                    break;
3407
                case '003366':
3408
                    $colorIdx = 0x38;
3409
                    break;
3410
                case '339966':
3411
                    $colorIdx = 0x39;
3412
                    break;
3413
                case '003300':
3414
                    $colorIdx = 0x3A;
3415
                    break;
3416
                case '333300':
3417
                    $colorIdx = 0x3B;
3418
                    break;
3419
                case '993300':
3420
                    $colorIdx = 0x3C;
3421
                    break;
3422
                case '993366':
3423
                    $colorIdx = 0x3D;
3424
                    break;
3425
                case '333399':
3426
                    $colorIdx = 0x3E;
3427
                    break;
3428
                case '333333':
3429
                    $colorIdx = 0x3F;
3430
                    break;
3431
                default:
3432
                    $colorIdx = 0x00;
3433
                    break;
3434
            }
3435 2
            $dataBlockFont .= pack('V', $colorIdx);
3436
            // Not used (4)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
3437 2
            $dataBlockFont .= pack('V', 0x00000000);
3438
            // Options flags for modified font attributes
3439 2
            $optionsFlags = 0;
3440 2
            $optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null ? 1 : 0);
3441 2
            $optionsFlags |= (1 == $optionsFlagsBold ? 0x00000002 : 0);
3442 2
            $optionsFlags |= (1 == 1 ? 0x00000008 : 0);
3443 2
            $optionsFlags |= (1 == 1 ? 0x00000010 : 0);
3444 2
            $optionsFlags |= (1 == 0 ? 0x00000020 : 0);
3445 2
            $optionsFlags |= (1 == 1 ? 0x00000080 : 0);
3446 2
            $dataBlockFont .= pack('V', $optionsFlags);
3447
            // Escapement type
3448 2
            $dataBlockFont .= pack('V', $fontEscapement);
3449
            // Underline type
3450 2
            $dataBlockFont .= pack('V', $fontUnderline);
3451
            // Always
3452 2
            $dataBlockFont .= pack('V', 0x00000000);
3453
            // Always
3454 2
            $dataBlockFont .= pack('V', 0x00000000);
3455
            // Not used (8)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
3456 2
            $dataBlockFont .= pack('VV', 0x00000000, 0x00000000);
3457
            // Always
3458 2
            $dataBlockFont .= pack('v', 0x0001);
3459
        }
3460 2
        if ($bFormatAlign == 1) {
3461
            $blockAlign = 0;
3462
            // Alignment and text break
3463
            switch ($conditional->getStyle()->getAlignment()->getHorizontal()) {
3464
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_GENERAL:
3465
                    $blockAlign = 0;
3466
                    break;
3467
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT:
3468
                    $blockAlign = 1;
3469
                    break;
3470
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT:
3471
                    $blockAlign = 3;
3472
                    break;
3473
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER:
3474
                    $blockAlign = 2;
3475
                    break;
3476
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER_CONTINUOUS:
3477
                    $blockAlign = 6;
3478
                    break;
3479
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_JUSTIFY:
3480
                    $blockAlign = 5;
3481
                    break;
3482
            }
3483
            if ($conditional->getStyle()->getAlignment()->getWrapText() == 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...
3484
                $blockAlign |= 1 << 3;
3485
            } else {
3486
                $blockAlign |= 0 << 3;
3487
            }
3488
            switch ($conditional->getStyle()->getAlignment()->getVertical()) {
3489
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_BOTTOM:
3490
                    $blockAlign = 2 << 4;
3491
                    break;
3492
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP:
3493
                    $blockAlign = 0 << 4;
3494
                    break;
3495
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER:
3496
                    $blockAlign = 1 << 4;
3497
                    break;
3498
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_JUSTIFY:
3499
                    $blockAlign = 3 << 4;
3500
                    break;
3501
            }
3502
            $blockAlign |= 0 << 7;
3503
3504
            // Text rotation angle
3505
            $blockRotation = $conditional->getStyle()->getAlignment()->getTextRotation();
3506
3507
            // Indentation
3508
            $blockIndent = $conditional->getStyle()->getAlignment()->getIndent();
3509
            if ($conditional->getStyle()->getAlignment()->getShrinkToFit() == 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...
3510
                $blockIndent |= 1 << 4;
3511
            } else {
3512
                $blockIndent |= 0 << 4;
3513
            }
3514
            $blockIndent |= 0 << 6;
3515
3516
            // Relative indentation
3517
            $blockIndentRelative = 255;
3518
3519
            $dataBlockAlign = pack('CCvvv', $blockAlign, $blockRotation, $blockIndent, $blockIndentRelative, 0x0000);
3520
        }
3521 2
        if ($bFormatBorder == 1) {
3522
            $blockLineStyle = 0;
3523
            switch ($conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()) {
3524
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3525
                    $blockLineStyle |= 0x00;
3526
                    break;
3527
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3528
                    $blockLineStyle |= 0x01;
3529
                    break;
3530
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3531
                    $blockLineStyle |= 0x02;
3532
                    break;
3533
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3534
                    $blockLineStyle |= 0x03;
3535
                    break;
3536
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3537
                    $blockLineStyle |= 0x04;
3538
                    break;
3539
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3540
                    $blockLineStyle |= 0x05;
3541
                    break;
3542
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3543
                    $blockLineStyle |= 0x06;
3544
                    break;
3545
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3546
                    $blockLineStyle |= 0x07;
3547
                    break;
3548
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3549
                    $blockLineStyle |= 0x08;
3550
                    break;
3551
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3552
                    $blockLineStyle |= 0x09;
3553
                    break;
3554
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3555
                    $blockLineStyle |= 0x0A;
3556
                    break;
3557
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3558
                    $blockLineStyle |= 0x0B;
3559
                    break;
3560
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3561
                    $blockLineStyle |= 0x0C;
3562
                    break;
3563
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3564
                    $blockLineStyle |= 0x0D;
3565
                    break;
3566
            }
3567 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getRight()->getBorderStyle()) {
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...
3568
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3569
                    $blockLineStyle |= 0x00 << 4;
3570
                    break;
3571
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3572
                    $blockLineStyle |= 0x01 << 4;
3573
                    break;
3574
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3575
                    $blockLineStyle |= 0x02 << 4;
3576
                    break;
3577
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3578
                    $blockLineStyle |= 0x03 << 4;
3579
                    break;
3580
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3581
                    $blockLineStyle |= 0x04 << 4;
3582
                    break;
3583
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3584
                    $blockLineStyle |= 0x05 << 4;
3585
                    break;
3586
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3587
                    $blockLineStyle |= 0x06 << 4;
3588
                    break;
3589
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3590
                    $blockLineStyle |= 0x07 << 4;
3591
                    break;
3592
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3593
                    $blockLineStyle |= 0x08 << 4;
3594
                    break;
3595
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3596
                    $blockLineStyle |= 0x09 << 4;
3597
                    break;
3598
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3599
                    $blockLineStyle |= 0x0A << 4;
3600
                    break;
3601
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3602
                    $blockLineStyle |= 0x0B << 4;
3603
                    break;
3604
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3605
                    $blockLineStyle |= 0x0C << 4;
3606
                    break;
3607
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3608
                    $blockLineStyle |= 0x0D << 4;
3609
                    break;
3610
            }
3611 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getTop()->getBorderStyle()) {
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...
3612
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3613
                    $blockLineStyle |= 0x00 << 8;
3614
                    break;
3615
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3616
                    $blockLineStyle |= 0x01 << 8;
3617
                    break;
3618
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3619
                    $blockLineStyle |= 0x02 << 8;
3620
                    break;
3621
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3622
                    $blockLineStyle |= 0x03 << 8;
3623
                    break;
3624
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3625
                    $blockLineStyle |= 0x04 << 8;
3626
                    break;
3627
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3628
                    $blockLineStyle |= 0x05 << 8;
3629
                    break;
3630
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3631
                    $blockLineStyle |= 0x06 << 8;
3632
                    break;
3633
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3634
                    $blockLineStyle |= 0x07 << 8;
3635
                    break;
3636
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3637
                    $blockLineStyle |= 0x08 << 8;
3638
                    break;
3639
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3640
                    $blockLineStyle |= 0x09 << 8;
3641
                    break;
3642
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3643
                    $blockLineStyle |= 0x0A << 8;
3644
                    break;
3645
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3646
                    $blockLineStyle |= 0x0B << 8;
3647
                    break;
3648
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3649
                    $blockLineStyle |= 0x0C << 8;
3650
                    break;
3651
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3652
                    $blockLineStyle |= 0x0D << 8;
3653
                    break;
3654
            }
3655 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getBottom()->getBorderStyle()) {
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...
3656
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3657
                    $blockLineStyle |= 0x00 << 12;
3658
                    break;
3659
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3660
                    $blockLineStyle |= 0x01 << 12;
3661
                    break;
3662
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3663
                    $blockLineStyle |= 0x02 << 12;
3664
                    break;
3665
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3666
                    $blockLineStyle |= 0x03 << 12;
3667
                    break;
3668
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3669
                    $blockLineStyle |= 0x04 << 12;
3670
                    break;
3671
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3672
                    $blockLineStyle |= 0x05 << 12;
3673
                    break;
3674
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3675
                    $blockLineStyle |= 0x06 << 12;
3676
                    break;
3677
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3678
                    $blockLineStyle |= 0x07 << 12;
3679
                    break;
3680
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3681
                    $blockLineStyle |= 0x08 << 12;
3682
                    break;
3683
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3684
                    $blockLineStyle |= 0x09 << 12;
3685
                    break;
3686
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3687
                    $blockLineStyle |= 0x0A << 12;
3688
                    break;
3689
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3690
                    $blockLineStyle |= 0x0B << 12;
3691
                    break;
3692
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3693
                    $blockLineStyle |= 0x0C << 12;
3694
                    break;
3695
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3696
                    $blockLineStyle |= 0x0D << 12;
3697
                    break;
3698
            }
3699
            //@todo writeCFRule() => $blockLineStyle => Index Color for left line
3700
            //@todo writeCFRule() => $blockLineStyle => Index Color for right line
3701
            //@todo writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off
3702
            //@todo writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off
3703
            $blockColor = 0;
3704
            //@todo writeCFRule() => $blockColor => Index Color for top line
3705
            //@todo writeCFRule() => $blockColor => Index Color for bottom line
3706
            //@todo writeCFRule() => $blockColor => Index Color for diagonal line
3707 View Code Duplication
            switch ($conditional->getStyle()->getBorders()->getDiagonal()->getBorderStyle()) {
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...
3708
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3709
                    $blockColor |= 0x00 << 21;
3710
                    break;
3711
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3712
                    $blockColor |= 0x01 << 21;
3713
                    break;
3714
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3715
                    $blockColor |= 0x02 << 21;
3716
                    break;
3717
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3718
                    $blockColor |= 0x03 << 21;
3719
                    break;
3720
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3721
                    $blockColor |= 0x04 << 21;
3722
                    break;
3723
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3724
                    $blockColor |= 0x05 << 21;
3725
                    break;
3726
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3727
                    $blockColor |= 0x06 << 21;
3728
                    break;
3729
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3730
                    $blockColor |= 0x07 << 21;
3731
                    break;
3732
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3733
                    $blockColor |= 0x08 << 21;
3734
                    break;
3735
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3736
                    $blockColor |= 0x09 << 21;
3737
                    break;
3738
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3739
                    $blockColor |= 0x0A << 21;
3740
                    break;
3741
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3742
                    $blockColor |= 0x0B << 21;
3743
                    break;
3744
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3745
                    $blockColor |= 0x0C << 21;
3746
                    break;
3747
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3748
                    $blockColor |= 0x0D << 21;
3749
                    break;
3750
            }
3751
            $dataBlockBorder = pack('vv', $blockLineStyle, $blockColor);
3752
        }
3753 2
        if ($bFormatFill == 1) {
3754
            // Fill Patern Style
3755 2
            $blockFillPatternStyle = 0;
0 ignored issues
show
Unused Code introduced by
$blockFillPatternStyle 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...
3756 2
            switch ($conditional->getStyle()->getFill()->getFillType()) {
3757 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_NONE:
3758
                    $blockFillPatternStyle = 0x00;
3759
                    break;
3760 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID:
3761
                    $blockFillPatternStyle = 0x01;
3762
                    break;
3763 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_MEDIUMGRAY:
3764
                    $blockFillPatternStyle = 0x02;
3765
                    break;
3766 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKGRAY:
3767
                    $blockFillPatternStyle = 0x03;
3768
                    break;
3769 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRAY:
3770
                    $blockFillPatternStyle = 0x04;
3771
                    break;
3772 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKHORIZONTAL:
3773
                    $blockFillPatternStyle = 0x05;
3774
                    break;
3775 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKVERTICAL:
3776
                    $blockFillPatternStyle = 0x06;
3777
                    break;
3778 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKDOWN:
3779
                    $blockFillPatternStyle = 0x07;
3780
                    break;
3781 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKUP:
3782
                    $blockFillPatternStyle = 0x08;
3783
                    break;
3784 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKGRID:
3785
                    $blockFillPatternStyle = 0x09;
3786
                    break;
3787 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKTRELLIS:
3788
                    $blockFillPatternStyle = 0x0A;
3789
                    break;
3790 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTHORIZONTAL:
3791
                    $blockFillPatternStyle = 0x0B;
3792
                    break;
3793 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTVERTICAL:
3794
                    $blockFillPatternStyle = 0x0C;
3795
                    break;
3796 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTDOWN:
3797
                    $blockFillPatternStyle = 0x0D;
3798
                    break;
3799 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTUP:
3800
                    $blockFillPatternStyle = 0x0E;
3801
                    break;
3802 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRID:
3803
                    $blockFillPatternStyle = 0x0F;
3804
                    break;
3805 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTTRELLIS:
3806
                    $blockFillPatternStyle = 0x10;
3807
                    break;
3808 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_GRAY125:
3809
                    $blockFillPatternStyle = 0x11;
3810
                    break;
3811 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_GRAY0625:
3812
                    $blockFillPatternStyle = 0x12;
3813
                    break;
3814 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_GRADIENT_LINEAR:
3815
                    $blockFillPatternStyle = 0x00;
3816
                    break; // does not exist in BIFF8
3817 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_GRADIENT_PATH:
3818
                    $blockFillPatternStyle = 0x00;
3819
                    break; // does not exist in BIFF8
3820
                default:
3821 2
                    $blockFillPatternStyle = 0x00;
3822 2
                    break;
3823
            }
3824
            // Color
3825 2 View Code Duplication
            switch ($conditional->getStyle()->getFill()->getStartColor()->getRGB()) {
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...
3826 2
                case '000000':
3827
                    $colorIdxBg = 0x08;
3828
                    break;
3829 2
                case 'FFFFFF':
3830
                    $colorIdxBg = 0x09;
3831
                    break;
3832 2
                case 'FF0000':
3833
                    $colorIdxBg = 0x0A;
3834
                    break;
3835 2
                case '00FF00':
3836
                    $colorIdxBg = 0x0B;
3837
                    break;
3838 2
                case '0000FF':
3839
                    $colorIdxBg = 0x0C;
3840
                    break;
3841 2
                case 'FFFF00':
3842
                    $colorIdxBg = 0x0D;
3843
                    break;
3844 2
                case 'FF00FF':
3845
                    $colorIdxBg = 0x0E;
3846
                    break;
3847 2
                case '00FFFF':
3848
                    $colorIdxBg = 0x0F;
3849
                    break;
3850 2
                case '800000':
3851
                    $colorIdxBg = 0x10;
3852
                    break;
3853 2
                case '008000':
3854
                    $colorIdxBg = 0x11;
3855
                    break;
3856 2
                case '000080':
3857
                    $colorIdxBg = 0x12;
3858
                    break;
3859 2
                case '808000':
3860
                    $colorIdxBg = 0x13;
3861
                    break;
3862 2
                case '800080':
3863
                    $colorIdxBg = 0x14;
3864
                    break;
3865 2
                case '008080':
3866
                    $colorIdxBg = 0x15;
3867
                    break;
3868 2
                case 'C0C0C0':
3869
                    $colorIdxBg = 0x16;
3870
                    break;
3871 2
                case '808080':
3872
                    $colorIdxBg = 0x17;
3873
                    break;
3874 2
                case '9999FF':
3875
                    $colorIdxBg = 0x18;
3876
                    break;
3877 2
                case '993366':
3878
                    $colorIdxBg = 0x19;
3879
                    break;
3880 2
                case 'FFFFCC':
3881
                    $colorIdxBg = 0x1A;
3882
                    break;
3883 2
                case 'CCFFFF':
3884
                    $colorIdxBg = 0x1B;
3885
                    break;
3886 2
                case '660066':
3887
                    $colorIdxBg = 0x1C;
3888
                    break;
3889 2
                case 'FF8080':
3890
                    $colorIdxBg = 0x1D;
3891
                    break;
3892 2
                case '0066CC':
3893
                    $colorIdxBg = 0x1E;
3894
                    break;
3895 2
                case 'CCCCFF':
3896
                    $colorIdxBg = 0x1F;
3897
                    break;
3898 2
                case '000080':
3899
                    $colorIdxBg = 0x20;
3900
                    break;
3901 2
                case 'FF00FF':
3902
                    $colorIdxBg = 0x21;
3903
                    break;
3904 2
                case 'FFFF00':
3905
                    $colorIdxBg = 0x22;
3906
                    break;
3907 2
                case '00FFFF':
3908
                    $colorIdxBg = 0x23;
3909
                    break;
3910 2
                case '800080':
3911
                    $colorIdxBg = 0x24;
3912
                    break;
3913 2
                case '800000':
3914
                    $colorIdxBg = 0x25;
3915
                    break;
3916 2
                case '008080':
3917
                    $colorIdxBg = 0x26;
3918
                    break;
3919 2
                case '0000FF':
3920
                    $colorIdxBg = 0x27;
3921
                    break;
3922 2
                case '00CCFF':
3923
                    $colorIdxBg = 0x28;
3924
                    break;
3925 2
                case 'CCFFFF':
3926
                    $colorIdxBg = 0x29;
3927
                    break;
3928 2
                case 'CCFFCC':
3929
                    $colorIdxBg = 0x2A;
3930
                    break;
3931 2
                case 'FFFF99':
3932
                    $colorIdxBg = 0x2B;
3933
                    break;
3934 2
                case '99CCFF':
3935
                    $colorIdxBg = 0x2C;
3936
                    break;
3937 2
                case 'FF99CC':
3938
                    $colorIdxBg = 0x2D;
3939
                    break;
3940 2
                case 'CC99FF':
3941
                    $colorIdxBg = 0x2E;
3942
                    break;
3943 2
                case 'FFCC99':
3944
                    $colorIdxBg = 0x2F;
3945
                    break;
3946 2
                case '3366FF':
3947
                    $colorIdxBg = 0x30;
3948
                    break;
3949 2
                case '33CCCC':
3950
                    $colorIdxBg = 0x31;
3951
                    break;
3952 2
                case '99CC00':
3953
                    $colorIdxBg = 0x32;
3954
                    break;
3955 2
                case 'FFCC00':
3956
                    $colorIdxBg = 0x33;
3957
                    break;
3958 2
                case 'FF9900':
3959
                    $colorIdxBg = 0x34;
3960
                    break;
3961 2
                case 'FF6600':
3962
                    $colorIdxBg = 0x35;
3963
                    break;
3964 2
                case '666699':
3965
                    $colorIdxBg = 0x36;
3966
                    break;
3967 2
                case '969696':
3968
                    $colorIdxBg = 0x37;
3969
                    break;
3970 2
                case '003366':
3971
                    $colorIdxBg = 0x38;
3972
                    break;
3973 2
                case '339966':
3974
                    $colorIdxBg = 0x39;
3975
                    break;
3976 2
                case '003300':
3977
                    $colorIdxBg = 0x3A;
3978
                    break;
3979 2
                case '333300':
3980
                    $colorIdxBg = 0x3B;
3981
                    break;
3982 2
                case '993300':
3983
                    $colorIdxBg = 0x3C;
3984
                    break;
3985 2
                case '993366':
3986
                    $colorIdxBg = 0x3D;
3987
                    break;
3988 2
                case '333399':
3989
                    $colorIdxBg = 0x3E;
3990
                    break;
3991 2
                case '333333':
3992
                    $colorIdxBg = 0x3F;
3993
                    break;
3994
                default:
3995 2
                          $colorIdxBg = 0x41;
3996 2
                    break;
3997
            }
3998
            // Fg Color
3999 2 View Code Duplication
            switch ($conditional->getStyle()->getFill()->getEndColor()->getRGB()) {
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...
4000 2
                case '000000':
4001
                    $colorIdxFg = 0x08;
4002
                    break;
4003 2
                case 'FFFFFF':
4004
                    $colorIdxFg = 0x09;
4005
                    break;
4006 2
                case 'FF0000':
4007
                    $colorIdxFg = 0x0A;
4008
                    break;
4009 2
                case '00FF00':
4010
                    $colorIdxFg = 0x0B;
4011
                    break;
4012 2
                case '0000FF':
4013
                    $colorIdxFg = 0x0C;
4014
                    break;
4015 2
                case 'FFFF00':
4016
                    $colorIdxFg = 0x0D;
4017
                    break;
4018 2
                case 'FF00FF':
4019
                    $colorIdxFg = 0x0E;
4020
                    break;
4021 2
                case '00FFFF':
4022
                    $colorIdxFg = 0x0F;
4023
                    break;
4024 2
                case '800000':
4025
                    $colorIdxFg = 0x10;
4026
                    break;
4027 2
                case '008000':
4028
                    $colorIdxFg = 0x11;
4029
                    break;
4030 2
                case '000080':
4031
                    $colorIdxFg = 0x12;
4032
                    break;
4033 2
                case '808000':
4034
                    $colorIdxFg = 0x13;
4035
                    break;
4036 2
                case '800080':
4037
                    $colorIdxFg = 0x14;
4038
                    break;
4039 2
                case '008080':
4040
                    $colorIdxFg = 0x15;
4041
                    break;
4042 2
                case 'C0C0C0':
4043
                    $colorIdxFg = 0x16;
4044
                    break;
4045 2
                case '808080':
4046
                    $colorIdxFg = 0x17;
4047
                    break;
4048 2
                case '9999FF':
4049
                    $colorIdxFg = 0x18;
4050
                    break;
4051 2
                case '993366':
4052
                    $colorIdxFg = 0x19;
4053
                    break;
4054 2
                case 'FFFFCC':
4055
                    $colorIdxFg = 0x1A;
4056
                    break;
4057 2
                case 'CCFFFF':
4058
                    $colorIdxFg = 0x1B;
4059
                    break;
4060 2
                case '660066':
4061
                    $colorIdxFg = 0x1C;
4062
                    break;
4063 2
                case 'FF8080':
4064
                    $colorIdxFg = 0x1D;
4065
                    break;
4066 2
                case '0066CC':
4067
                    $colorIdxFg = 0x1E;
4068
                    break;
4069 2
                case 'CCCCFF':
4070
                    $colorIdxFg = 0x1F;
4071
                    break;
4072 2
                case '000080':
4073
                    $colorIdxFg = 0x20;
4074
                    break;
4075 2
                case 'FF00FF':
4076
                    $colorIdxFg = 0x21;
4077
                    break;
4078 2
                case 'FFFF00':
4079
                    $colorIdxFg = 0x22;
4080
                    break;
4081 2
                case '00FFFF':
4082
                    $colorIdxFg = 0x23;
4083
                    break;
4084 2
                case '800080':
4085
                    $colorIdxFg = 0x24;
4086
                    break;
4087 2
                case '800000':
4088
                    $colorIdxFg = 0x25;
4089
                    break;
4090 2
                case '008080':
4091
                    $colorIdxFg = 0x26;
4092
                    break;
4093 2
                case '0000FF':
4094
                    $colorIdxFg = 0x27;
4095
                    break;
4096 2
                case '00CCFF':
4097
                    $colorIdxFg = 0x28;
4098
                    break;
4099 2
                case 'CCFFFF':
4100
                    $colorIdxFg = 0x29;
4101
                    break;
4102 2
                case 'CCFFCC':
4103
                    $colorIdxFg = 0x2A;
4104
                    break;
4105 2
                case 'FFFF99':
4106
                    $colorIdxFg = 0x2B;
4107
                    break;
4108 2
                case '99CCFF':
4109
                    $colorIdxFg = 0x2C;
4110
                    break;
4111 2
                case 'FF99CC':
4112
                    $colorIdxFg = 0x2D;
4113
                    break;
4114 2
                case 'CC99FF':
4115
                    $colorIdxFg = 0x2E;
4116
                    break;
4117 2
                case 'FFCC99':
4118
                    $colorIdxFg = 0x2F;
4119
                    break;
4120 2
                case '3366FF':
4121
                    $colorIdxFg = 0x30;
4122
                    break;
4123 2
                case '33CCCC':
4124
                    $colorIdxFg = 0x31;
4125
                    break;
4126 2
                case '99CC00':
4127
                    $colorIdxFg = 0x32;
4128
                    break;
4129 2
                case 'FFCC00':
4130
                    $colorIdxFg = 0x33;
4131
                    break;
4132 2
                case 'FF9900':
4133
                    $colorIdxFg = 0x34;
4134
                    break;
4135 2
                case 'FF6600':
4136
                    $colorIdxFg = 0x35;
4137
                    break;
4138 2
                case '666699':
4139
                    $colorIdxFg = 0x36;
4140
                    break;
4141 2
                case '969696':
4142
                    $colorIdxFg = 0x37;
4143
                    break;
4144 2
                case '003366':
4145
                    $colorIdxFg = 0x38;
4146
                    break;
4147 2
                case '339966':
4148
                    $colorIdxFg = 0x39;
4149
                    break;
4150 2
                case '003300':
4151
                    $colorIdxFg = 0x3A;
4152
                    break;
4153 2
                case '333300':
4154
                    $colorIdxFg = 0x3B;
4155
                    break;
4156 2
                case '993300':
4157
                    $colorIdxFg = 0x3C;
4158
                    break;
4159 2
                case '993366':
4160
                    $colorIdxFg = 0x3D;
4161
                    break;
4162 2
                case '333399':
4163
                    $colorIdxFg = 0x3E;
4164
                    break;
4165 2
                case '333333':
4166
                    $colorIdxFg = 0x3F;
4167
                    break;
4168
                default:
4169 2
                          $colorIdxFg = 0x40;
4170 2
                    break;
4171
            }
4172 2
            $dataBlockFill = pack('v', $blockFillPatternStyle);
4173 2
            $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7));
4174
        }
4175 2
        if ($bFormatProt == 1) {
4176
            $dataBlockProtection = 0;
4177
            if ($conditional->getStyle()->getProtection()->getLocked() == \PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED) {
4178
                $dataBlockProtection = 1;
4179
            }
4180
            if ($conditional->getStyle()->getProtection()->getHidden() == \PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED) {
4181
                $dataBlockProtection = 1 << 1;
4182
            }
4183
        }
4184
4185 2
        $data = pack('CCvvVv', $type, $operatorType, $szValue1, $szValue2, $flags, 0x0000);
0 ignored issues
show
Bug introduced by
The variable $type 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...
Bug introduced by
The variable $operatorType 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...
4186 2
        if ($bFormatFont == 1) { // Block Formatting : OK
4187 2
            $data .= $dataBlockFont;
0 ignored issues
show
Bug introduced by
The variable $dataBlockFont 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...
4188
        }
4189 2
        if ($bFormatAlign == 1) {
4190
            $data .= $dataBlockAlign;
0 ignored issues
show
Bug introduced by
The variable $dataBlockAlign 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...
4191
        }
4192 2
        if ($bFormatBorder == 1) {
4193
            $data .= $dataBlockBorder;
0 ignored issues
show
Bug introduced by
The variable $dataBlockBorder 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...
4194
        }
4195 2
        if ($bFormatFill == 1) { // Block Formatting : OK
4196 2
            $data .= $dataBlockFill;
0 ignored issues
show
Bug introduced by
The variable $dataBlockFill 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...
4197
        }
4198 2
        if ($bFormatProt == 1) {
4199
            $data .= $dataBlockProtection;
0 ignored issues
show
Bug introduced by
The variable $dataBlockProtection 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...
4200
        }
4201 2
        if (!is_null($operand1)) {
4202 2
            $data .= $operand1;
4203
        }
4204 2
        if (!is_null($operand2)) {
4205 1
            $data .= $operand2;
4206
        }
4207 2
        $header = pack('vv', $record, strlen($data));
4208 2
        $this->append($header . $data);
4209 2
    }
4210
4211
    /**
4212
     * Write CFHeader record.
4213
     */
4214 2
    private function writeCFHeader()
4215
    {
4216 2
        $record = 0x01B0; // Record identifier
4217 2
        $length = 0x0016; // Bytes to follow
4218
4219 2
        $numColumnMin = null;
4220 2
        $numColumnMax = null;
4221 2
        $numRowMin = null;
4222 2
        $numRowMax = null;
4223 2
        $arrConditional = [];
4224 2
        foreach ($this->phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
4225 2
            foreach ($conditionalStyles as $conditional) {
4226 2
                if ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION
4227 2
                        || $conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
4228 2
                    if (!in_array($conditional->getHashCode(), $arrConditional)) {
4229 2
                        $arrConditional[] = $conditional->getHashCode();
4230
                    }
4231
                    // Cells
4232 2
                    $arrCoord = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($cellCoordinate);
4233 2
                    if (!is_numeric($arrCoord[0])) {
4234 2
                        $arrCoord[0] = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($arrCoord[0]);
4235
                    }
4236 2
                    if (is_null($numColumnMin) || ($numColumnMin > $arrCoord[0])) {
4237 2
                        $numColumnMin = $arrCoord[0];
4238
                    }
4239 2
                    if (is_null($numColumnMax) || ($numColumnMax < $arrCoord[0])) {
4240 2
                        $numColumnMax = $arrCoord[0];
4241
                    }
4242 2
                    if (is_null($numRowMin) || ($numRowMin > $arrCoord[1])) {
4243 2
                        $numRowMin = $arrCoord[1];
4244
                    }
4245 2
                    if (is_null($numRowMax) || ($numRowMax < $arrCoord[1])) {
4246 2
                        $numRowMax = $arrCoord[1];
4247
                    }
4248
                }
4249
            }
4250
        }
4251 2
        $needRedraw = 1;
4252 2
        $cellRange = pack('vvvv', $numRowMin - 1, $numRowMax - 1, $numColumnMin - 1, $numColumnMax - 1);
4253
4254 2
        $header = pack('vv', $record, $length);
4255 2
        $data = pack('vv', count($arrConditional), $needRedraw);
4256 2
        $data .= $cellRange;
4257 2
        $data .= pack('v', 0x0001);
4258 2
        $data .= $cellRange;
4259 2
        $this->append($header . $data);
4260 2
    }
4261
}
4262