Completed
Push — develop ( fb1d28...296cc6 )
by Adrien
23:03
created

Worksheet::writePassword()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 2
nop 0
dl 0
loc 17
ccs 10
cts 10
cp 1
crap 3
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
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
24
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
25
 * @version    ##VERSION##, ##DATE##
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
     * @var int
74
     */
75
    private $xlsStringMaxLength;
76
77
    /**
78
     * Array containing format information for columns
79
     * @var array
80
     */
81
    private $columnInfo;
82
83
    /**
84
     * Array containing the selected area for the worksheet
85
     * @var array
86
     */
87
    private $selection;
88
89
    /**
90
     * The active pane for the worksheet
91
     * @var int
92
     */
93
    private $activePane;
94
95
    /**
96
     * Whether to use outline.
97
     * @var int
98
     */
99
    private $outlineOn;
100
101
    /**
102
     * Auto outline styles.
103
     * @var bool
104
     */
105
    private $outlineStyle;
106
107
    /**
108
     * Whether to have outline summary below.
109
     * @var bool
110
     */
111
    private $outlineBelow;
112
113
    /**
114
     * Whether to have outline summary at the right.
115
     * @var bool
116
     */
117
    private $outlineRight;
118
119
    /**
120
     * Reference to the total number of strings in the workbook
121
     * @var int
122
     */
123
    private $stringTotal;
124
125
    /**
126
     * Reference to the number of unique strings in the workbook
127
     * @var int
128
     */
129
    private $stringUnique;
130
131
    /**
132
     * Reference to the array containing all the unique strings in the workbook
133
     * @var array
134
     */
135
    private $stringTable;
136
137
    /**
138
     * Color cache
139
     */
140
    private $colors;
141
142
    /**
143
     * Index of first used row (at least 0)
144
     * @var int
145
     */
146
    private $firstRowIndex;
147
148
    /**
149
     * Index of last used row. (no used rows means -1)
150
     * @var int
151
     */
152
    private $lastRowIndex;
153
154
    /**
155
     * Index of first used column (at least 0)
156
     * @var int
157
     */
158
    private $firstColumnIndex;
159
160
    /**
161
     * Index of last used column (no used columns means -1)
162
     * @var int
163
     */
164
    private $lastColumnIndex;
165
166
    /**
167
     * Sheet object
168
     * @var \PhpOffice\PhpSpreadsheet\Worksheet
169
     */
170
    public $phpSheet;
171
172
    /**
173
     * Count cell style Xfs
174
     *
175
     * @var int
176
     */
177
    private $countCellStyleXfs;
178
179
    /**
180
     * Escher object corresponding to MSODRAWING
181
     *
182
     * @var \PhpOffice\PhpSpreadsheet\Shared\Escher
183
     */
184
    private $escher;
185
186
    /**
187
     * Array of font hashes associated to FONT records index
188
     *
189
     * @var array
190
     */
191
    public $fontHashIndex;
192
193
    /**
194
     * Constructor
195
     *
196
     * @param int        &$str_total        Total number of strings
197
     * @param int        &$str_unique    Total number of unique strings
198
     * @param array        &$str_table        String Table
199
     * @param array        &$colors        Colour Table
200
     * @param mixed        $parser            The formula parser created for the Workbook
201
     * @param bool    $preCalculateFormulas    Flag indicating whether formulas should be calculated or just written
202
     * @param string    $phpSheet        The worksheet to write
203
     * @param \PhpOffice\PhpSpreadsheet\Worksheet $phpSheet
204
     */
205 38
    public function __construct(&$str_total, &$str_unique, &$str_table, &$colors, $parser, $preCalculateFormulas, $phpSheet)
206
    {
207
        // It needs to call its parent's constructor explicitly
208 38
        parent::__construct();
209
210 38
        $this->_preCalculateFormulas = $preCalculateFormulas;
0 ignored issues
show
Bug introduced by
The property _preCalculateFormulas does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
211 38
        $this->stringTotal = &$str_total;
212 38
        $this->stringUnique = &$str_unique;
213 38
        $this->stringTable = &$str_table;
214 38
        $this->colors = &$colors;
215 38
        $this->parser = $parser;
216
217 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...
218
219 38
        $this->xlsStringMaxLength = 255;
220 38
        $this->columnInfo = [];
221 38
        $this->selection = [0, 0, 0, 0];
222 38
        $this->activePane = 3;
223
224 38
        $this->_print_headers = 0;
0 ignored issues
show
Bug introduced by
The property _print_headers does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
225
226 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...
227 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...
228 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...
229 38
        $this->outlineOn = 1;
230
231 38
        $this->fontHashIndex = [];
232
233
        // calculate values for DIMENSIONS record
234 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...
235 38
        $minC = 'A';
236
237 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...
238 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...
239
240
        // Determine lowest and highest column and row
241 38
        $this->lastRowIndex = ($maxR > 65535) ? 65535 : $maxR;
242
243 38
        $this->firstColumnIndex = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($minC);
244 38
        $this->lastColumnIndex = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($maxC);
245
246
//        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...
247 38
        if ($this->lastColumnIndex > 255) {
248
            $this->lastColumnIndex = 255;
249
        }
250
251 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...
252 38
    }
253
254
    /**
255
     * Add data to the beginning of the workbook (note the reverse order)
256
     * and to the end of the workbook.
257
     *
258
     * @see \PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook::storeWorkbook()
259
     */
260 38
    public function close()
261
    {
262 38
        $phpSheet = $this->phpSheet;
263
264 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...
265
266
        // Write BOF record
267 38
        $this->storeBof(0x0010);
268
269
        // Write PRINTHEADERS
270 38
        $this->writePrintHeaders();
271
272
        // Write PRINTGRIDLINES
273 38
        $this->writePrintGridlines();
274
275
        // Write GRIDSET
276 38
        $this->writeGridset();
277
278
        // Calculate column widths
279 38
        $phpSheet->calculateColumnWidths();
280
281
        // Column dimensions
282 38
        if (($defaultWidth = $phpSheet->getDefaultColumnDimension()->getWidth()) < 0) {
283 38
            $defaultWidth = \PhpOffice\PhpSpreadsheet\Shared\Font::getDefaultColumnWidthByFont($phpSheet->getParent()->getDefaultStyle()->getFont());
284
        }
285
286 38
        $columnDimensions = $phpSheet->getColumnDimensions();
287 38
        $maxCol = $this->lastColumnIndex - 1;
288 38
        for ($i = 0; $i <= $maxCol; ++$i) {
289 38
            $hidden = 0;
290 38
            $level = 0;
291 38
            $xfIndex = 15; // there are 15 cell style Xfs
292
293 38
            $width = $defaultWidth;
294
295 38
            $columnLetter = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($i);
296 38
            if (isset($columnDimensions[$columnLetter])) {
297 19
                $columnDimension = $columnDimensions[$columnLetter];
298 19
                if ($columnDimension->getWidth() >= 0) {
299 19
                    $width = $columnDimension->getWidth();
300
                }
301 19
                $hidden = $columnDimension->getVisible() ? 0 : 1;
302 19
                $level = $columnDimension->getOutlineLevel();
303 19
                $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs
304
            }
305
306
            // Components of columnInfo:
307
            // $firstcol first column on the range
308
            // $lastcol  last column on the range
309
            // $width    width to set
310
            // $xfIndex  The optional cell style Xf index to apply to the columns
311
            // $hidden   The optional hidden atribute
312
            // $level    The optional outline level
313 38
            $this->columnInfo[] = [$i, $i, $width, $xfIndex, $hidden, $level];
314
        }
315
316
        // Write GUTS
317 38
        $this->writeGuts();
318
319
        // Write DEFAULTROWHEIGHT
320 38
        $this->writeDefaultRowHeight();
321
        // Write WSBOOL
322 38
        $this->writeWsbool();
323
        // Write horizontal and vertical page breaks
324 38
        $this->writeBreaks();
325
        // Write page header
326 38
        $this->writeHeader();
327
        // Write page footer
328 38
        $this->writeFooter();
329
        // Write page horizontal centering
330 38
        $this->writeHcenter();
331
        // Write page vertical centering
332 38
        $this->writeVcenter();
333
        // Write left margin
334 38
        $this->writeMarginLeft();
335
        // Write right margin
336 38
        $this->writeMarginRight();
337
        // Write top margin
338 38
        $this->writeMarginTop();
339
        // Write bottom margin
340 38
        $this->writeMarginBottom();
341
        // Write page setup
342 38
        $this->writeSetup();
343
        // Write sheet protection
344 38
        $this->writeProtect();
345
        // Write SCENPROTECT
346 38
        $this->writeScenProtect();
347
        // Write OBJECTPROTECT
348 38
        $this->writeObjectProtect();
349
        // Write sheet password
350 38
        $this->writePassword();
351
        // Write DEFCOLWIDTH record
352 38
        $this->writeDefcol();
353
354
        // Write the COLINFO records if they exist
355 38
        if (!empty($this->columnInfo)) {
356 38
            $colcount = count($this->columnInfo);
357 38
            for ($i = 0; $i < $colcount; ++$i) {
358 38
                $this->writeColinfo($this->columnInfo[$i]);
359
            }
360
        }
361 38
        $autoFilterRange = $phpSheet->getAutoFilter()->getRange();
362 38
        if (!empty($autoFilterRange)) {
363
            // Write AUTOFILTERINFO
364 3
            $this->writeAutoFilterInfo();
365
        }
366
367
        // Write sheet dimensions
368 38
        $this->writeDimensions();
369
370
        // Row dimensions
371 38
        foreach ($phpSheet->getRowDimensions() as $rowDimension) {
372 37
            $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs
373 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...
374
        }
375
376
        // Write Cells
377 38
        foreach ($phpSheet->getCellCollection() as $cellID) {
378 38
            $cell = $phpSheet->getCell($cellID);
379 38
            $row = $cell->getRow() - 1;
380 38
            $column = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($cell->getColumn()) - 1;
381
382
            // Don't break Excel!
383
//            if ($row + 1 > 65536 or $column + 1 > 256) {
384 38
            if ($row > 65535 || $column > 255) {
385
                break;
386
            }
387
388
            // Write cell value
389 38
            $xfIndex = $cell->getXfIndex() + 15; // there are 15 cell style Xfs
390
391 38
            $cVal = $cell->getValue();
392 38
            if ($cVal instanceof \PhpOffice\PhpSpreadsheet\RichText) {
393 9
                $arrcRun = [];
394 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...
395 9
                $str_pos = 0;
396 9
                $elements = $cVal->getRichTextElements();
397 9
                foreach ($elements as $element) {
398
                    // FONT Index
399 9
                    if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
400 9
                        $str_fontidx = $this->fontHashIndex[$element->getFont()->getHashCode()];
401
                    } else {
402 8
                        $str_fontidx = 0;
403
                    }
404 9
                    $arrcRun[] = ['strlen' => $str_pos, 'fontidx' => $str_fontidx];
405
                    // Position FROM
406 9
                    $str_pos += \PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($element->getText(), 'UTF-8');
407
                }
408 9
                $this->writeRichTextString($row, $column, $cVal->getPlainText(), $xfIndex, $arrcRun);
409
            } else {
410 37
                switch ($cell->getDatatype()) {
411 37
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING:
412 30
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NULL:
413 35
                        if ($cVal === '' || $cVal === null) {
414 18
                            $this->writeBlank($row, $column, $xfIndex);
415
                        } else {
416 33
                            $this->writeString($row, $column, $cVal, $xfIndex);
417
                        }
418 35
                        break;
419
420 26
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC:
421 23
                        $this->writeNumber($row, $column, $cVal, $xfIndex);
422 23
                        break;
423
424 18
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_FORMULA:
425 16
                        $calculatedValue = $this->_preCalculateFormulas ?
426 16
                            $cell->getCalculatedValue() : null;
427 16
                        $this->writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue);
428 16
                        break;
429
430 8
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_BOOL:
431 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...
432 8
                        break;
433
434
                    case \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_ERROR:
435
                        $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...
436 38
                        break;
437
                }
438
            }
439
        }
440
441
        // Append
442 38
        $this->writeMsoDrawing();
443
444
        // Write WINDOW2 record
445 38
        $this->writeWindow2();
446
447
        // Write PLV record
448 38
        $this->writePageLayoutView();
449
450
        // Write ZOOM record
451 38
        $this->writeZoom();
452 38
        if ($phpSheet->getFreezePane()) {
453 3
            $this->writePanes();
454
        }
455
456
        // Write SELECTION record
457 38
        $this->writeSelection();
458
459
        // Write MergedCellsTable Record
460 38
        $this->writeMergedCells();
461
462
        // Hyperlinks
463 38
        foreach ($phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) {
464 7
            list($column, $row) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($coordinate);
465
466 7
            $url = $hyperlink->getUrl();
467
468 7
            if (strpos($url, 'sheet://') !== false) {
469
                // internal to current workbook
470 6
                $url = str_replace('sheet://', 'internal:', $url);
471 7
            } 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...
472
                // URL
473
            } else {
474
                // external (local file)
475
                $url = 'external:' . $url;
476
            }
477
478 7
            $this->writeUrl($row - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($column) - 1, $url);
479
        }
480
481 38
        $this->writeDataValidity();
482 38
        $this->writeSheetLayout();
483
484
        // Write SHEETPROTECTION record
485 38
        $this->writeSheetProtection();
486 38
        $this->writeRangeProtection();
487
488 38
        $arrConditionalStyles = $phpSheet->getConditionalStylesCollection();
489 38
        if (!empty($arrConditionalStyles)) {
490 2
            $arrConditional = [];
491
            // @todo CFRule & CFHeader
492
            // Write CFHEADER record
493 2
            $this->writeCFHeader();
494
            // Write ConditionalFormattingTable records
495 2
            foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) {
496 2
                foreach ($conditionalStyles as $conditional) {
497 2
                    if ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION
498 2
                        || $conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
499 2
                        if (!in_array($conditional->getHashCode(), $arrConditional)) {
500 2
                            $arrConditional[] = $conditional->getHashCode();
501
                            // Write CFRULE record
502 2
                            $this->writeCFRule($conditional);
503
                        }
504
                    }
505
                }
506
            }
507
        }
508
509 38
        $this->storeEof();
510 38
    }
511
512
    /**
513
     * Write a cell range address in BIFF8
514
     * always fixed range
515
     * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format
516
     *
517
     * @param string $range E.g. 'A1' or 'A1:B6'
518
     * @return string Binary data
519
     */
520 7
    private function writeBIFF8CellRangeAddressFixed($range = 'A1')
521
    {
522 7
        $explodes = explode(':', $range);
523
524
        // extract first cell, e.g. 'A1'
525 7
        $firstCell = $explodes[0];
526
527
        // extract last cell, e.g. 'B6'
528 7
        if (count($explodes) == 1) {
529 2
            $lastCell = $firstCell;
530
        } else {
531 5
            $lastCell = $explodes[1];
532
        }
533
534 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...
535 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...
536
537 7
        return pack('vvvv', $firstCellCoordinates[1] - 1, $lastCellCoordinates[1] - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($firstCellCoordinates[0]) - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($lastCellCoordinates[0]) - 1);
538
    }
539
540
    /**
541
     * Retrieves data from memory in one chunk, or from disk in $buffer
542
     * sized chunks.
543
     *
544
     * @return string The data
545
     */
546 38
    public function getData()
547
    {
548 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...
549
550
        // Return data stored in memory
551 38
        if (isset($this->_data)) {
552 38
            $tmp = $this->_data;
553 38
            unset($this->_data);
554
555 38
            return $tmp;
556
        }
557
        // No data to return
558
        return false;
559
    }
560
561
    /**
562
     * Set the option to print the row and column headers on the printed page.
563
     *
564
     * @param int $print Whether to print the headers or not. Defaults to 1 (print).
565
     */
566
    public function printRowColHeaders($print = 1)
567
    {
568
        $this->_print_headers = $print;
569
    }
570
571
    /**
572
     * This method sets the properties for outlining and grouping. The defaults
573
     * correspond to Excel's defaults.
574
     *
575
     * @param bool $visible
576
     * @param bool $symbols_below
577
     * @param bool $symbols_right
578
     * @param bool $auto_style
579
     */
580
    public function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false)
581
    {
582
        $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...
583
        $this->outlineBelow = $symbols_below;
584
        $this->outlineRight = $symbols_right;
585
        $this->outlineStyle = $auto_style;
586
587
        // Ensure this is a boolean vale for Window2
588
        if ($this->outlineOn) {
589
            $this->outlineOn = 1;
590
        }
591
    }
592
593
    /**
594
     * Write a double to the specified row and column (zero indexed).
595
     * An integer can be written as a double. Excel will display an
596
     * integer. $format is optional.
597
     *
598
     * Returns  0 : normal termination
599
     *         -2 : row or column out of range
600
     *
601
     * @param int $row    Zero indexed row
602
     * @param int $col    Zero indexed column
603
     * @param float   $num    The number to write
604
     * @param mixed   $xfIndex The optional XF format
605
     * @return int
606
     */
607 23
    private function writeNumber($row, $col, $num, $xfIndex)
608
    {
609 23
        $record = 0x0203; // Record identifier
610 23
        $length = 0x000E; // Number of bytes to follow
611
612 23
        $header = pack('vv', $record, $length);
613 23
        $data = pack('vvv', $row, $col, $xfIndex);
614 23
        $xl_double = pack('d', $num);
615 23
        if (self::getByteOrder()) { // if it's Big Endian
616
            $xl_double = strrev($xl_double);
617
        }
618
619 23
        $this->append($header . $data . $xl_double);
620
621 23
        return 0;
622
    }
623
624
    /**
625
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
626
     *
627
     * @param int $row Row index (0-based)
628
     * @param int $col Column index (0-based)
629
     * @param string $str The string
630
     * @param int $xfIndex Index to XF record
631
     */
632 33
    private function writeString($row, $col, $str, $xfIndex)
633
    {
634 33
        $this->writeLabelSst($row, $col, $str, $xfIndex);
635 33
    }
636
637
    /**
638
     * Write a LABELSST record or a LABEL record. Which one depends on BIFF version
639
     * It differs from writeString by the writing of rich text strings.
640
     * @param int $row Row index (0-based)
641
     * @param int $col Column index (0-based)
642
     * @param string $str The string
643
     * @param int   $xfIndex The XF format index for the cell
644
     * @param array $arrcRun Index to Font record and characters beginning
645
     */
646 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...
647
    {
648 9
        $record = 0x00FD; // Record identifier
649 9
        $length = 0x000A; // Bytes to follow
650 9
        $str = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeShort($str, $arrcRun);
651
652
        /* check if string is already present */
653 9
        if (!isset($this->stringTable[$str])) {
654 9
            $this->stringTable[$str] = $this->stringUnique++;
655
        }
656 9
        ++$this->stringTotal;
657
658 9
        $header = pack('vv', $record, $length);
659 9
        $data = pack('vvvV', $row, $col, $xfIndex, $this->stringTable[$str]);
660 9
        $this->append($header . $data);
661 9
    }
662
663
    /**
664
     * Write a string to the specified row and column (zero indexed).
665
     * NOTE: there is an Excel 5 defined limit of 255 characters.
666
     * $format is optional.
667
     * Returns  0 : normal termination
668
     *         -2 : row or column out of range
669
     *         -3 : long string truncated to 255 chars
670
     *
671
     * @param int $row    Zero indexed row
672
     * @param int $col    Zero indexed column
673
     * @param string  $str    The string to write
674
     * @param mixed   $xfIndex The XF format index for the cell
675
     * @return int
676
     */
677
    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...
678
    {
679
        $strlen = strlen($str);
680
        $record = 0x0204; // Record identifier
681
        $length = 0x0008 + $strlen; // Bytes to follow
682
683
        $str_error = 0;
684
685
        if ($strlen > $this->xlsStringMaxLength) { // LABEL must be < 255 chars
686
            $str = substr($str, 0, $this->xlsStringMaxLength);
687
            $length = 0x0008 + $this->xlsStringMaxLength;
688
            $strlen = $this->xlsStringMaxLength;
689
            $str_error = -3;
690
        }
691
692
        $header = pack('vv', $record, $length);
693
        $data = pack('vvvv', $row, $col, $xfIndex, $strlen);
694
        $this->append($header . $data . $str);
695
696
        return $str_error;
697
    }
698
699
    /**
700
     * Write a string to the specified row and column (zero indexed).
701
     * This is the BIFF8 version (no 255 chars limit).
702
     * $format is optional.
703
     * Returns  0 : normal termination
704
     *         -2 : row or column out of range
705
     *         -3 : long string truncated to 255 chars
706
     *
707
     * @param int $row    Zero indexed row
708
     * @param int $col    Zero indexed column
709
     * @param string  $str    The string to write
710
     * @param mixed   $xfIndex The XF format index for the cell
711
     * @return int
712
     */
713 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...
714
    {
715 33
        $record = 0x00FD; // Record identifier
716 33
        $length = 0x000A; // Bytes to follow
717
718 33
        $str = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($str);
719
720
        /* check if string is already present */
721 33
        if (!isset($this->stringTable[$str])) {
722 33
            $this->stringTable[$str] = $this->stringUnique++;
723
        }
724 33
        ++$this->stringTotal;
725
726 33
        $header = pack('vv', $record, $length);
727 33
        $data = pack('vvvV', $row, $col, $xfIndex, $this->stringTable[$str]);
728 33
        $this->append($header . $data);
729 33
    }
730
731
    /**
732
     * Writes a note associated with the cell given by the row and column.
733
     * NOTE records don't have a length limit.
734
     *
735
     * @param int $row    Zero indexed row
736
     * @param int $col    Zero indexed column
737
     * @param string  $note   The note to write
738
     */
739
    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...
740
    {
741
        $note_length = strlen($note);
742
        $record = 0x001C; // Record identifier
743
        $max_length = 2048; // Maximun length for a NOTE record
744
745
        // Length for this record is no more than 2048 + 6
746
        $length = 0x0006 + min($note_length, 2048);
747
        $header = pack('vv', $record, $length);
748
        $data = pack('vvv', $row, $col, $note_length);
749
        $this->append($header . $data . substr($note, 0, 2048));
750
751
        for ($i = $max_length; $i < $note_length; $i += $max_length) {
752
            $chunk = substr($note, $i, $max_length);
753
            $length = 0x0006 + strlen($chunk);
754
            $header = pack('vv', $record, $length);
755
            $data = pack('vvv', -1, 0, strlen($chunk));
756
            $this->append($header . $data . $chunk);
757
        }
758
759
        return 0;
760
    }
761
762
    /**
763
     * Write a blank cell to the specified row and column (zero indexed).
764
     * A blank cell is used to specify formatting without adding a string
765
     * or a number.
766
     *
767
     * A blank cell without a format serves no purpose. Therefore, we don't write
768
     * a BLANK record unless a format is specified.
769
     *
770
     * Returns  0 : normal termination (including no format)
771
     *         -1 : insufficient number of arguments
772
     *         -2 : row or column out of range
773
     *
774
     * @param int $row    Zero indexed row
775
     * @param int $col    Zero indexed column
776
     * @param mixed   $xfIndex The XF format index
777
     */
778 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...
779
    {
780 18
        $record = 0x0201; // Record identifier
781 18
        $length = 0x0006; // Number of bytes to follow
782
783 18
        $header = pack('vv', $record, $length);
784 18
        $data = pack('vvv', $row, $col, $xfIndex);
785 18
        $this->append($header . $data);
786
787 18
        return 0;
788
    }
789
790
    /**
791
     * Write a boolean or an error type to the specified row and column (zero indexed)
792
     *
793
     * @param int $row Row index (0-based)
794
     * @param int $col Column index (0-based)
795
     * @param int $value
796
     * @param bool $isError Error or Boolean?
797
     * @param int $xfIndex
798
     */
799 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...
800
    {
801 8
        $record = 0x0205;
802 8
        $length = 8;
803
804 8
        $header = pack('vv', $record, $length);
805 8
        $data = pack('vvvCC', $row, $col, $xfIndex, $value, $isError);
806 8
        $this->append($header . $data);
807
808 8
        return 0;
809
    }
810
811
    /**
812
     * Write a formula to the specified row and column (zero indexed).
813
     * The textual representation of the formula is passed to the parser in
814
     * Parser.php which returns a packed binary string.
815
     *
816
     * Returns  0 : normal termination
817
     *         -1 : formula errors (bad formula)
818
     *         -2 : row or column out of range
819
     *
820
     * @param int $row     Zero indexed row
821
     * @param int $col     Zero indexed column
822
     * @param string  $formula The formula text string
823
     * @param mixed   $xfIndex  The XF format index
824
     * @param mixed   $calculatedValue  Calculated value
825
     * @return int
826
     */
827 16
    private function writeFormula($row, $col, $formula, $xfIndex, $calculatedValue)
828
    {
829 16
        $record = 0x0006; // Record identifier
830
831
        // Initialize possible additional value for STRING record that should be written after the FORMULA record?
832 16
        $stringValue = null;
833
834
        // calculated value
835 16
        if (isset($calculatedValue)) {
836
            // Since we can't yet get the data type of the calculated value,
837
            // we use best effort to determine data type
838 16
            if (is_bool($calculatedValue)) {
839
                // Boolean value
840 3
                $num = pack('CCCvCv', 0x01, 0x00, (int) $calculatedValue, 0x00, 0x00, 0xFFFF);
841 16
            } elseif (is_int($calculatedValue) || is_float($calculatedValue)) {
842
                // Numeric value
843 14
                $num = pack('d', $calculatedValue);
844 12
            } elseif (is_string($calculatedValue)) {
845 12
                $errorCodes = \PhpOffice\PhpSpreadsheet\Cell\DataType::getErrorCodes();
846 12
                if (isset($errorCodes[$calculatedValue])) {
847
                    // Error value
848 4
                    $num = pack('CCCvCv', 0x02, 0x00, self::mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF);
849 12
                } elseif ($calculatedValue === '') {
850
                    // 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...
851 5
                    $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF);
852
                } else {
853
                    // Non-empty string value (or empty string BIFF5)
854 7
                    $stringValue = $calculatedValue;
855 12
                    $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF);
856
                }
857
            } else {
858
                // We are really not supposed to reach here
859 16
                $num = pack('d', 0x00);
860
            }
861
        } else {
862
            $num = pack('d', 0x00);
863
        }
864
865 16
        $grbit = 0x03; // Option flags
866 16
        $unknown = 0x0000; // Must be zero
867
868
        // Strip the '=' or '@' sign at the beginning of the formula string
869 16
        if ($formula{0} == '=') {
870 16
            $formula = substr($formula, 1);
871
        } else {
872
            // Error handling
873
            $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...
874
875
            return -1;
876
        }
877
878
        // Parse the formula using the parser in Parser.php
879
        try {
880 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...
881 16
            $formula = $this->parser->toReversePolish();
882
883 16
            $formlen = strlen($formula); // Length of the binary string
884 16
            $length = 0x16 + $formlen; // Length of the record data
885
886 16
            $header = pack('vv', $record, $length);
887
888 16
            $data = pack('vvv', $row, $col, $xfIndex)
889 16
                        . $num
890 16
                        . pack('vVv', $grbit, $unknown, $formlen);
891 16
            $this->append($header . $data . $formula);
892
893
            // Append also a STRING record if necessary
894 16
            if ($stringValue !== null) {
895 7
                $this->writeStringRecord($stringValue);
896
            }
897
898 16
            return 0;
899 5
        } catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
900
            // do nothing
901
        }
902 5
    }
903
904
    /**
905
     * Write a STRING record. This
906
     *
907
     * @param string $stringValue
908
     */
909 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...
910
    {
911 7
        $record = 0x0207; // Record identifier
912 7
        $data = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($stringValue);
913
914 7
        $length = strlen($data);
915 7
        $header = pack('vv', $record, $length);
916
917 7
        $this->append($header . $data);
918 7
    }
919
920
    /**
921
     * Write a hyperlink.
922
     * This is comprised of two elements: the visible label and
923
     * the invisible link. The visible label is the same as the link unless an
924
     * alternative string is specified. The label is written using the
925
     * writeString() method. Therefore the 255 characters string limit applies.
926
     * $string and $format are optional.
927
     *
928
     * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external
929
     * directory url.
930
     *
931
     * Returns  0 : normal termination
932
     *         -2 : row or column out of range
933
     *         -3 : long string truncated to 255 chars
934
     *
935
     * @param int $row    Row
936
     * @param int $col    Column
937
     * @param string  $url    URL string
938
     * @return int
939
     */
940 7
    private function writeUrl($row, $col, $url)
941
    {
942
        // Add start row and col to arg list
943 7
        return $this->writeUrlRange($row, $col, $row, $col, $url);
944
    }
945
946
    /**
947
     * This is the more general form of writeUrl(). It allows a hyperlink to be
948
     * written to a range of cells. This function also decides the type of hyperlink
949
     * to be written. These are either, Web (http, ftp, mailto), Internal
950
     * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1').
951
     *
952
     * @see writeUrl()
953
     * @param int $row1   Start row
954
     * @param int $col1   Start column
955
     * @param int $row2   End row
956
     * @param int $col2   End column
957
     * @param string  $url    URL string
958
     * @return int
959
     */
960 7
    public function writeUrlRange($row1, $col1, $row2, $col2, $url)
961
    {
962
        // Check for internal/external sheet links or default to web link
963 7
        if (preg_match('[^internal:]', $url)) {
964 6
            return $this->writeUrlInternal($row1, $col1, $row2, $col2, $url);
965
        }
966 7
        if (preg_match('[^external:]', $url)) {
967
            return $this->writeUrlExternal($row1, $col1, $row2, $col2, $url);
968
        }
969
970 7
        return $this->writeUrlWeb($row1, $col1, $row2, $col2, $url);
971
    }
972
973
    /**
974
     * Used to write http, ftp and mailto hyperlinks.
975
     * The link type ($options) is 0x03 is the same as absolute dir ref without
976
     * sheet. However it is differentiated by the $unknown2 data stream.
977
     *
978
     * @see writeUrl()
979
     * @param int $row1   Start row
980
     * @param int $col1   Start column
981
     * @param int $row2   End row
982
     * @param int $col2   End column
983
     * @param string  $url    URL string
984
     * @return int
985
     */
986 7
    public function writeUrlWeb($row1, $col1, $row2, $col2, $url)
987
    {
988 7
        $record = 0x01B8; // Record identifier
989 7
        $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...
990
991
        // Pack the undocumented parts of the hyperlink stream
992 7
        $unknown1 = pack('H*', 'D0C9EA79F9BACE118C8200AA004BA90B02000000');
993 7
        $unknown2 = pack('H*', 'E0C9EA79F9BACE118C8200AA004BA90B');
994
995
        // Pack the option flags
996 7
        $options = pack('V', 0x03);
997
998
        // Convert URL to a null terminated wchar string
999 7
        $url = implode("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY));
1000 7
        $url = $url . "\0\0\0";
1001
1002
        // Pack the length of the URL
1003 7
        $url_len = pack('V', strlen($url));
1004
1005
        // Calculate the data length
1006 7
        $length = 0x34 + strlen($url);
1007
1008
        // Pack the header data
1009 7
        $header = pack('vv', $record, $length);
1010 7
        $data = pack('vvvv', $row1, $row2, $col1, $col2);
1011
1012
        // Write the packed data
1013 7
        $this->append($header . $data . $unknown1 . $options . $unknown2 . $url_len . $url);
1014
1015 7
        return 0;
1016
    }
1017
1018
    /**
1019
     * Used to write internal reference hyperlinks such as "Sheet1!A1".
1020
     *
1021
     * @see writeUrl()
1022
     * @param int $row1   Start row
1023
     * @param int $col1   Start column
1024
     * @param int $row2   End row
1025
     * @param int $col2   End column
1026
     * @param string  $url    URL string
1027
     * @return int
1028
     */
1029 6
    public function writeUrlInternal($row1, $col1, $row2, $col2, $url)
1030
    {
1031 6
        $record = 0x01B8; // Record identifier
1032 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...
1033
1034
        // Strip URL type
1035 6
        $url = preg_replace('/^internal:/', '', $url);
1036
1037
        // Pack the undocumented parts of the hyperlink stream
1038 6
        $unknown1 = pack('H*', 'D0C9EA79F9BACE118C8200AA004BA90B02000000');
1039
1040
        // Pack the option flags
1041 6
        $options = pack('V', 0x08);
1042
1043
        // Convert the URL type and to a null terminated wchar string
1044 6
        $url .= "\0";
1045
1046
        // character count
1047 6
        $url_len = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($url);
1048 6
        $url_len = pack('V', $url_len);
1049
1050 6
        $url = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::convertEncoding($url, 'UTF-16LE', 'UTF-8');
1051
1052
        // Calculate the data length
1053 6
        $length = 0x24 + strlen($url);
1054
1055
        // Pack the header data
1056 6
        $header = pack('vv', $record, $length);
1057 6
        $data = pack('vvvv', $row1, $row2, $col1, $col2);
1058
1059
        // Write the packed data
1060 6
        $this->append($header . $data . $unknown1 . $options . $url_len . $url);
1061
1062 6
        return 0;
1063
    }
1064
1065
    /**
1066
     * Write links to external directory names such as 'c:\foo.xls',
1067
     * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'.
1068
     *
1069
     * Note: Excel writes some relative links with the $dir_long string. We ignore
1070
     * these cases for the sake of simpler code.
1071
     *
1072
     * @see writeUrl()
1073
     * @param int $row1   Start row
1074
     * @param int $col1   Start column
1075
     * @param int $row2   End row
1076
     * @param int $col2   End column
1077
     * @param string  $url    URL string
1078
     * @return int
1079
     */
1080
    public function writeUrlExternal($row1, $col1, $row2, $col2, $url)
1081
    {
1082
        // Network drives are different. We will handle them separately
1083
        // MS/Novell network drives and shares start with \\
1084
        if (preg_match('[^external:\\\\]', $url)) {
1085
            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...
1086
        }
1087
1088
        $record = 0x01B8; // Record identifier
1089
        $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...
1090
1091
        // Strip URL type and change Unix dir separator to Dos style (if needed)
1092
        //
1093
        $url = preg_replace('/^external:/', '', $url);
1094
        $url = preg_replace('/\//', '\\', $url);
1095
1096
        // Determine if the link is relative or absolute:
1097
        //   relative if link contains no dir separator, "somefile.xls"
1098
        //   relative if link starts with up-dir, "..\..\somefile.xls"
1099
        //   otherwise, absolute
1100
1101
        $absolute = 0x00; // relative path
1102
        if (preg_match('/^[A-Z]:/', $url)) {
1103
            $absolute = 0x02; // absolute path on Windows, e.g. C:\...
1104
        }
1105
        $link_type = 0x01 | $absolute;
1106
1107
        // Determine if the link contains a sheet reference and change some of the
1108
        // parameters accordingly.
1109
        // Split the dir name and sheet name (if it exists)
1110
        $dir_long = $url;
1111
        if (preg_match("/\#/", $url)) {
1112
            $link_type |= 0x08;
1113
        }
1114
1115
        // Pack the link type
1116
        $link_type = pack('V', $link_type);
1117
1118
        // Calculate the up-level dir count e.g.. (..\..\..\ == 3)
1119
        $up_count = preg_match_all("/\.\.\\\/", $dir_long, $useless);
1120
        $up_count = pack('v', $up_count);
1121
1122
        // Store the short dos dir name (null terminated)
1123
        $dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0";
1124
1125
        // Store the long dir name as a wchar string (non-null terminated)
1126
        $dir_long = $dir_long . "\0";
1127
1128
        // Pack the lengths of the dir strings
1129
        $dir_short_len = pack('V', strlen($dir_short));
1130
        $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...
1131
        $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...
1132
1133
        // Pack the undocumented parts of the hyperlink stream
1134
        $unknown1 = pack('H*', 'D0C9EA79F9BACE118C8200AA004BA90B02000000');
1135
        $unknown2 = pack('H*', '0303000000000000C000000000000046');
1136
        $unknown3 = pack('H*', 'FFFFADDE000000000000000000000000000000000000000');
1137
        $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...
1138
1139
        // Pack the main data stream
1140
        $data = pack('vvvv', $row1, $row2, $col1, $col2) .
1141
                          $unknown1 .
1142
                          $link_type .
1143
                          $unknown2 .
1144
                          $up_count .
1145
                          $dir_short_len .
1146
                          $dir_short .
1147
                          $unknown3 .
1148
                          $stream_len; /*.
1149
                          $dir_long_len .
1150
                          $unknown4     .
1151
                          $dir_long     .
1152
                          $sheet_len    .
1153
                          $sheet        ;*/
1154
1155
        // Pack the header data
1156
        $length = strlen($data);
1157
        $header = pack('vv', $record, $length);
1158
1159
        // Write the packed data
1160
        $this->append($header . $data);
1161
1162
        return 0;
1163
    }
1164
1165
    /**
1166
     * This method is used to set the height and format for a row.
1167
     *
1168
     * @param int $row    The row to set
1169
     * @param int $height Height we are giving to the row.
1170
     *                        Use null to set XF without setting height
1171
     * @param int $xfIndex  The optional cell style Xf index to apply to the columns
1172
     * @param bool    $hidden The optional hidden attribute
1173
     * @param int $level  The optional outline level for row, in range [0,7]
1174
     */
1175 37
    private function writeRow($row, $height, $xfIndex, $hidden = false, $level = 0)
1176
    {
1177 37
        $record = 0x0208; // Record identifier
1178 37
        $length = 0x0010; // Number of bytes to follow
1179
1180 37
        $colMic = 0x0000; // First defined column
1181 37
        $colMac = 0x0000; // Last defined column
1182 37
        $irwMac = 0x0000; // Used by Excel to optimise loading
1183 37
        $reserved = 0x0000; // Reserved
1184 37
        $grbit = 0x0000; // Option flags
1185 37
        $ixfe = $xfIndex;
1186
1187 37
        if ($height < 0) {
1188 36
            $height = null;
1189
        }
1190
1191
        // Use writeRow($row, null, $XF) to set XF format without setting height
1192 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...
1193 6
            $miyRw = $height * 20; // row height
1194
        } else {
1195 36
            $miyRw = 0xff; // default row height is 256
1196
        }
1197
1198
        // Set the options flags. fUnsynced is used to show that the font and row
1199
        // heights are not compatible. This is usually the case for WriteExcel.
1200
        // The collapsed flag 0x10 doesn't seem to be used to indicate that a row
1201
        // is collapsed. Instead it is used to indicate that the previous row is
1202
        // collapsed. The zero height flag, 0x20, is used to collapse a row.
1203
1204 37
        $grbit |= $level;
1205 37
        if ($hidden) {
1206 2
            $grbit |= 0x0030;
1207
        }
1208 37
        if ($height !== null) {
1209 6
            $grbit |= 0x0040; // fUnsynced
1210
        }
1211 37
        if ($xfIndex !== 0xF) {
1212
            $grbit |= 0x0080;
1213
        }
1214 37
        $grbit |= 0x0100;
1215
1216 37
        $header = pack('vv', $record, $length);
1217 37
        $data = pack('vvvvvvvv', $row, $colMic, $colMac, $miyRw, $irwMac, $reserved, $grbit, $ixfe);
1218 37
        $this->append($header . $data);
1219 37
    }
1220
1221
    /**
1222
     * Writes Excel DIMENSIONS to define the area in which there is data.
1223
     */
1224 38
    private function writeDimensions()
1225
    {
1226 38
        $record = 0x0200; // Record identifier
1227
1228 38
        $length = 0x000E;
1229 38
        $data = pack('VVvvv', $this->firstRowIndex, $this->lastRowIndex + 1, $this->firstColumnIndex, $this->lastColumnIndex + 1, 0x0000); // reserved
1230
1231 38
        $header = pack('vv', $record, $length);
1232 38
        $this->append($header . $data);
1233 38
    }
1234
1235
    /**
1236
     * Write BIFF record Window2.
1237
     */
1238 38
    private function writeWindow2()
1239
    {
1240 38
        $record = 0x023E; // Record identifier
1241 38
        $length = 0x0012;
1242
1243 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...
1244 38
        $rwTop = 0x0000; // Top row visible in window
1245 38
        $colLeft = 0x0000; // Leftmost column visible in window
1246
1247
        // The options flags that comprise $grbit
1248 38
        $fDspFmla = 0; // 0 - bit
1249 38
        $fDspGrid = $this->phpSheet->getShowGridlines() ? 1 : 0; // 1
1250 38
        $fDspRwCol = $this->phpSheet->getShowRowColHeaders() ? 1 : 0; // 2
1251 38
        $fFrozen = $this->phpSheet->getFreezePane() ? 1 : 0; // 3
1252 38
        $fDspZeros = 1; // 4
1253 38
        $fDefaultHdr = 1; // 5
1254 38
        $fArabic = $this->phpSheet->getRightToLeft() ? 1 : 0; // 6
1255 38
        $fDspGuts = $this->outlineOn; // 7
1256 38
        $fFrozenNoSplit = 0; // 0 - bit
1257
        // no support in PhpSpreadsheet for selected sheet, therefore sheet is only selected if it is the active sheet
1258 38
        $fSelected = ($this->phpSheet === $this->phpSheet->getParent()->getActiveSheet()) ? 1 : 0;
1259 38
        $fPaged = 1; // 2
1260 38
        $fPageBreakPreview = $this->phpSheet->getSheetView()->getView() === \PhpOffice\PhpSpreadsheet\Worksheet\SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW;
1261
1262 38
        $grbit = $fDspFmla;
1263 38
        $grbit |= $fDspGrid << 1;
1264 38
        $grbit |= $fDspRwCol << 2;
1265 38
        $grbit |= $fFrozen << 3;
1266 38
        $grbit |= $fDspZeros << 4;
1267 38
        $grbit |= $fDefaultHdr << 5;
1268 38
        $grbit |= $fArabic << 6;
1269 38
        $grbit |= $fDspGuts << 7;
1270 38
        $grbit |= $fFrozenNoSplit << 8;
1271 38
        $grbit |= $fSelected << 9;
1272 38
        $grbit |= $fPaged << 10;
1273 38
        $grbit |= $fPageBreakPreview << 11;
1274
1275 38
        $header = pack('vv', $record, $length);
1276 38
        $data = pack('vvv', $grbit, $rwTop, $colLeft);
1277
1278
        // 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...
1279 38
        $rgbHdr = 0x0040; // Row/column heading and gridline color index
1280 38
        $zoom_factor_page_break = ($fPageBreakPreview ? $this->phpSheet->getSheetView()->getZoomScale() : 0x0000);
1281 38
        $zoom_factor_normal = $this->phpSheet->getSheetView()->getZoomScaleNormal();
1282
1283 38
        $data .= pack('vvvvV', $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000);
1284
1285 38
        $this->append($header . $data);
1286 38
    }
1287
1288
    /**
1289
     * Write BIFF record DEFAULTROWHEIGHT.
1290
     */
1291 38
    private function writeDefaultRowHeight()
1292
    {
1293 38
        $defaultRowHeight = $this->phpSheet->getDefaultRowDimension()->getRowHeight();
1294
1295 38
        if ($defaultRowHeight < 0) {
1296 35
            return;
1297
        }
1298
1299
        // convert to twips
1300 3
        $defaultRowHeight = (int) 20 * $defaultRowHeight;
1301
1302 3
        $record = 0x0225; // Record identifier
1303 3
        $length = 0x0004; // Number of bytes to follow
1304
1305 3
        $header = pack('vv', $record, $length);
1306 3
        $data = pack('vv', 1, $defaultRowHeight);
1307 3
        $this->append($header . $data);
1308 3
    }
1309
1310
    /**
1311
     * Write BIFF record DEFCOLWIDTH if COLINFO records are in use.
1312
     */
1313 38
    private function writeDefcol()
1314
    {
1315 38
        $defaultColWidth = 8;
1316
1317 38
        $record = 0x0055; // Record identifier
1318 38
        $length = 0x0002; // Number of bytes to follow
1319
1320 38
        $header = pack('vv', $record, $length);
1321 38
        $data = pack('v', $defaultColWidth);
1322 38
        $this->append($header . $data);
1323 38
    }
1324
1325
    /**
1326
     * Write BIFF record COLINFO to define column widths
1327
     *
1328
     * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C
1329
     * length record.
1330
     *
1331
     * @param array $col_array This is the only parameter received and is composed of the following:
1332
     *                0 => First formatted column,
1333
     *                1 => Last formatted column,
1334
     *                2 => Col width (8.43 is Excel default),
1335
     *                3 => The optional XF format of the column,
1336
     *                4 => Option flags.
1337
     *                5 => Optional outline level
1338
     */
1339 38
    private function writeColinfo($col_array)
1340
    {
1341 38
        if (isset($col_array[0])) {
1342 38
            $colFirst = $col_array[0];
1343
        }
1344 38
        if (isset($col_array[1])) {
1345 38
            $colLast = $col_array[1];
1346
        }
1347 38
        if (isset($col_array[2])) {
1348 38
            $coldx = $col_array[2];
1349
        } else {
1350
            $coldx = 8.43;
1351
        }
1352 38
        if (isset($col_array[3])) {
1353 38
            $xfIndex = $col_array[3];
1354
        } else {
1355
            $xfIndex = 15;
1356
        }
1357 38
        if (isset($col_array[4])) {
1358 38
            $grbit = $col_array[4];
1359
        } else {
1360
            $grbit = 0;
1361
        }
1362 38
        if (isset($col_array[5])) {
1363 38
            $level = $col_array[5];
1364
        } else {
1365
            $level = 0;
1366
        }
1367 38
        $record = 0x007D; // Record identifier
1368 38
        $length = 0x000C; // Number of bytes to follow
1369
1370 38
        $coldx *= 256; // Convert to units of 1/256 of a char
1371
1372 38
        $ixfe = $xfIndex;
1373 38
        $reserved = 0x0000; // Reserved
1374
1375 38
        $level = max(0, min($level, 7));
1376 38
        $grbit |= $level << 8;
1377
1378 38
        $header = pack('vv', $record, $length);
1379 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...
1380 38
        $this->append($header . $data);
1381 38
    }
1382
1383
    /**
1384
     * Write BIFF record SELECTION.
1385
     */
1386 38
    private function writeSelection()
1387
    {
1388
        // look up the selected cell range
1389 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...
1390 38
        $selectedCells = \PhpOffice\PhpSpreadsheet\Cell::splitRange($this->phpSheet->getSelectedCells());
1391 38
        $selectedCells = $selectedCells[0];
1392 38
        if (count($selectedCells) == 2) {
1393 13
            list($first, $last) = $selectedCells;
1394
        } else {
1395 31
            $first = $selectedCells[0];
1396 31
            $last = $selectedCells[0];
1397
        }
1398
1399 38
        list($colFirst, $rwFirst) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($first);
1400 38
        $colFirst = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($colFirst) - 1; // base 0 column index
1401 38
        --$rwFirst; // base 0 row index
1402
1403 38
        list($colLast, $rwLast) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($last);
1404 38
        $colLast = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($colLast) - 1; // base 0 column index
1405 38
        --$rwLast; // base 0 row index
1406
1407
        // make sure we are not out of bounds
1408 38
        $colFirst = min($colFirst, 255);
1409 38
        $colLast = min($colLast, 255);
1410
1411 38
        $rwFirst = min($rwFirst, 65535);
1412 38
        $rwLast = min($rwLast, 65535);
1413
1414 38
        $record = 0x001D; // Record identifier
1415 38
        $length = 0x000F; // Number of bytes to follow
1416
1417 38
        $pnn = $this->activePane; // Pane position
1418 38
        $rwAct = $rwFirst; // Active row
1419 38
        $colAct = $colFirst; // Active column
1420 38
        $irefAct = 0; // Active cell ref
1421 38
        $cref = 1; // Number of refs
1422
1423 38
        if (!isset($rwLast)) {
1424
            $rwLast = $rwFirst; // Last  row in reference
1425
        }
1426 38
        if (!isset($colLast)) {
1427
            $colLast = $colFirst; // Last  col in reference
1428
        }
1429
1430
        // Swap last row/col for first row/col as necessary
1431 38
        if ($rwFirst > $rwLast) {
1432
            list($rwFirst, $rwLast) = [$rwLast, $rwFirst];
1433
        }
1434
1435 38
        if ($colFirst > $colLast) {
1436
            list($colFirst, $colLast) = [$colLast, $colFirst];
1437
        }
1438
1439 38
        $header = pack('vv', $record, $length);
1440 38
        $data = pack('CvvvvvvCC', $pnn, $rwAct, $colAct, $irefAct, $cref, $rwFirst, $rwLast, $colFirst, $colLast);
1441 38
        $this->append($header . $data);
1442 38
    }
1443
1444
    /**
1445
     * Store the MERGEDCELLS records for all ranges of merged cells
1446
     */
1447 38
    private function writeMergedCells()
1448
    {
1449 38
        $mergeCells = $this->phpSheet->getMergeCells();
1450 38
        $countMergeCells = count($mergeCells);
1451
1452 38
        if ($countMergeCells == 0) {
1453 37
            return;
1454
        }
1455
1456
        // maximum allowed number of merged cells per record
1457 10
        $maxCountMergeCellsPerRecord = 1027;
1458
1459
        // record identifier
1460 10
        $record = 0x00E5;
1461
1462
        // counter for total number of merged cells treated so far by the writer
1463 10
        $i = 0;
1464
1465
        // counter for number of merged cells written in record currently being written
1466 10
        $j = 0;
1467
1468
        // initialize record data
1469 10
        $recordData = '';
1470
1471
        // loop through the merged cells
1472 10
        foreach ($mergeCells as $mergeCell) {
1473 10
            ++$i;
1474 10
            ++$j;
1475
1476
            // extract the row and column indexes
1477 10
            $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...
1478 10
            list($first, $last) = $range[0];
1479 10
            list($firstColumn, $firstRow) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($first);
1480 10
            list($lastColumn, $lastRow) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($last);
1481
1482 10
            $recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($firstColumn) - 1, \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($lastColumn) - 1);
1483
1484
            // flush record if we have reached limit for number of merged cells, or reached final merged cell
1485 10
            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...
1486 10
                $recordData = pack('v', $j) . $recordData;
1487 10
                $length = strlen($recordData);
1488 10
                $header = pack('vv', $record, $length);
1489 10
                $this->append($header . $recordData);
1490
1491
                // initialize for next record, if any
1492 10
                $recordData = '';
1493 10
                $j = 0;
1494
            }
1495
        }
1496 10
    }
1497
1498
    /**
1499
     * Write SHEETLAYOUT record
1500
     */
1501 38
    private function writeSheetLayout()
1502
    {
1503 38
        if (!$this->phpSheet->isTabColorSet()) {
1504 38
            return;
1505
        }
1506
1507 5
        $recordData = pack(
1508 5
            'vvVVVvv',
1509 5
            0x0862,
1510 5
            0x0000, // unused
1511 5
            0x00000000, // unused
1512 5
            0x00000000, // unused
1513 5
            0x00000014, // size of record data
1514 5
            $this->colors[$this->phpSheet->getTabColor()->getRGB()], // color index
1515 5
            0x0000        // unused
1516
        );
1517
1518 5
        $length = strlen($recordData);
1519
1520 5
        $record = 0x0862; // Record identifier
1521 5
        $header = pack('vv', $record, $length);
1522 5
        $this->append($header . $recordData);
1523 5
    }
1524
1525
    /**
1526
     * Write SHEETPROTECTION
1527
     */
1528 38
    private function writeSheetProtection()
1529
    {
1530
        // record identifier
1531 38
        $record = 0x0867;
1532
1533
        // prepare options
1534 38
        $options = (int) !$this->phpSheet->getProtection()->getObjects()
1535 38
                    | (int) !$this->phpSheet->getProtection()->getScenarios() << 1
1536 38
                    | (int) !$this->phpSheet->getProtection()->getFormatCells() << 2
1537 38
                    | (int) !$this->phpSheet->getProtection()->getFormatColumns() << 3
1538 38
                    | (int) !$this->phpSheet->getProtection()->getFormatRows() << 4
1539 38
                    | (int) !$this->phpSheet->getProtection()->getInsertColumns() << 5
1540 38
                    | (int) !$this->phpSheet->getProtection()->getInsertRows() << 6
1541 38
                    | (int) !$this->phpSheet->getProtection()->getInsertHyperlinks() << 7
1542 38
                    | (int) !$this->phpSheet->getProtection()->getDeleteColumns() << 8
1543 38
                    | (int) !$this->phpSheet->getProtection()->getDeleteRows() << 9
1544 38
                    | (int) !$this->phpSheet->getProtection()->getSelectLockedCells() << 10
1545 38
                    | (int) !$this->phpSheet->getProtection()->getSort() << 11
1546 38
                    | (int) !$this->phpSheet->getProtection()->getAutoFilter() << 12
1547 38
                    | (int) !$this->phpSheet->getProtection()->getPivotTables() << 13
1548 38
                    | (int) !$this->phpSheet->getProtection()->getSelectUnlockedCells() << 14;
1549
1550
        // record data
1551 38
        $recordData = pack(
1552 38
            'vVVCVVvv',
1553 38
            0x0867, // repeated record identifier
1554 38
            0x0000, // not used
1555 38
            0x0000, // not used
1556 38
            0x00, // not used
1557 38
            0x01000200, // unknown data
1558 38
            0xFFFFFFFF, // unknown data
1559
            $options, // options
1560 38
            0x0000 // not used
1561
        );
1562
1563 38
        $length = strlen($recordData);
1564 38
        $header = pack('vv', $record, $length);
1565
1566 38
        $this->append($header . $recordData);
1567 38
    }
1568
1569
    /**
1570
     * Write BIFF record RANGEPROTECTION
1571
     *
1572
     * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records
1573
     * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records
1574
     */
1575 38
    private function writeRangeProtection()
1576
    {
1577 38
        foreach ($this->phpSheet->getProtectedCells() as $range => $password) {
1578
            // number of ranges, e.g. 'A1:B3 C20:D25'
1579 5
            $cellRanges = explode(' ', $range);
1580 5
            $cref = count($cellRanges);
1581
1582 5
            $recordData = pack(
1583 5
                'vvVVvCVvVv',
1584 5
                0x0868,
1585 5
                0x00,
1586 5
                0x0000,
1587 5
                0x0000,
1588 5
                0x02,
1589 5
                0x0,
1590 5
                0x0000,
1591
                $cref,
1592 5
                0x0000,
1593 5
                0x00
1594
            );
1595
1596 5
            foreach ($cellRanges as $cellRange) {
1597 5
                $recordData .= $this->writeBIFF8CellRangeAddressFixed($cellRange);
1598
            }
1599
1600
            // the rgbFeat structure
1601 5
            $recordData .= pack(
1602 5
                'VV',
1603 5
                0x0000,
1604
                hexdec($password)
1605
            );
1606
1607 5
            $recordData .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong('p' . md5($recordData));
1608
1609 5
            $length = strlen($recordData);
1610
1611 5
            $record = 0x0868; // Record identifier
1612 5
            $header = pack('vv', $record, $length);
1613 5
            $this->append($header . $recordData);
1614
        }
1615 38
    }
1616
1617
    /**
1618
     * Write BIFF record EXTERNCOUNT to indicate the number of external sheet
1619
     * references in a worksheet.
1620
     *
1621
     * Excel only stores references to external sheets that are used in formulas.
1622
     * For simplicity we store references to all the sheets in the workbook
1623
     * regardless of whether they are used or not. This reduces the overall
1624
     * complexity and eliminates the need for a two way dialogue between the formula
1625
     * parser the worksheet objects.
1626
     *
1627
     * @param int $count The number of external sheet references in this worksheet
1628
     */
1629 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...
1630
    {
1631
        $record = 0x0016; // Record identifier
1632
        $length = 0x0002; // Number of bytes to follow
1633
1634
        $header = pack('vv', $record, $length);
1635
        $data = pack('v', $count);
1636
        $this->append($header . $data);
1637
    }
1638
1639
    /**
1640
     * Writes the Excel BIFF EXTERNSHEET record. These references are used by
1641
     * formulas. A formula references a sheet name via an index. Since we store a
1642
     * reference to all of the external worksheets the EXTERNSHEET index is the same
1643
     * as the worksheet index.
1644
     *
1645
     * @param string $sheetname The name of a external worksheet
1646
     */
1647
    private function writeExternsheet($sheetname)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
1648
    {
1649
        $record = 0x0017; // Record identifier
1650
1651
        // References to the current sheet are encoded differently to references to
1652
        // external sheets.
1653
        //
1654
        if ($this->phpSheet->getTitle() == $sheetname) {
1655
            $sheetname = '';
1656
            $length = 0x02; // The following 2 bytes
1657
            $cch = 1; // The following byte
1658
            $rgch = 0x02; // Self reference
1659
        } else {
1660
            $length = 0x02 + strlen($sheetname);
1661
            $cch = strlen($sheetname);
1662
            $rgch = 0x03; // Reference to a sheet in the current workbook
1663
        }
1664
1665
        $header = pack('vv', $record, $length);
1666
        $data = pack('CC', $cch, $rgch);
1667
        $this->append($header . $data . $sheetname);
1668
    }
1669
1670
    /**
1671
     * Writes the Excel BIFF PANE record.
1672
     * The panes can either be frozen or thawed (unfrozen).
1673
     * Frozen panes are specified in terms of an integer number of rows and columns.
1674
     * Thawed panes are specified in terms of Excel's units for rows and columns.
1675
     */
1676 3
    private function writePanes()
1677
    {
1678 3
        $panes = [];
1679 3
        if ($freezePane = $this->phpSheet->getFreezePane()) {
1680 3
            list($column, $row) = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($freezePane);
1681 3
            $panes[0] = $row - 1;
1682 3
            $panes[1] = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($column) - 1;
1683
        } else {
1684
            // thaw panes
1685
            return;
1686
        }
1687
1688 3
        $y = isset($panes[0]) ? $panes[0] : null;
1689 3
        $x = isset($panes[1]) ? $panes[1] : null;
1690 3
        $rwTop = isset($panes[2]) ? $panes[2] : null;
1691 3
        $colLeft = isset($panes[3]) ? $panes[3] : null;
1692 3
        if (count($panes) > 4) { // if Active pane was received
1693
            $pnnAct = $panes[4];
1694
        } else {
1695 3
            $pnnAct = null;
1696
        }
1697 3
        $record = 0x0041; // Record identifier
1698 3
        $length = 0x000A; // Number of bytes to follow
1699
1700
        // Code specific to frozen or thawed panes.
1701 3
        if ($this->phpSheet->getFreezePane()) {
1702
            // 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...
1703 3
            if (!isset($rwTop)) {
1704 3
                $rwTop = $y;
1705
            }
1706 3
            if (!isset($colLeft)) {
1707 3
                $colLeft = $x;
1708
            }
1709
        } else {
1710
            // 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...
1711
            if (!isset($rwTop)) {
1712
                $rwTop = 0;
1713
            }
1714
            if (!isset($colLeft)) {
1715
                $colLeft = 0;
1716
            }
1717
1718
            // Convert Excel's row and column units to the internal units.
1719
            // The default row height is 12.75
1720
            // The default column width is 8.43
1721
            // The following slope and intersection values were interpolated.
1722
            //
1723
            $y = 20 * $y + 255;
1724
            $x = 113.879 * $x + 390;
1725
        }
1726
1727
        // Determine which pane should be active. There is also the undocumented
1728
        // option to override this should it be necessary: may be removed later.
1729
        //
1730 3
        if (!isset($pnnAct)) {
1731 3
            if ($x != 0 && $y != 0) {
1732
                $pnnAct = 0; // Bottom right
1733
            }
1734 3
            if ($x != 0 && $y == 0) {
1735
                $pnnAct = 1; // Top right
1736
            }
1737 3
            if ($x == 0 && $y != 0) {
1738 3
                $pnnAct = 2; // Bottom left
1739
            }
1740 3
            if ($x == 0 && $y == 0) {
1741
                $pnnAct = 3; // Top left
1742
            }
1743
        }
1744
1745 3
        $this->activePane = $pnnAct; // Used in writeSelection
1746
1747 3
        $header = pack('vv', $record, $length);
1748 3
        $data = pack('vvvvv', $x, $y, $rwTop, $colLeft, $pnnAct);
1749 3
        $this->append($header . $data);
1750 3
    }
1751
1752
    /**
1753
     * Store the page setup SETUP BIFF record.
1754
     */
1755 38
    private function writeSetup()
1756
    {
1757 38
        $record = 0x00A1; // Record identifier
1758 38
        $length = 0x0022; // Number of bytes to follow
1759
1760 38
        $iPaperSize = $this->phpSheet->getPageSetup()->getPaperSize(); // Paper size
1761
1762 38
        $iScale = $this->phpSheet->getPageSetup()->getScale() ?
1763 38
            $this->phpSheet->getPageSetup()->getScale() : 100; // Print scaling factor
1764
1765 38
        $iPageStart = 0x01; // Starting page number
1766 38
        $iFitWidth = (int) $this->phpSheet->getPageSetup()->getFitToWidth(); // Fit to number of pages wide
1767 38
        $iFitHeight = (int) $this->phpSheet->getPageSetup()->getFitToHeight(); // Fit to number of pages high
1768 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...
1769 38
        $iRes = 0x0258; // Print resolution
1770 38
        $iVRes = 0x0258; // Vertical print resolution
1771
1772 38
        $numHdr = $this->phpSheet->getPageMargins()->getHeader(); // Header Margin
1773
1774 38
        $numFtr = $this->phpSheet->getPageMargins()->getFooter(); // Footer Margin
1775 38
        $iCopies = 0x01; // Number of copies
1776
1777 38
        $fLeftToRight = 0x0; // Print over then down
1778
1779
        // Page orientation
1780 38
        $fLandscape = ($this->phpSheet->getPageSetup()->getOrientation() == \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE) ?
1781 38
            0x0 : 0x1;
1782
1783 38
        $fNoPls = 0x0; // Setup not read from printer
1784 38
        $fNoColor = 0x0; // Print black and white
1785 38
        $fDraft = 0x0; // Print draft quality
1786 38
        $fNotes = 0x0; // Print notes
1787 38
        $fNoOrient = 0x0; // Orientation not set
1788 38
        $fUsePage = 0x0; // Use custom starting page
1789
1790 38
        $grbit = $fLeftToRight;
1791 38
        $grbit |= $fLandscape << 1;
1792 38
        $grbit |= $fNoPls << 2;
1793 38
        $grbit |= $fNoColor << 3;
1794 38
        $grbit |= $fDraft << 4;
1795 38
        $grbit |= $fNotes << 5;
1796 38
        $grbit |= $fNoOrient << 6;
1797 38
        $grbit |= $fUsePage << 7;
1798
1799 38
        $numHdr = pack('d', $numHdr);
1800 38
        $numFtr = pack('d', $numFtr);
1801 38
        if (self::getByteOrder()) { // if it's Big Endian
1802
            $numHdr = strrev($numHdr);
1803
            $numFtr = strrev($numFtr);
1804
        }
1805
1806 38
        $header = pack('vv', $record, $length);
1807 38
        $data1 = pack('vvvvvvvv', $iPaperSize, $iScale, $iPageStart, $iFitWidth, $iFitHeight, $grbit, $iRes, $iVRes);
1808 38
        $data2 = $numHdr . $numFtr;
1809 38
        $data3 = pack('v', $iCopies);
1810 38
        $this->append($header . $data1 . $data2 . $data3);
1811 38
    }
1812
1813
    /**
1814
     * Store the header caption BIFF record.
1815
     */
1816 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...
1817
    {
1818 38
        $record = 0x0014; // Record identifier
1819
1820
        /* 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...
1821
        // need to fix character count (multibyte!)
1822
        if (strlen($this->phpSheet->getHeaderFooter()->getOddHeader()) <= 255) {
1823
            $str      = $this->phpSheet->getHeaderFooter()->getOddHeader();       // header string
1824
        } else {
1825
            $str = '';
1826
        }
1827
        */
1828
1829 38
        $recordData = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($this->phpSheet->getHeaderFooter()->getOddHeader());
1830 38
        $length = strlen($recordData);
1831
1832 38
        $header = pack('vv', $record, $length);
1833
1834 38
        $this->append($header . $recordData);
1835 38
    }
1836
1837
    /**
1838
     * Store the footer caption BIFF record.
1839
     */
1840 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...
1841
    {
1842 38
        $record = 0x0015; // Record identifier
1843
1844
        /* 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...
1845
        // need to fix character count (multibyte!)
1846
        if (strlen($this->phpSheet->getHeaderFooter()->getOddFooter()) <= 255) {
1847
            $str = $this->phpSheet->getHeaderFooter()->getOddFooter();
1848
        } else {
1849
            $str = '';
1850
        }
1851
        */
1852
1853 38
        $recordData = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($this->phpSheet->getHeaderFooter()->getOddFooter());
1854 38
        $length = strlen($recordData);
1855
1856 38
        $header = pack('vv', $record, $length);
1857
1858 38
        $this->append($header . $recordData);
1859 38
    }
1860
1861
    /**
1862
     * Store the horizontal centering HCENTER BIFF record.
1863
     */
1864 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...
1865
    {
1866 38
        $record = 0x0083; // Record identifier
1867 38
        $length = 0x0002; // Bytes to follow
1868
1869 38
        $fHCenter = $this->phpSheet->getPageSetup()->getHorizontalCentered() ? 1 : 0; // Horizontal centering
1870
1871 38
        $header = pack('vv', $record, $length);
1872 38
        $data = pack('v', $fHCenter);
1873
1874 38
        $this->append($header . $data);
1875 38
    }
1876
1877
    /**
1878
     * Store the vertical centering VCENTER BIFF record.
1879
     */
1880 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...
1881
    {
1882 38
        $record = 0x0084; // Record identifier
1883 38
        $length = 0x0002; // Bytes to follow
1884
1885 38
        $fVCenter = $this->phpSheet->getPageSetup()->getVerticalCentered() ? 1 : 0; // Horizontal centering
1886
1887 38
        $header = pack('vv', $record, $length);
1888 38
        $data = pack('v', $fVCenter);
1889 38
        $this->append($header . $data);
1890 38
    }
1891
1892
    /**
1893
     * Store the LEFTMARGIN BIFF record.
1894
     */
1895 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...
1896
    {
1897 38
        $record = 0x0026; // Record identifier
1898 38
        $length = 0x0008; // Bytes to follow
1899
1900 38
        $margin = $this->phpSheet->getPageMargins()->getLeft(); // Margin in inches
1901
1902 38
        $header = pack('vv', $record, $length);
1903 38
        $data = pack('d', $margin);
1904 38
        if (self::getByteOrder()) { // if it's Big Endian
1905
            $data = strrev($data);
1906
        }
1907
1908 38
        $this->append($header . $data);
1909 38
    }
1910
1911
    /**
1912
     * Store the RIGHTMARGIN BIFF record.
1913
     */
1914 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...
1915
    {
1916 38
        $record = 0x0027; // Record identifier
1917 38
        $length = 0x0008; // Bytes to follow
1918
1919 38
        $margin = $this->phpSheet->getPageMargins()->getRight(); // Margin in inches
1920
1921 38
        $header = pack('vv', $record, $length);
1922 38
        $data = pack('d', $margin);
1923 38
        if (self::getByteOrder()) { // if it's Big Endian
1924
            $data = strrev($data);
1925
        }
1926
1927 38
        $this->append($header . $data);
1928 38
    }
1929
1930
    /**
1931
     * Store the TOPMARGIN BIFF record.
1932
     */
1933 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...
1934
    {
1935 38
        $record = 0x0028; // Record identifier
1936 38
        $length = 0x0008; // Bytes to follow
1937
1938 38
        $margin = $this->phpSheet->getPageMargins()->getTop(); // Margin in inches
1939
1940 38
        $header = pack('vv', $record, $length);
1941 38
        $data = pack('d', $margin);
1942 38
        if (self::getByteOrder()) { // if it's Big Endian
1943
            $data = strrev($data);
1944
        }
1945
1946 38
        $this->append($header . $data);
1947 38
    }
1948
1949
    /**
1950
     * Store the BOTTOMMARGIN BIFF record.
1951
     */
1952 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...
1953
    {
1954 38
        $record = 0x0029; // Record identifier
1955 38
        $length = 0x0008; // Bytes to follow
1956
1957 38
        $margin = $this->phpSheet->getPageMargins()->getBottom(); // Margin in inches
1958
1959 38
        $header = pack('vv', $record, $length);
1960 38
        $data = pack('d', $margin);
1961 38
        if (self::getByteOrder()) { // if it's Big Endian
1962
            $data = strrev($data);
1963
        }
1964
1965 38
        $this->append($header . $data);
1966 38
    }
1967
1968
    /**
1969
     * Write the PRINTHEADERS BIFF record.
1970
     */
1971 38
    private function writePrintHeaders()
1972
    {
1973 38
        $record = 0x002a; // Record identifier
1974 38
        $length = 0x0002; // Bytes to follow
1975
1976 38
        $fPrintRwCol = $this->_print_headers; // Boolean flag
1977
1978 38
        $header = pack('vv', $record, $length);
1979 38
        $data = pack('v', $fPrintRwCol);
1980 38
        $this->append($header . $data);
1981 38
    }
1982
1983
    /**
1984
     * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the
1985
     * GRIDSET record.
1986
     */
1987 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...
1988
    {
1989 38
        $record = 0x002b; // Record identifier
1990 38
        $length = 0x0002; // Bytes to follow
1991
1992 38
        $fPrintGrid = $this->phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag
1993
1994 38
        $header = pack('vv', $record, $length);
1995 38
        $data = pack('v', $fPrintGrid);
1996 38
        $this->append($header . $data);
1997 38
    }
1998
1999
    /**
2000
     * Write the GRIDSET BIFF record. Must be used in conjunction with the
2001
     * PRINTGRIDLINES record.
2002
     */
2003 38
    private function writeGridset()
2004
    {
2005 38
        $record = 0x0082; // Record identifier
2006 38
        $length = 0x0002; // Bytes to follow
2007
2008 38
        $fGridSet = !$this->phpSheet->getPrintGridlines(); // Boolean flag
2009
2010 38
        $header = pack('vv', $record, $length);
2011 38
        $data = pack('v', $fGridSet);
2012 38
        $this->append($header . $data);
2013 38
    }
2014
2015
    /**
2016
     * Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet.
2017
     */
2018 3
    private function writeAutoFilterInfo()
2019
    {
2020 3
        $record = 0x009D; // Record identifier
2021 3
        $length = 0x0002; // Bytes to follow
2022
2023 3
        $rangeBounds = \PhpOffice\PhpSpreadsheet\Cell::rangeBoundaries($this->phpSheet->getAutoFilter()->getRange());
2024 3
        $iNumFilters = 1 + $rangeBounds[1][0] - $rangeBounds[0][0];
2025
2026 3
        $header = pack('vv', $record, $length);
2027 3
        $data = pack('v', $iNumFilters);
2028 3
        $this->append($header . $data);
2029 3
    }
2030
2031
    /**
2032
     * Write the GUTS BIFF record. This is used to configure the gutter margins
2033
     * where Excel outline symbols are displayed. The visibility of the gutters is
2034
     * controlled by a flag in WSBOOL.
2035
     *
2036
     * @see writeWsbool()
2037
     */
2038 38
    private function writeGuts()
2039
    {
2040 38
        $record = 0x0080; // Record identifier
2041 38
        $length = 0x0008; // Bytes to follow
2042
2043 38
        $dxRwGut = 0x0000; // Size of row gutter
2044 38
        $dxColGut = 0x0000; // Size of col gutter
2045
2046
        // determine maximum row outline level
2047 38
        $maxRowOutlineLevel = 0;
2048 38
        foreach ($this->phpSheet->getRowDimensions() as $rowDimension) {
2049 37
            $maxRowOutlineLevel = max($maxRowOutlineLevel, $rowDimension->getOutlineLevel());
2050
        }
2051
2052 38
        $col_level = 0;
2053
2054
        // Calculate the maximum column outline level. The equivalent calculation
2055
        // for the row outline level is carried out in writeRow().
2056 38
        $colcount = count($this->columnInfo);
2057 38
        for ($i = 0; $i < $colcount; ++$i) {
2058 38
            $col_level = max($this->columnInfo[$i][5], $col_level);
2059
        }
2060
2061
        // Set the limits for the outline levels (0 <= x <= 7).
2062 38
        $col_level = max(0, min($col_level, 7));
2063
2064
        // The displayed level is one greater than the max outline levels
2065 38
        if ($maxRowOutlineLevel) {
2066
            ++$maxRowOutlineLevel;
2067
        }
2068 38
        if ($col_level) {
2069 1
            ++$col_level;
2070
        }
2071
2072 38
        $header = pack('vv', $record, $length);
2073 38
        $data = pack('vvvv', $dxRwGut, $dxColGut, $maxRowOutlineLevel, $col_level);
2074
2075 38
        $this->append($header . $data);
2076 38
    }
2077
2078
    /**
2079
     * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction
2080
     * with the SETUP record.
2081
     */
2082 38
    private function writeWsbool()
2083
    {
2084 38
        $record = 0x0081; // Record identifier
2085 38
        $length = 0x0002; // Bytes to follow
2086 38
        $grbit = 0x0000;
2087
2088
        // The only option that is of interest is the flag for fit to page. So we
2089
        // set all the options in one go.
2090
        //
2091
        // Set the option flags
2092 38
        $grbit |= 0x0001; // Auto page breaks visible
2093 38
        if ($this->outlineStyle) {
2094
            $grbit |= 0x0020; // Auto outline styles
2095
        }
2096 38
        if ($this->phpSheet->getShowSummaryBelow()) {
2097 38
            $grbit |= 0x0040; // Outline summary below
2098
        }
2099 38
        if ($this->phpSheet->getShowSummaryRight()) {
2100 38
            $grbit |= 0x0080; // Outline summary right
2101
        }
2102 38
        if ($this->phpSheet->getPageSetup()->getFitToPage()) {
2103
            $grbit |= 0x0100; // Page setup fit to page
2104
        }
2105 38
        if ($this->outlineOn) {
2106 38
            $grbit |= 0x0400; // Outline symbols displayed
2107
        }
2108
2109 38
        $header = pack('vv', $record, $length);
2110 38
        $data = pack('v', $grbit);
2111 38
        $this->append($header . $data);
2112 38
    }
2113
2114
    /**
2115
     * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records.
2116
     */
2117 38
    private function writeBreaks()
2118
    {
2119
        // initialize
2120 38
        $vbreaks = [];
2121 38
        $hbreaks = [];
2122
2123 38
        foreach ($this->phpSheet->getBreaks() as $cell => $breakType) {
2124
            // Fetch coordinates
2125 1
            $coordinates = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($cell);
2126
2127
            // Decide what to do by the type of break
2128
            switch ($breakType) {
2129 1
                case \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_COLUMN:
2130
                    // Add to list of vertical breaks
2131
                    $vbreaks[] = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($coordinates[0]) - 1;
2132
                    break;
2133 1
                case \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_ROW:
2134
                    // Add to list of horizontal breaks
2135 1
                    $hbreaks[] = $coordinates[1];
2136 1
                    break;
2137
                case \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_NONE:
2138
                default:
2139
                    // Nothing to do
2140 1
                    break;
2141
            }
2142
        }
2143
2144
        //horizontal page breaks
2145 38
        if (!empty($hbreaks)) {
2146
            // Sort and filter array of page breaks
2147 1
            sort($hbreaks, SORT_NUMERIC);
2148 1
            if ($hbreaks[0] == 0) { // don't use first break if it's 0
2149
                array_shift($hbreaks);
2150
            }
2151
2152 1
            $record = 0x001b; // Record identifier
2153 1
            $cbrk = count($hbreaks); // Number of page breaks
2154 1
            $length = 2 + 6 * $cbrk; // Bytes to follow
2155
2156 1
            $header = pack('vv', $record, $length);
2157 1
            $data = pack('v', $cbrk);
2158
2159
            // Append each page break
2160 1
            foreach ($hbreaks as $hbreak) {
2161 1
                $data .= pack('vvv', $hbreak, 0x0000, 0x00ff);
2162
            }
2163
2164 1
            $this->append($header . $data);
2165
        }
2166
2167
        // vertical page breaks
2168 38
        if (!empty($vbreaks)) {
2169
            // 1000 vertical pagebreaks appears to be an internal Excel 5 limit.
2170
            // It is slightly higher in Excel 97/200, approx. 1026
2171
            $vbreaks = array_slice($vbreaks, 0, 1000);
2172
2173
            // Sort and filter array of page breaks
2174
            sort($vbreaks, SORT_NUMERIC);
2175
            if ($vbreaks[0] == 0) { // don't use first break if it's 0
2176
                array_shift($vbreaks);
2177
            }
2178
2179
            $record = 0x001a; // Record identifier
2180
            $cbrk = count($vbreaks); // Number of page breaks
2181
            $length = 2 + 6 * $cbrk; // Bytes to follow
2182
2183
            $header = pack('vv', $record, $length);
2184
            $data = pack('v', $cbrk);
2185
2186
            // Append each page break
2187
            foreach ($vbreaks as $vbreak) {
2188
                $data .= pack('vvv', $vbreak, 0x0000, 0xffff);
2189
            }
2190
2191
            $this->append($header . $data);
2192
        }
2193 38
    }
2194
2195
    /**
2196
     * Set the Biff PROTECT record to indicate that the worksheet is protected.
2197
     */
2198 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...
2199
    {
2200
        // Exit unless sheet protection has been specified
2201 38
        if (!$this->phpSheet->getProtection()->getSheet()) {
2202 36
            return;
2203
        }
2204
2205 7
        $record = 0x0012; // Record identifier
2206 7
        $length = 0x0002; // Bytes to follow
2207
2208 7
        $fLock = 1; // Worksheet is protected
2209
2210 7
        $header = pack('vv', $record, $length);
2211 7
        $data = pack('v', $fLock);
2212
2213 7
        $this->append($header . $data);
2214 7
    }
2215
2216
    /**
2217
     * Write SCENPROTECT
2218
     */
2219 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...
2220
    {
2221
        // Exit if sheet protection is not active
2222 38
        if (!$this->phpSheet->getProtection()->getSheet()) {
2223 36
            return;
2224
        }
2225
2226
        // Exit if scenarios are not protected
2227 7
        if (!$this->phpSheet->getProtection()->getScenarios()) {
2228 7
            return;
2229
        }
2230
2231
        $record = 0x00DD; // Record identifier
2232
        $length = 0x0002; // Bytes to follow
2233
2234
        $header = pack('vv', $record, $length);
2235
        $data = pack('v', 1);
2236
2237
        $this->append($header . $data);
2238
    }
2239
2240
    /**
2241
     * Write OBJECTPROTECT
2242
     */
2243 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...
2244
    {
2245
        // Exit if sheet protection is not active
2246 38
        if (!$this->phpSheet->getProtection()->getSheet()) {
2247 36
            return;
2248
        }
2249
2250
        // Exit if objects are not protected
2251 7
        if (!$this->phpSheet->getProtection()->getObjects()) {
2252 7
            return;
2253
        }
2254
2255
        $record = 0x0063; // Record identifier
2256
        $length = 0x0002; // Bytes to follow
2257
2258
        $header = pack('vv', $record, $length);
2259
        $data = pack('v', 1);
2260
2261
        $this->append($header . $data);
2262
    }
2263
2264
    /**
2265
     * Write the worksheet PASSWORD record.
2266
     */
2267 38
    private function writePassword()
2268
    {
2269
        // Exit unless sheet protection and password have been specified
2270 38
        if (!$this->phpSheet->getProtection()->getSheet() || !$this->phpSheet->getProtection()->getPassword()) {
2271 37
            return;
2272
        }
2273
2274 1
        $record = 0x0013; // Record identifier
2275 1
        $length = 0x0002; // Bytes to follow
2276
2277 1
        $wPassword = hexdec($this->phpSheet->getProtection()->getPassword()); // Encoded password
2278
2279 1
        $header = pack('vv', $record, $length);
2280 1
        $data = pack('v', $wPassword);
2281
2282 1
        $this->append($header . $data);
2283 1
    }
2284
2285
    /**
2286
     * Insert a 24bit bitmap image in a worksheet.
2287
     *
2288
     * @param int $row     The row we are going to insert the bitmap into
2289
     * @param int $col     The column we are going to insert the bitmap into
2290
     * @param mixed   $bitmap  The bitmap filename or GD-image resource
2291
     * @param int $x       The horizontal position (offset) of the image inside the cell.
2292
     * @param int $y       The vertical position (offset) of the image inside the cell.
2293
     * @param float   $scale_x The horizontal scale
2294
     * @param float   $scale_y The vertical scale
2295
     */
2296
    public function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1)
2297
    {
2298
        $bitmap_array = (is_resource($bitmap) ? $this->processBitmapGd($bitmap) : $this->processBitmap($bitmap));
2299
        list($width, $height, $size, $data) = $bitmap_array;
2300
2301
        // Scale the frame of the image.
2302
        $width *= $scale_x;
2303
        $height *= $scale_y;
2304
2305
        // Calculate the vertices of the image and write the OBJ record
2306
        $this->positionImage($col, $row, $x, $y, $width, $height);
2307
2308
        // Write the IMDATA record to store the bitmap data
2309
        $record = 0x007f;
2310
        $length = 8 + $size;
2311
        $cf = 0x09;
2312
        $env = 0x01;
2313
        $lcb = $size;
2314
2315
        $header = pack('vvvvV', $record, $length, $cf, $env, $lcb);
2316
        $this->append($header . $data);
2317
    }
2318
2319
    /**
2320
     * Calculate the vertices that define the position of the image as required by
2321
     * the OBJ record.
2322
     *
2323
     *         +------------+------------+
2324
     *         |     A      |      B     |
2325
     *   +-----+------------+------------+
2326
     *   |     |(x1,y1)     |            |
2327
     *   |  1  |(A1)._______|______      |
2328
     *   |     |    |              |     |
2329
     *   |     |    |              |     |
2330
     *   +-----+----|    BITMAP    |-----+
2331
     *   |     |    |              |     |
2332
     *   |  2  |    |______________.     |
2333
     *   |     |            |        (B2)|
2334
     *   |     |            |     (x2,y2)|
2335
     *   +---- +------------+------------+
2336
     *
2337
     * Example of a bitmap that covers some of the area from cell A1 to cell B2.
2338
     *
2339
     * Based on the width and height of the bitmap we need to calculate 8 vars:
2340
     *     $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2.
2341
     * The width and height of the cells are also variable and have to be taken into
2342
     * account.
2343
     * The values of $col_start and $row_start are passed in from the calling
2344
     * function. The values of $col_end and $row_end are calculated by subtracting
2345
     * the width and height of the bitmap from the width and height of the
2346
     * underlying cells.
2347
     * The vertices are expressed as a percentage of the underlying cell width as
2348
     * follows (rhs values are in pixels):
2349
     *
2350
     *       x1 = X / W *1024
2351
     *       y1 = Y / H *256
2352
     *       x2 = (X-1) / W *1024
2353
     *       y2 = (Y-1) / H *256
2354
     *
2355
     *       Where:  X is distance from the left side of the underlying cell
2356
     *               Y is distance from the top of the underlying cell
2357
     *               W is the width of the cell
2358
     *               H is the height of the cell
2359
     * The SDK incorrectly states that the height should be expressed as a
2360
     *        percentage of 1024.
2361
     *
2362
     * @param int $col_start Col containing upper left corner of object
2363
     * @param int $row_start Row containing top left corner of object
2364
     * @param int $x1        Distance to left side of object
2365
     * @param int $y1        Distance to top of object
2366
     * @param int $width     Width of image frame
2367
     * @param int $height    Height of image frame
2368
     */
2369
    public function positionImage($col_start, $row_start, $x1, $y1, $width, $height)
2370
    {
2371
        // Initialise end cell to the same as the start cell
2372
        $col_end = $col_start; // Col containing lower right corner of object
2373
        $row_end = $row_start; // Row containing bottom right corner of object
2374
2375
        // Zero the specified offset if greater than the cell dimensions
2376
        if ($x1 >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_start))) {
2377
            $x1 = 0;
2378
        }
2379
        if ($y1 >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_start + 1)) {
2380
            $y1 = 0;
2381
        }
2382
2383
        $width = $width + $x1 - 1;
2384
        $height = $height + $y1 - 1;
2385
2386
        // Subtract the underlying cell widths to find the end cell of the image
2387
        while ($width >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end))) {
2388
            $width -= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end));
2389
            ++$col_end;
2390
        }
2391
2392
        // Subtract the underlying cell heights to find the end cell of the image
2393
        while ($height >= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1)) {
2394
            $height -= \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1);
2395
            ++$row_end;
2396
        }
2397
2398
        // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell
2399
        // with zero eight or width.
2400
        //
2401
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_start)) == 0) {
2402
            return;
2403
        }
2404
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end)) == 0) {
2405
            return;
2406
        }
2407
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_start + 1) == 0) {
2408
            return;
2409
        }
2410
        if (\PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1) == 0) {
2411
            return;
2412
        }
2413
2414
        // Convert the pixel values to the percentage value expected by Excel
2415
        $x1 = $x1 / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_start)) * 1024;
2416
        $y1 = $y1 / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_start + 1) * 256;
2417
        $x2 = $width / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeCol($this->phpSheet, \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object
2418
        $y2 = $height / \PhpOffice\PhpSpreadsheet\Shared\Xls::sizeRow($this->phpSheet, $row_end + 1) * 256; // Distance to bottom of object
2419
2420
        $this->writeObjPicture($col_start, $x1, $row_start, $y1, $col_end, $x2, $row_end, $y2);
2421
    }
2422
2423
    /**
2424
     * Store the OBJ record that precedes an IMDATA record. This could be generalise
2425
     * to support other Excel objects.
2426
     *
2427
     * @param int $colL Column containing upper left corner of object
2428
     * @param int $dxL  Distance from left side of cell
2429
     * @param int $rwT  Row containing top left corner of object
2430
     * @param int $dyT  Distance from top of cell
2431
     * @param int $colR Column containing lower right corner of object
2432
     * @param int $dxR  Distance from right of cell
2433
     * @param int $rwB  Row containing bottom right corner of object
2434
     * @param int $dyB  Distance from bottom of cell
2435
     */
2436
    private function writeObjPicture($colL, $dxL, $rwT, $dyT, $colR, $dxR, $rwB, $dyB)
2437
    {
2438
        $record = 0x005d; // Record identifier
2439
        $length = 0x003c; // Bytes to follow
2440
2441
        $cObj = 0x0001; // Count of objects in file (set to 1)
2442
        $OT = 0x0008; // Object type. 8 = Picture
2443
        $id = 0x0001; // Object ID
2444
        $grbit = 0x0614; // Option flags
2445
2446
        $cbMacro = 0x0000; // Length of FMLA structure
2447
        $Reserved1 = 0x0000; // Reserved
2448
        $Reserved2 = 0x0000; // Reserved
2449
2450
        $icvBack = 0x09; // Background colour
2451
        $icvFore = 0x09; // Foreground colour
2452
        $fls = 0x00; // Fill pattern
2453
        $fAuto = 0x00; // Automatic fill
2454
        $icv = 0x08; // Line colour
2455
        $lns = 0xff; // Line style
2456
        $lnw = 0x01; // Line weight
2457
        $fAutoB = 0x00; // Automatic border
2458
        $frs = 0x0000; // Frame style
2459
        $cf = 0x0009; // Image format, 9 = bitmap
2460
        $Reserved3 = 0x0000; // Reserved
2461
        $cbPictFmla = 0x0000; // Length of FMLA structure
2462
        $Reserved4 = 0x0000; // Reserved
2463
        $grbit2 = 0x0001; // Option flags
2464
        $Reserved5 = 0x0000; // Reserved
2465
2466
        $header = pack('vv', $record, $length);
2467
        $data = pack('V', $cObj);
2468
        $data .= pack('v', $OT);
2469
        $data .= pack('v', $id);
2470
        $data .= pack('v', $grbit);
2471
        $data .= pack('v', $colL);
2472
        $data .= pack('v', $dxL);
2473
        $data .= pack('v', $rwT);
2474
        $data .= pack('v', $dyT);
2475
        $data .= pack('v', $colR);
2476
        $data .= pack('v', $dxR);
2477
        $data .= pack('v', $rwB);
2478
        $data .= pack('v', $dyB);
2479
        $data .= pack('v', $cbMacro);
2480
        $data .= pack('V', $Reserved1);
2481
        $data .= pack('v', $Reserved2);
2482
        $data .= pack('C', $icvBack);
2483
        $data .= pack('C', $icvFore);
2484
        $data .= pack('C', $fls);
2485
        $data .= pack('C', $fAuto);
2486
        $data .= pack('C', $icv);
2487
        $data .= pack('C', $lns);
2488
        $data .= pack('C', $lnw);
2489
        $data .= pack('C', $fAutoB);
2490
        $data .= pack('v', $frs);
2491
        $data .= pack('V', $cf);
2492
        $data .= pack('v', $Reserved3);
2493
        $data .= pack('v', $cbPictFmla);
2494
        $data .= pack('v', $Reserved4);
2495
        $data .= pack('v', $grbit2);
2496
        $data .= pack('V', $Reserved5);
2497
2498
        $this->append($header . $data);
2499
    }
2500
2501
    /**
2502
     * Convert a GD-image into the internal format.
2503
     *
2504
     * @param resource $image The image to process
2505
     * @return array Array with data and properties of the bitmap
2506
     */
2507
    public function processBitmapGd($image)
2508
    {
2509
        $width = imagesx($image);
2510
        $height = imagesy($image);
2511
2512
        $data = pack('Vvvvv', 0x000c, $width, $height, 0x01, 0x18);
2513
        for ($j = $height; --$j;) {
2514
            for ($i = 0; $i < $width; ++$i) {
2515
                $color = imagecolorsforindex($image, imagecolorat($image, $i, $j));
2516
                foreach (['red', 'green', 'blue'] as $key) {
2517
                    $color[$key] = $color[$key] + round((255 - $color[$key]) * $color['alpha'] / 127);
2518
                }
2519
                $data .= chr($color['blue']) . chr($color['green']) . chr($color['red']);
2520
            }
2521
            if (3 * $width % 4) {
2522
                $data .= str_repeat("\x00", 4 - 3 * $width % 4);
2523
            }
2524
        }
2525
2526
        return [$width, $height, strlen($data), $data];
2527
    }
2528
2529
    /**
2530
     * Convert a 24 bit bitmap into the modified internal format used by Windows.
2531
     * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the
2532
     * MSDN library.
2533
     *
2534
     * @param string $bitmap The bitmap to process
2535
     * @return array Array with data and properties of the bitmap
2536
     */
2537
    public function processBitmap($bitmap)
2538
    {
2539
        // Open file.
2540
        $bmp_fd = @fopen($bitmap, 'rb');
2541
        if (!$bmp_fd) {
2542
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("Couldn't import $bitmap");
2543
        }
2544
2545
        // Slurp the file into a string.
2546
        $data = fread($bmp_fd, filesize($bitmap));
2547
2548
        // Check that the file is big enough to be a bitmap.
2549
        if (strlen($data) <= 0x36) {
2550
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap doesn't contain enough data.\n");
2551
        }
2552
2553
        // The first 2 bytes are used to identify the bitmap.
2554
        $identity = unpack('A2ident', $data);
2555
        if ($identity['ident'] != 'BM') {
2556
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap doesn't appear to be a valid bitmap image.\n");
2557
        }
2558
2559
        // Remove bitmap data: ID.
2560
        $data = substr($data, 2);
2561
2562
        // Read and remove the bitmap size. This is more reliable than reading
2563
        // the data size at offset 0x22.
2564
        //
2565
        $size_array = unpack('Vsa', substr($data, 0, 4));
2566
        $size = $size_array['sa'];
2567
        $data = substr($data, 4);
2568
        $size -= 0x36; // Subtract size of bitmap header.
2569
        $size += 0x0C; // Add size of BIFF header.
2570
2571
        // Remove bitmap data: reserved, offset, header length.
2572
        $data = substr($data, 12);
2573
2574
        // Read and remove the bitmap width and height. Verify the sizes.
2575
        $width_and_height = unpack('V2', substr($data, 0, 8));
2576
        $width = $width_and_height[1];
2577
        $height = $width_and_height[2];
2578
        $data = substr($data, 8);
2579
        if ($width > 0xFFFF) {
2580
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: largest image width supported is 65k.\n");
2581
        }
2582
        if ($height > 0xFFFF) {
2583
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: largest image height supported is 65k.\n");
2584
        }
2585
2586
        // Read and remove the bitmap planes and bpp data. Verify them.
2587
        $planes_and_bitcount = unpack('v2', substr($data, 0, 4));
2588
        $data = substr($data, 4);
2589
        if ($planes_and_bitcount[2] != 24) { // Bitcount
2590
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap isn't a 24bit true color bitmap.\n");
2591
        }
2592
        if ($planes_and_bitcount[1] != 1) {
2593
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: only 1 plane supported in bitmap image.\n");
2594
        }
2595
2596
        // Read and remove the bitmap compression. Verify compression.
2597
        $compression = unpack('Vcomp', substr($data, 0, 4));
2598
        $data = substr($data, 4);
2599
2600
        if ($compression['comp'] != 0) {
2601
            throw new \PhpOffice\PhpSpreadsheet\Writer\Exception("$bitmap: compression not supported in bitmap image.\n");
2602
        }
2603
2604
        // Remove bitmap data: data size, hres, vres, colours, imp. colours.
2605
        $data = substr($data, 20);
2606
2607
        // Add the BITMAPCOREHEADER data
2608
        $header = pack('Vvvvv', 0x000c, $width, $height, 0x01, 0x18);
2609
        $data = $header . $data;
2610
2611
        return [$width, $height, $size, $data];
2612
    }
2613
2614
    /**
2615
     * Store the window zoom factor. This should be a reduced fraction but for
2616
     * simplicity we will store all fractions with a numerator of 100.
2617
     */
2618 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...
2619
    {
2620
        // If scale is 100 we don't need to write a record
2621 38
        if ($this->phpSheet->getSheetView()->getZoomScale() == 100) {
2622 38
            return;
2623
        }
2624
2625
        $record = 0x00A0; // Record identifier
2626
        $length = 0x0004; // Bytes to follow
2627
2628
        $header = pack('vv', $record, $length);
2629
        $data = pack('vv', $this->phpSheet->getSheetView()->getZoomScale(), 100);
2630
        $this->append($header . $data);
2631
    }
2632
2633
    /**
2634
     * Get Escher object
2635
     *
2636
     * @return \PhpOffice\PhpSpreadsheet\Shared\Escher
2637
     */
2638
    public function getEscher()
2639
    {
2640
        return $this->escher;
2641
    }
2642
2643
    /**
2644
     * Set Escher object
2645
     *
2646
     * @param \PhpOffice\PhpSpreadsheet\Shared\Escher $pValue
2647
     */
2648 10
    public function setEscher(\PhpOffice\PhpSpreadsheet\Shared\Escher $pValue = null)
2649
    {
2650 10
        $this->escher = $pValue;
2651 10
    }
2652
2653
    /**
2654
     * Write MSODRAWING record
2655
     */
2656 38
    private function writeMsoDrawing()
2657
    {
2658
        // write the Escher stream if necessary
2659 38
        if (isset($this->escher)) {
2660 10
            $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls\Escher($this->escher);
2661 10
            $data = $writer->close();
2662 10
            $spOffsets = $writer->getSpOffsets();
2663 10
            $spTypes = $writer->getSpTypes();
2664
            // write the neccesary MSODRAWING, OBJ records
2665
2666
            // split the Escher stream
2667 10
            $spOffsets[0] = 0;
2668 10
            $nm = count($spOffsets) - 1; // number of shapes excluding first shape
2669 10
            for ($i = 1; $i <= $nm; ++$i) {
2670
                // MSODRAWING record
2671
                $record = 0x00EC; // Record identifier
2672
2673
                // chunk of Escher stream for one shape
2674
                $dataChunk = substr($data, $spOffsets[$i - 1], $spOffsets[$i] - $spOffsets[$i - 1]);
2675
2676
                $length = strlen($dataChunk);
2677
                $header = pack('vv', $record, $length);
2678
2679
                $this->append($header . $dataChunk);
2680
2681
                // OBJ record
2682
                $record = 0x005D; // record identifier
2683
                $objData = '';
2684
2685
                // ftCmo
2686
                if ($spTypes[$i] == 0x00C9) {
2687
                    // Add ftCmo (common object data) subobject
2688
                    $objData .=
2689
                        pack(
2690
                            'vvvvvVVV',
2691
                            0x0015, // 0x0015 = ftCmo
2692
                            0x0012, // length of ftCmo data
2693
                            0x0014, // object type, 0x0014 = filter
2694
                            $i, // object id number, Excel seems to use 1-based index, local for the sheet
2695
                            0x2101, // option flags, 0x2001 is what OpenOffice.org uses
2696
                            0, // reserved
2697
                            0, // reserved
2698
                            0  // reserved
2699
                        );
2700
2701
                    // Add ftSbs Scroll bar subobject
2702
                    $objData .= pack('vv', 0x00C, 0x0014);
2703
                    $objData .= pack('H*', '0000000000000000640001000A00000010000100');
2704
                    // Add ftLbsData (List box data) subobject
2705
                    $objData .= pack('vv', 0x0013, 0x1FEE);
2706
                    $objData .= pack('H*', '00000000010001030000020008005700');
2707
                } else {
2708
                    // Add ftCmo (common object data) subobject
2709
                    $objData .=
2710
                        pack(
2711
                            'vvvvvVVV',
2712
                            0x0015, // 0x0015 = ftCmo
2713
                            0x0012, // length of ftCmo data
2714
                            0x0008, // object type, 0x0008 = picture
2715
                            $i, // object id number, Excel seems to use 1-based index, local for the sheet
2716
                            0x6011, // option flags, 0x6011 is what OpenOffice.org uses
2717
                            0, // reserved
2718
                            0, // reserved
2719
                            0  // reserved
2720
                        );
2721
                }
2722
2723
                // ftEnd
2724
                $objData .=
2725
                    pack(
2726
                        'vv',
2727
                        0x0000, // 0x0000 = ftEnd
2728
                        0x0000  // length of ftEnd data
2729
                    );
2730
2731
                $length = strlen($objData);
2732
                $header = pack('vv', $record, $length);
2733
                $this->append($header . $objData);
2734
            }
2735
        }
2736 38
    }
2737
2738
    /**
2739
     * Store the DATAVALIDATIONS and DATAVALIDATION records.
2740
     */
2741 38
    private function writeDataValidity()
2742
    {
2743
        // Datavalidation collection
2744 38
        $dataValidationCollection = $this->phpSheet->getDataValidationCollection();
2745
2746
        // Write data validations?
2747 38
        if (!empty($dataValidationCollection)) {
2748
            // DATAVALIDATIONS record
2749 2
            $record = 0x01B2; // Record identifier
2750 2
            $length = 0x0012; // Bytes to follow
2751
2752 2
            $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records
2753 2
            $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position
2754 2
            $verPos = 0x00000000; // Vertical position of prompt box, if fixed position
2755 2
            $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible
2756
2757 2
            $header = pack('vv', $record, $length);
2758 2
            $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, count($dataValidationCollection));
2759 2
            $this->append($header . $data);
2760
2761
            // DATAVALIDATION records
2762 2
            $record = 0x01BE; // Record identifier
2763
2764 2
            foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) {
2765
                // initialize record data
2766 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...
2767
2768
                // options
2769 2
                $options = 0x00000000;
2770
2771
                // data type
2772 2
                $type = $dataValidation->getType();
2773 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...
2774 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_NONE:
2775
                        $type = 0x00;
2776
                        break;
2777 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_WHOLE:
2778 1
                        $type = 0x01;
2779 1
                        break;
2780 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_DECIMAL:
2781
                        $type = 0x02;
2782
                        break;
2783 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST:
2784 2
                        $type = 0x03;
2785 2
                        break;
2786
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_DATE:
2787
                        $type = 0x04;
2788
                        break;
2789
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_TIME:
2790
                        $type = 0x05;
2791
                        break;
2792
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_TEXTLENGTH:
2793
                        $type = 0x06;
2794
                        break;
2795
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_CUSTOM:
2796
                        $type = 0x07;
2797
                        break;
2798
                }
2799 2
                $options |= $type << 0;
2800
2801
                // error style
2802 2
                $errorStyle = $dataValidation->getType();
2803 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...
2804 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_STOP:
2805
                        $errorStyle = 0x00;
2806
                        break;
2807 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_WARNING:
2808
                        $errorStyle = 0x01;
2809
                        break;
2810 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::STYLE_INFORMATION:
2811
                        $errorStyle = 0x02;
2812
                        break;
2813
                }
2814 2
                $options |= $errorStyle << 4;
2815
2816
                // explicit formula?
2817 2
                if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) {
2818 1
                    $options |= 0x01 << 7;
2819
                }
2820
2821
                // empty cells allowed
2822 2
                $options |= $dataValidation->getAllowBlank() << 8;
2823
2824
                // show drop down
2825 2
                $options |= (!$dataValidation->getShowDropDown()) << 9;
2826
2827
                // show input message
2828 2
                $options |= $dataValidation->getShowInputMessage() << 18;
2829
2830
                // show error message
2831 2
                $options |= $dataValidation->getShowErrorMessage() << 19;
2832
2833
                // condition operator
2834 2
                $operator = $dataValidation->getOperator();
2835 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...
2836 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_BETWEEN:
2837
                        $operator = 0x00;
2838
                        break;
2839 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_NOTBETWEEN:
2840
                        $operator = 0x01;
2841
                        break;
2842 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_EQUAL:
2843
                        $operator = 0x02;
2844
                        break;
2845 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_NOTEQUAL:
2846
                        $operator = 0x03;
2847
                        break;
2848 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_GREATERTHAN:
2849
                        $operator = 0x04;
2850
                        break;
2851 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_LESSTHAN:
2852
                        $operator = 0x05;
2853
                        break;
2854 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_GREATERTHANOREQUAL:
2855
                        $operator = 0x06;
2856
                        break;
2857 2
                    case \PhpOffice\PhpSpreadsheet\Cell\DataValidation::OPERATOR_LESSTHANOREQUAL:
2858
                        $operator = 0x07;
2859
                        break;
2860
                }
2861 2
                $options |= $operator << 20;
2862
2863 2
                $data = pack('V', $options);
2864
2865
                // prompt title
2866 2
                $promptTitle = $dataValidation->getPromptTitle() !== '' ?
2867 2
                    $dataValidation->getPromptTitle() : chr(0);
2868 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($promptTitle);
2869
2870
                // error title
2871 2
                $errorTitle = $dataValidation->getErrorTitle() !== '' ?
2872 2
                    $dataValidation->getErrorTitle() : chr(0);
2873 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($errorTitle);
2874
2875
                // prompt text
2876 2
                $prompt = $dataValidation->getPrompt() !== '' ?
2877 2
                    $dataValidation->getPrompt() : chr(0);
2878 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($prompt);
2879
2880
                // error text
2881 2
                $error = $dataValidation->getError() !== '' ?
2882 2
                    $dataValidation->getError() : chr(0);
2883 2
                $data .= \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($error);
2884
2885
                // formula 1
2886
                try {
2887 2
                    $formula1 = $dataValidation->getFormula1();
2888 2
                    if ($type == 0x03) { // list type
2889 2
                        $formula1 = str_replace(',', chr(0), $formula1);
2890
                    }
2891 2
                    $this->parser->parse($formula1);
2892 1
                    $formula1 = $this->parser->toReversePolish();
2893 1
                    $sz1 = strlen($formula1);
2894 2
                } catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
2895 2
                    $sz1 = 0;
2896 2
                    $formula1 = '';
2897
                }
2898 2
                $data .= pack('vv', $sz1, 0x0000);
2899 2
                $data .= $formula1;
2900
2901
                // formula 2
2902
                try {
2903 2
                    $formula2 = $dataValidation->getFormula2();
2904 2
                    if ($formula2 === '') {
2905 2
                        throw new \PhpOffice\PhpSpreadsheet\Writer\Exception('No formula2');
2906
                    }
2907 1
                    $this->parser->parse($formula2);
2908
                    $formula2 = $this->parser->toReversePolish();
2909
                    $sz2 = strlen($formula2);
2910 2
                } catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
2911 2
                    $sz2 = 0;
2912 2
                    $formula2 = '';
2913
                }
2914 2
                $data .= pack('vv', $sz2, 0x0000);
2915 2
                $data .= $formula2;
2916
2917
                // cell range address list
2918 2
                $data .= pack('v', 0x0001);
2919 2
                $data .= $this->writeBIFF8CellRangeAddressFixed($cellCoordinate);
2920
2921 2
                $length = strlen($data);
2922 2
                $header = pack('vv', $record, $length);
2923
2924 2
                $this->append($header . $data);
2925
            }
2926
        }
2927 38
    }
2928
2929
    /**
2930
     * Map Error code
2931
     *
2932
     * @param string $errorCode
2933
     * @return int
2934
     */
2935 4
    private static function mapErrorCode($errorCode)
2936
    {
2937
        switch ($errorCode) {
2938 4
            case '#NULL!':
2939
                return 0x00;
2940 4
            case '#DIV/0!':
2941 3
                return 0x07;
2942 2
            case '#VALUE!':
2943 1
                return 0x0F;
2944 1
            case '#REF!':
2945
                return 0x17;
2946 1
            case '#NAME?':
2947
                return 0x1D;
2948 1
            case '#NUM!':
2949
                return 0x24;
2950 1
            case '#N/A':
2951 1
                return 0x2A;
2952
        }
2953
2954
        return 0;
2955
    }
2956
2957
    /**
2958
     * Write PLV Record
2959
     */
2960 38
    private function writePageLayoutView()
2961
    {
2962 38
        $record = 0x088B; // Record identifier
2963 38
        $length = 0x0010; // Bytes to follow
2964
2965 38
        $rt = 0x088B; // 2
2966 38
        $grbitFrt = 0x0000; // 2
2967 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...
2968 38
        $wScalvePLV = $this->phpSheet->getSheetView()->getZoomScale(); // 2
2969
2970
        // The options flags that comprise $grbit
2971 38
        if ($this->phpSheet->getSheetView()->getView() == \PhpOffice\PhpSpreadsheet\Worksheet\SheetView::SHEETVIEW_PAGE_LAYOUT) {
2972 1
            $fPageLayoutView = 1;
2973
        } else {
2974 37
            $fPageLayoutView = 0;
2975
        }
2976 38
        $fRulerVisible = 0;
2977 38
        $fWhitespaceHidden = 0;
2978
2979 38
        $grbit = $fPageLayoutView; // 2
2980 38
        $grbit |= $fRulerVisible << 1;
2981 38
        $grbit |= $fWhitespaceHidden << 3;
2982
2983 38
        $header = pack('vv', $record, $length);
2984 38
        $data = pack('vvVVvv', $rt, $grbitFrt, 0x00000000, 0x00000000, $wScalvePLV, $grbit);
2985 38
        $this->append($header . $data);
2986 38
    }
2987
2988
    /**
2989
     * Write CFRule Record
2990
     * @param \PhpOffice\PhpSpreadsheet\Style\Conditional $conditional
2991
     */
2992 2
    private function writeCFRule(\PhpOffice\PhpSpreadsheet\Style\Conditional $conditional)
2993
    {
2994 2
        $record = 0x01B1; // Record identifier
2995
2996
        // $type : Type of the CF
2997
        // $operatorType : Comparison operator
2998 2
        if ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION) {
2999
            $type = 0x02;
3000
            $operatorType = 0x00;
3001 2
        } elseif ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
3002 2
            $type = 0x01;
3003
3004 2
            switch ($conditional->getOperatorType()) {
3005 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_NONE:
3006
                    $operatorType = 0x00;
3007
                    break;
3008 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_EQUAL:
3009
                    $operatorType = 0x03;
3010
                    break;
3011 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHAN:
3012
                    $operatorType = 0x05;
3013
                    break;
3014 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHANOREQUAL:
3015 2
                    $operatorType = 0x07;
3016 2
                    break;
3017 2
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN:
3018 2
                    $operatorType = 0x06;
3019 2
                    break;
3020 1
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHANOREQUAL:
3021
                    $operatorType = 0x08;
3022
                    break;
3023 1
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_NOTEQUAL:
3024
                    $operatorType = 0x04;
3025
                    break;
3026 1
                case \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_BETWEEN:
3027 1
                    $operatorType = 0x01;
3028 1
                    break;
3029
                    // not OPERATOR_NOTBETWEEN 0x02
3030
            }
3031
        }
3032
3033
        // $szValue1 : size of the formula data for first value or formula
3034
        // $szValue2 : size of the formula data for second value or formula
3035 2
        $arrConditions = $conditional->getConditions();
3036 2
        $numConditions = sizeof($arrConditions);
3037 2
        if ($numConditions == 1) {
3038 2
            $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
3039 2
            $szValue2 = 0x0000;
3040 2
            $operand1 = pack('Cv', 0x1E, $arrConditions[0]);
3041 2
            $operand2 = null;
3042 1
        } elseif ($numConditions == 2 && ($conditional->getOperatorType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_BETWEEN)) {
3043 1
            $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
3044 1
            $szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000);
3045 1
            $operand1 = pack('Cv', 0x1E, $arrConditions[0]);
3046 1
            $operand2 = pack('Cv', 0x1E, $arrConditions[1]);
3047
        } else {
3048
            $szValue1 = 0x0000;
3049
            $szValue2 = 0x0000;
3050
            $operand1 = null;
3051
            $operand2 = null;
3052
        }
3053
3054
        // $flags : Option flags
3055
        // Alignment
3056 2
        $bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null ? 1 : 0);
3057 2
        $bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null ? 1 : 0);
3058 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...
3059 2
        $bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null ? 1 : 0);
3060 2
        $bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0 ? 1 : 0);
3061 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...
3062 2
        if ($bAlignHz == 0 || $bAlignVt == 0 || $bAlignWrapTx == 0 || $bTxRotation == 0 || $bIndent == 0 || $bShrinkToFit == 0) {
3063
            $bFormatAlign = 1;
3064
        } else {
3065 2
            $bFormatAlign = 0;
3066
        }
3067
        // Protection
3068 2
        $bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null ? 1 : 0);
3069 2
        $bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null ? 1 : 0);
3070 2
        if ($bProtLocked == 0 || $bProtHidden == 0) {
3071
            $bFormatProt = 1;
3072
        } else {
3073 2
            $bFormatProt = 0;
3074
        }
3075
        // Border
3076 2
        $bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3077 2
                        && $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3078 2
        $bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3079 2
                        && $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3080 2
        $bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3081 2
                        && $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3082 2
        $bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_BLACK
3083 2
                        && $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE ? 1 : 0);
3084 2
        if ($bBorderLeft == 0 || $bBorderRight == 0 || $bBorderTop == 0 || $bBorderBottom == 0) {
3085
            $bFormatBorder = 1;
3086
        } else {
3087 2
            $bFormatBorder = 0;
3088
        }
3089
        // Pattern
3090 2
        $bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null ? 0 : 1);
3091 2
        $bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null ? 0 : 1);
3092 2
        $bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null ? 0 : 1);
3093 2
        if ($bFillStyle == 0 || $bFillColor == 0 || $bFillColorBg == 0) {
3094 2
            $bFormatFill = 1;
3095
        } else {
3096
            $bFormatFill = 0;
3097
        }
3098
        // Font
3099 2
        if ($conditional->getStyle()->getFont()->getName() != null
3100 2
            || $conditional->getStyle()->getFont()->getSize() != null
3101 2
            || $conditional->getStyle()->getFont()->getBold() != null
3102 2
            || $conditional->getStyle()->getFont()->getItalic() != null
3103 1
            || $conditional->getStyle()->getFont()->getSuperScript() != null
3104 1
            || $conditional->getStyle()->getFont()->getSubScript() != null
3105 1
            || $conditional->getStyle()->getFont()->getUnderline() != null
3106 1
            || $conditional->getStyle()->getFont()->getStrikethrough() != null
3107 2
            || $conditional->getStyle()->getFont()->getColor()->getARGB() != null) {
3108 2
            $bFormatFont = 1;
3109
        } else {
3110
            $bFormatFont = 0;
3111
        }
3112
        // Alignment
3113 2
        $flags = 0;
3114 2
        $flags |= (1 == $bAlignHz ? 0x00000001 : 0);
3115 2
        $flags |= (1 == $bAlignVt ? 0x00000002 : 0);
3116 2
        $flags |= (1 == $bAlignWrapTx ? 0x00000004 : 0);
3117 2
        $flags |= (1 == $bTxRotation ? 0x00000008 : 0);
3118
        // Justify last line flag
3119 2
        $flags |= (1 == 1 ? 0x00000010 : 0);
3120 2
        $flags |= (1 == $bIndent ? 0x00000020 : 0);
3121 2
        $flags |= (1 == $bShrinkToFit ? 0x00000040 : 0);
3122
        // Default
3123 2
        $flags |= (1 == 1 ? 0x00000080 : 0);
3124
        // Protection
3125 2
        $flags |= (1 == $bProtLocked ? 0x00000100 : 0);
3126 2
        $flags |= (1 == $bProtHidden ? 0x00000200 : 0);
3127
        // Border
3128 2
        $flags |= (1 == $bBorderLeft ? 0x00000400 : 0);
3129 2
        $flags |= (1 == $bBorderRight ? 0x00000800 : 0);
3130 2
        $flags |= (1 == $bBorderTop ? 0x00001000 : 0);
3131 2
        $flags |= (1 == $bBorderBottom ? 0x00002000 : 0);
3132 2
        $flags |= (1 == 1 ? 0x00004000 : 0); // Top left to Bottom right border
3133 2
        $flags |= (1 == 1 ? 0x00008000 : 0); // Bottom left to Top right border
3134
        // Pattern
3135 2
        $flags |= (1 == $bFillStyle ? 0x00010000 : 0);
3136 2
        $flags |= (1 == $bFillColor ? 0x00020000 : 0);
3137 2
        $flags |= (1 == $bFillColorBg ? 0x00040000 : 0);
3138 2
        $flags |= (1 == 1 ? 0x00380000 : 0);
3139
        // Font
3140 2
        $flags |= (1 == $bFormatFont ? 0x04000000 : 0);
3141
        // Alignment:
3142 2
        $flags |= (1 == $bFormatAlign ? 0x08000000 : 0);
3143
        // Border
3144 2
        $flags |= (1 == $bFormatBorder ? 0x10000000 : 0);
3145
        // Pattern
3146 2
        $flags |= (1 == $bFormatFill ? 0x20000000 : 0);
3147
        // Protection
3148 2
        $flags |= (1 == $bFormatProt ? 0x40000000 : 0);
3149
        // Text direction
3150 2
        $flags |= (1 == 0 ? 0x80000000 : 0);
3151
3152
        // Data Blocks
3153 2
        if ($bFormatFont == 1) {
3154
            // Font Name
3155 2
            if ($conditional->getStyle()->getFont()->getName() == null) {
3156 2
                $dataBlockFont = pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
3157 2
                $dataBlockFont .= pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
3158
            } else {
3159
                $dataBlockFont = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName());
3160
            }
3161
            // Font Size
3162 2
            if ($conditional->getStyle()->getFont()->getSize() == null) {
3163 2
                $dataBlockFont .= pack('V', 20 * 11);
3164
            } else {
3165
                $dataBlockFont .= pack('V', 20 * $conditional->getStyle()->getFont()->getSize());
3166
            }
3167
            // Font Options
3168 2
            $dataBlockFont .= pack('V', 0);
3169
            // Font weight
3170 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...
3171 1
                $dataBlockFont .= pack('v', 0x02BC);
3172
            } else {
3173 2
                $dataBlockFont .= pack('v', 0x0190);
3174
            }
3175
            // Escapement type
3176 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...
3177
                $dataBlockFont .= pack('v', 0x02);
3178
                $fontEscapement = 0;
3179 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...
3180
                $dataBlockFont .= pack('v', 0x01);
3181
                $fontEscapement = 0;
3182
            } else {
3183 2
                $dataBlockFont .= pack('v', 0x00);
3184 2
                $fontEscapement = 1;
3185
            }
3186
            // Underline type
3187 2
            switch ($conditional->getStyle()->getFont()->getUnderline()) {
3188 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_NONE:
3189
                    $dataBlockFont .= pack('C', 0x00);
3190
                    $fontUnderline = 0;
3191
                    break;
3192 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLE:
3193
                    $dataBlockFont .= pack('C', 0x02);
3194
                    $fontUnderline = 0;
3195
                    break;
3196 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLEACCOUNTING:
3197
                    $dataBlockFont .= pack('C', 0x22);
3198
                    $fontUnderline = 0;
3199
                    break;
3200 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE:
3201
                    $dataBlockFont .= pack('C', 0x01);
3202
                    $fontUnderline = 0;
3203
                    break;
3204 2
                case \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLEACCOUNTING:
3205
                    $dataBlockFont .= pack('C', 0x21);
3206
                    $fontUnderline = 0;
3207
                    break;
3208
                default:
3209 2
                    $dataBlockFont .= pack('C', 0x00);
3210 2
                    $fontUnderline = 1;
3211 2
                    break;
3212
            }
3213
            // 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...
3214 2
            $dataBlockFont .= pack('vC', 0x0000, 0x00);
3215
            // Font color index
3216 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...
3217 2
                case '000000':
3218
                    $colorIdx = 0x08;
3219
                    break;
3220 2
                case 'FFFFFF':
3221
                    $colorIdx = 0x09;
3222
                    break;
3223 2
                case 'FF0000':
3224 2
                    $colorIdx = 0x0A;
3225 2
                    break;
3226 2
                case '00FF00':
3227 2
                    $colorIdx = 0x0B;
3228 2
                    break;
3229 1
                case '0000FF':
3230
                    $colorIdx = 0x0C;
3231
                    break;
3232 1
                case 'FFFF00':
3233 1
                    $colorIdx = 0x0D;
3234 1
                    break;
3235
                case 'FF00FF':
3236
                    $colorIdx = 0x0E;
3237
                    break;
3238
                case '00FFFF':
3239
                    $colorIdx = 0x0F;
3240
                    break;
3241
                case '800000':
3242
                    $colorIdx = 0x10;
3243
                    break;
3244
                case '008000':
3245
                    $colorIdx = 0x11;
3246
                    break;
3247
                case '000080':
3248
                    $colorIdx = 0x12;
3249
                    break;
3250
                case '808000':
3251
                    $colorIdx = 0x13;
3252
                    break;
3253
                case '800080':
3254
                    $colorIdx = 0x14;
3255
                    break;
3256
                case '008080':
3257
                    $colorIdx = 0x15;
3258
                    break;
3259
                case 'C0C0C0':
3260
                    $colorIdx = 0x16;
3261
                    break;
3262
                case '808080':
3263
                    $colorIdx = 0x17;
3264
                    break;
3265
                case '9999FF':
3266
                    $colorIdx = 0x18;
3267
                    break;
3268
                case '993366':
3269
                    $colorIdx = 0x19;
3270
                    break;
3271
                case 'FFFFCC':
3272
                    $colorIdx = 0x1A;
3273
                    break;
3274
                case 'CCFFFF':
3275
                    $colorIdx = 0x1B;
3276
                    break;
3277
                case '660066':
3278
                    $colorIdx = 0x1C;
3279
                    break;
3280
                case 'FF8080':
3281
                    $colorIdx = 0x1D;
3282
                    break;
3283
                case '0066CC':
3284
                    $colorIdx = 0x1E;
3285
                    break;
3286
                case 'CCCCFF':
3287
                    $colorIdx = 0x1F;
3288
                    break;
3289
                case '000080':
3290
                    $colorIdx = 0x20;
3291
                    break;
3292
                case 'FF00FF':
3293
                    $colorIdx = 0x21;
3294
                    break;
3295
                case 'FFFF00':
3296
                    $colorIdx = 0x22;
3297
                    break;
3298
                case '00FFFF':
3299
                    $colorIdx = 0x23;
3300
                    break;
3301
                case '800080':
3302
                    $colorIdx = 0x24;
3303
                    break;
3304
                case '800000':
3305
                    $colorIdx = 0x25;
3306
                    break;
3307
                case '008080':
3308
                    $colorIdx = 0x26;
3309
                    break;
3310
                case '0000FF':
3311
                    $colorIdx = 0x27;
3312
                    break;
3313
                case '00CCFF':
3314
                    $colorIdx = 0x28;
3315
                    break;
3316
                case 'CCFFFF':
3317
                    $colorIdx = 0x29;
3318
                    break;
3319
                case 'CCFFCC':
3320
                    $colorIdx = 0x2A;
3321
                    break;
3322
                case 'FFFF99':
3323
                    $colorIdx = 0x2B;
3324
                    break;
3325
                case '99CCFF':
3326
                    $colorIdx = 0x2C;
3327
                    break;
3328
                case 'FF99CC':
3329
                    $colorIdx = 0x2D;
3330
                    break;
3331
                case 'CC99FF':
3332
                    $colorIdx = 0x2E;
3333
                    break;
3334
                case 'FFCC99':
3335
                    $colorIdx = 0x2F;
3336
                    break;
3337
                case '3366FF':
3338
                    $colorIdx = 0x30;
3339
                    break;
3340
                case '33CCCC':
3341
                    $colorIdx = 0x31;
3342
                    break;
3343
                case '99CC00':
3344
                    $colorIdx = 0x32;
3345
                    break;
3346
                case 'FFCC00':
3347
                    $colorIdx = 0x33;
3348
                    break;
3349
                case 'FF9900':
3350
                    $colorIdx = 0x34;
3351
                    break;
3352
                case 'FF6600':
3353
                    $colorIdx = 0x35;
3354
                    break;
3355
                case '666699':
3356
                    $colorIdx = 0x36;
3357
                    break;
3358
                case '969696':
3359
                    $colorIdx = 0x37;
3360
                    break;
3361
                case '003366':
3362
                    $colorIdx = 0x38;
3363
                    break;
3364
                case '339966':
3365
                    $colorIdx = 0x39;
3366
                    break;
3367
                case '003300':
3368
                    $colorIdx = 0x3A;
3369
                    break;
3370
                case '333300':
3371
                    $colorIdx = 0x3B;
3372
                    break;
3373
                case '993300':
3374
                    $colorIdx = 0x3C;
3375
                    break;
3376
                case '993366':
3377
                    $colorIdx = 0x3D;
3378
                    break;
3379
                case '333399':
3380
                    $colorIdx = 0x3E;
3381
                    break;
3382
                case '333333':
3383
                    $colorIdx = 0x3F;
3384
                    break;
3385
                default:
3386
                    $colorIdx = 0x00;
3387
                    break;
3388
            }
3389 2
            $dataBlockFont .= pack('V', $colorIdx);
3390
            // 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...
3391 2
            $dataBlockFont .= pack('V', 0x00000000);
3392
            // Options flags for modified font attributes
3393 2
            $optionsFlags = 0;
3394 2
            $optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null ? 1 : 0);
3395 2
            $optionsFlags |= (1 == $optionsFlagsBold ? 0x00000002 : 0);
3396 2
            $optionsFlags |= (1 == 1 ? 0x00000008 : 0);
3397 2
            $optionsFlags |= (1 == 1 ? 0x00000010 : 0);
3398 2
            $optionsFlags |= (1 == 0 ? 0x00000020 : 0);
3399 2
            $optionsFlags |= (1 == 1 ? 0x00000080 : 0);
3400 2
            $dataBlockFont .= pack('V', $optionsFlags);
3401
            // Escapement type
3402 2
            $dataBlockFont .= pack('V', $fontEscapement);
3403
            // Underline type
3404 2
            $dataBlockFont .= pack('V', $fontUnderline);
3405
            // Always
3406 2
            $dataBlockFont .= pack('V', 0x00000000);
3407
            // Always
3408 2
            $dataBlockFont .= pack('V', 0x00000000);
3409
            // 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...
3410 2
            $dataBlockFont .= pack('VV', 0x00000000, 0x00000000);
3411
            // Always
3412 2
            $dataBlockFont .= pack('v', 0x0001);
3413
        }
3414 2
        if ($bFormatAlign == 1) {
3415
            $blockAlign = 0;
3416
            // Alignment and text break
3417
            switch ($conditional->getStyle()->getAlignment()->getHorizontal()) {
3418
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_GENERAL:
3419
                    $blockAlign = 0;
3420
                    break;
3421
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT:
3422
                    $blockAlign = 1;
3423
                    break;
3424
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT:
3425
                    $blockAlign = 3;
3426
                    break;
3427
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER:
3428
                    $blockAlign = 2;
3429
                    break;
3430
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER_CONTINUOUS:
3431
                    $blockAlign = 6;
3432
                    break;
3433
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_JUSTIFY:
3434
                    $blockAlign = 5;
3435
                    break;
3436
            }
3437
            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...
3438
                $blockAlign |= 1 << 3;
3439
            } else {
3440
                $blockAlign |= 0 << 3;
3441
            }
3442
            switch ($conditional->getStyle()->getAlignment()->getVertical()) {
3443
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_BOTTOM:
3444
                    $blockAlign = 2 << 4;
3445
                    break;
3446
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP:
3447
                    $blockAlign = 0 << 4;
3448
                    break;
3449
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER:
3450
                    $blockAlign = 1 << 4;
3451
                    break;
3452
                case \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_JUSTIFY:
3453
                    $blockAlign = 3 << 4;
3454
                    break;
3455
            }
3456
            $blockAlign |= 0 << 7;
3457
3458
            // Text rotation angle
3459
            $blockRotation = $conditional->getStyle()->getAlignment()->getTextRotation();
3460
3461
            // Indentation
3462
            $blockIndent = $conditional->getStyle()->getAlignment()->getIndent();
3463
            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...
3464
                $blockIndent |= 1 << 4;
3465
            } else {
3466
                $blockIndent |= 0 << 4;
3467
            }
3468
            $blockIndent |= 0 << 6;
3469
3470
            // Relative indentation
3471
            $blockIndentRelative = 255;
3472
3473
            $dataBlockAlign = pack('CCvvv', $blockAlign, $blockRotation, $blockIndent, $blockIndentRelative, 0x0000);
3474
        }
3475 2
        if ($bFormatBorder == 1) {
3476
            $blockLineStyle = 0;
3477
            switch ($conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()) {
3478
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3479
                    $blockLineStyle |= 0x00;
3480
                    break;
3481
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3482
                    $blockLineStyle |= 0x01;
3483
                    break;
3484
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3485
                    $blockLineStyle |= 0x02;
3486
                    break;
3487
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3488
                    $blockLineStyle |= 0x03;
3489
                    break;
3490
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3491
                    $blockLineStyle |= 0x04;
3492
                    break;
3493
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3494
                    $blockLineStyle |= 0x05;
3495
                    break;
3496
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3497
                    $blockLineStyle |= 0x06;
3498
                    break;
3499
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3500
                    $blockLineStyle |= 0x07;
3501
                    break;
3502
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3503
                    $blockLineStyle |= 0x08;
3504
                    break;
3505
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3506
                    $blockLineStyle |= 0x09;
3507
                    break;
3508
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3509
                    $blockLineStyle |= 0x0A;
3510
                    break;
3511
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3512
                    $blockLineStyle |= 0x0B;
3513
                    break;
3514
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3515
                    $blockLineStyle |= 0x0C;
3516
                    break;
3517
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3518
                    $blockLineStyle |= 0x0D;
3519
                    break;
3520
            }
3521 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...
3522
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3523
                    $blockLineStyle |= 0x00 << 4;
3524
                    break;
3525
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3526
                    $blockLineStyle |= 0x01 << 4;
3527
                    break;
3528
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3529
                    $blockLineStyle |= 0x02 << 4;
3530
                    break;
3531
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3532
                    $blockLineStyle |= 0x03 << 4;
3533
                    break;
3534
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3535
                    $blockLineStyle |= 0x04 << 4;
3536
                    break;
3537
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3538
                    $blockLineStyle |= 0x05 << 4;
3539
                    break;
3540
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3541
                    $blockLineStyle |= 0x06 << 4;
3542
                    break;
3543
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3544
                    $blockLineStyle |= 0x07 << 4;
3545
                    break;
3546
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3547
                    $blockLineStyle |= 0x08 << 4;
3548
                    break;
3549
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3550
                    $blockLineStyle |= 0x09 << 4;
3551
                    break;
3552
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3553
                    $blockLineStyle |= 0x0A << 4;
3554
                    break;
3555
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3556
                    $blockLineStyle |= 0x0B << 4;
3557
                    break;
3558
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3559
                    $blockLineStyle |= 0x0C << 4;
3560
                    break;
3561
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3562
                    $blockLineStyle |= 0x0D << 4;
3563
                    break;
3564
            }
3565 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...
3566
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3567
                    $blockLineStyle |= 0x00 << 8;
3568
                    break;
3569
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3570
                    $blockLineStyle |= 0x01 << 8;
3571
                    break;
3572
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3573
                    $blockLineStyle |= 0x02 << 8;
3574
                    break;
3575
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3576
                    $blockLineStyle |= 0x03 << 8;
3577
                    break;
3578
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3579
                    $blockLineStyle |= 0x04 << 8;
3580
                    break;
3581
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3582
                    $blockLineStyle |= 0x05 << 8;
3583
                    break;
3584
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3585
                    $blockLineStyle |= 0x06 << 8;
3586
                    break;
3587
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3588
                    $blockLineStyle |= 0x07 << 8;
3589
                    break;
3590
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3591
                    $blockLineStyle |= 0x08 << 8;
3592
                    break;
3593
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3594
                    $blockLineStyle |= 0x09 << 8;
3595
                    break;
3596
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3597
                    $blockLineStyle |= 0x0A << 8;
3598
                    break;
3599
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3600
                    $blockLineStyle |= 0x0B << 8;
3601
                    break;
3602
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3603
                    $blockLineStyle |= 0x0C << 8;
3604
                    break;
3605
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3606
                    $blockLineStyle |= 0x0D << 8;
3607
                    break;
3608
            }
3609 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...
3610
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3611
                    $blockLineStyle |= 0x00 << 12;
3612
                    break;
3613
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3614
                    $blockLineStyle |= 0x01 << 12;
3615
                    break;
3616
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3617
                    $blockLineStyle |= 0x02 << 12;
3618
                    break;
3619
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3620
                    $blockLineStyle |= 0x03 << 12;
3621
                    break;
3622
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3623
                    $blockLineStyle |= 0x04 << 12;
3624
                    break;
3625
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3626
                    $blockLineStyle |= 0x05 << 12;
3627
                    break;
3628
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3629
                    $blockLineStyle |= 0x06 << 12;
3630
                    break;
3631
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3632
                    $blockLineStyle |= 0x07 << 12;
3633
                    break;
3634
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3635
                    $blockLineStyle |= 0x08 << 12;
3636
                    break;
3637
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3638
                    $blockLineStyle |= 0x09 << 12;
3639
                    break;
3640
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3641
                    $blockLineStyle |= 0x0A << 12;
3642
                    break;
3643
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3644
                    $blockLineStyle |= 0x0B << 12;
3645
                    break;
3646
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3647
                    $blockLineStyle |= 0x0C << 12;
3648
                    break;
3649
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3650
                    $blockLineStyle |= 0x0D << 12;
3651
                    break;
3652
            }
3653
            //@todo writeCFRule() => $blockLineStyle => Index Color for left line
3654
            //@todo writeCFRule() => $blockLineStyle => Index Color for right line
3655
            //@todo writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off
3656
            //@todo writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off
3657
            $blockColor = 0;
3658
            //@todo writeCFRule() => $blockColor => Index Color for top line
3659
            //@todo writeCFRule() => $blockColor => Index Color for bottom line
3660
            //@todo writeCFRule() => $blockColor => Index Color for diagonal line
3661 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...
3662
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_NONE:
3663
                    $blockColor |= 0x00 << 21;
3664
                    break;
3665
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN:
3666
                    $blockColor |= 0x01 << 21;
3667
                    break;
3668
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM:
3669
                    $blockColor |= 0x02 << 21;
3670
                    break;
3671
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHED:
3672
                    $blockColor |= 0x03 << 21;
3673
                    break;
3674
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOTTED:
3675
                    $blockColor |= 0x04 << 21;
3676
                    break;
3677
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK:
3678
                    $blockColor |= 0x05 << 21;
3679
                    break;
3680
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE:
3681
                    $blockColor |= 0x06 << 21;
3682
                    break;
3683
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_HAIR:
3684
                    $blockColor |= 0x07 << 21;
3685
                    break;
3686
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHED:
3687
                    $blockColor |= 0x08 << 21;
3688
                    break;
3689
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOT:
3690
                    $blockColor |= 0x09 << 21;
3691
                    break;
3692
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOT:
3693
                    $blockColor |= 0x0A << 21;
3694
                    break;
3695
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DASHDOTDOT:
3696
                    $blockColor |= 0x0B << 21;
3697
                    break;
3698
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUMDASHDOTDOT:
3699
                    $blockColor |= 0x0C << 21;
3700
                    break;
3701
                case \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_SLANTDASHDOT:
3702
                    $blockColor |= 0x0D << 21;
3703
                    break;
3704
            }
3705
            $dataBlockBorder = pack('vv', $blockLineStyle, $blockColor);
3706
        }
3707 2
        if ($bFormatFill == 1) {
3708
            // Fill Patern Style
3709 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...
3710 2
            switch ($conditional->getStyle()->getFill()->getFillType()) {
3711 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_NONE:
3712
                    $blockFillPatternStyle = 0x00;
3713
                    break;
3714 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID:
3715
                    $blockFillPatternStyle = 0x01;
3716
                    break;
3717 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_MEDIUMGRAY:
3718
                    $blockFillPatternStyle = 0x02;
3719
                    break;
3720 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKGRAY:
3721
                    $blockFillPatternStyle = 0x03;
3722
                    break;
3723 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRAY:
3724
                    $blockFillPatternStyle = 0x04;
3725
                    break;
3726 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKHORIZONTAL:
3727
                    $blockFillPatternStyle = 0x05;
3728
                    break;
3729 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKVERTICAL:
3730
                    $blockFillPatternStyle = 0x06;
3731
                    break;
3732 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKDOWN:
3733
                    $blockFillPatternStyle = 0x07;
3734
                    break;
3735 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKUP:
3736
                    $blockFillPatternStyle = 0x08;
3737
                    break;
3738 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKGRID:
3739
                    $blockFillPatternStyle = 0x09;
3740
                    break;
3741 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_DARKTRELLIS:
3742
                    $blockFillPatternStyle = 0x0A;
3743
                    break;
3744 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTHORIZONTAL:
3745
                    $blockFillPatternStyle = 0x0B;
3746
                    break;
3747 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTVERTICAL:
3748
                    $blockFillPatternStyle = 0x0C;
3749
                    break;
3750 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTDOWN:
3751
                    $blockFillPatternStyle = 0x0D;
3752
                    break;
3753 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTUP:
3754
                    $blockFillPatternStyle = 0x0E;
3755
                    break;
3756 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTGRID:
3757
                    $blockFillPatternStyle = 0x0F;
3758
                    break;
3759 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_LIGHTTRELLIS:
3760
                    $blockFillPatternStyle = 0x10;
3761
                    break;
3762 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_GRAY125:
3763
                    $blockFillPatternStyle = 0x11;
3764
                    break;
3765 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_PATTERN_GRAY0625:
3766
                    $blockFillPatternStyle = 0x12;
3767
                    break;
3768 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_GRADIENT_LINEAR:
3769
                    $blockFillPatternStyle = 0x00;
3770
                    break; // does not exist in BIFF8
3771 2
                case \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_GRADIENT_PATH:
3772
                    $blockFillPatternStyle = 0x00;
3773
                    break; // does not exist in BIFF8
3774
                default:
3775 2
                    $blockFillPatternStyle = 0x00;
3776 2
                    break;
3777
            }
3778
            // Color
3779 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...
3780 2
                case '000000':
3781
                    $colorIdxBg = 0x08;
3782
                    break;
3783 2
                case 'FFFFFF':
3784
                    $colorIdxBg = 0x09;
3785
                    break;
3786 2
                case 'FF0000':
3787
                    $colorIdxBg = 0x0A;
3788
                    break;
3789 2
                case '00FF00':
3790
                    $colorIdxBg = 0x0B;
3791
                    break;
3792 2
                case '0000FF':
3793
                    $colorIdxBg = 0x0C;
3794
                    break;
3795 2
                case 'FFFF00':
3796
                    $colorIdxBg = 0x0D;
3797
                    break;
3798 2
                case 'FF00FF':
3799
                    $colorIdxBg = 0x0E;
3800
                    break;
3801 2
                case '00FFFF':
3802
                    $colorIdxBg = 0x0F;
3803
                    break;
3804 2
                case '800000':
3805
                    $colorIdxBg = 0x10;
3806
                    break;
3807 2
                case '008000':
3808
                    $colorIdxBg = 0x11;
3809
                    break;
3810 2
                case '000080':
3811
                    $colorIdxBg = 0x12;
3812
                    break;
3813 2
                case '808000':
3814
                    $colorIdxBg = 0x13;
3815
                    break;
3816 2
                case '800080':
3817
                    $colorIdxBg = 0x14;
3818
                    break;
3819 2
                case '008080':
3820
                    $colorIdxBg = 0x15;
3821
                    break;
3822 2
                case 'C0C0C0':
3823
                    $colorIdxBg = 0x16;
3824
                    break;
3825 2
                case '808080':
3826
                    $colorIdxBg = 0x17;
3827
                    break;
3828 2
                case '9999FF':
3829
                    $colorIdxBg = 0x18;
3830
                    break;
3831 2
                case '993366':
3832
                    $colorIdxBg = 0x19;
3833
                    break;
3834 2
                case 'FFFFCC':
3835
                    $colorIdxBg = 0x1A;
3836
                    break;
3837 2
                case 'CCFFFF':
3838
                    $colorIdxBg = 0x1B;
3839
                    break;
3840 2
                case '660066':
3841
                    $colorIdxBg = 0x1C;
3842
                    break;
3843 2
                case 'FF8080':
3844
                    $colorIdxBg = 0x1D;
3845
                    break;
3846 2
                case '0066CC':
3847
                    $colorIdxBg = 0x1E;
3848
                    break;
3849 2
                case 'CCCCFF':
3850
                    $colorIdxBg = 0x1F;
3851
                    break;
3852 2
                case '000080':
3853
                    $colorIdxBg = 0x20;
3854
                    break;
3855 2
                case 'FF00FF':
3856
                    $colorIdxBg = 0x21;
3857
                    break;
3858 2
                case 'FFFF00':
3859
                    $colorIdxBg = 0x22;
3860
                    break;
3861 2
                case '00FFFF':
3862
                    $colorIdxBg = 0x23;
3863
                    break;
3864 2
                case '800080':
3865
                    $colorIdxBg = 0x24;
3866
                    break;
3867 2
                case '800000':
3868
                    $colorIdxBg = 0x25;
3869
                    break;
3870 2
                case '008080':
3871
                    $colorIdxBg = 0x26;
3872
                    break;
3873 2
                case '0000FF':
3874
                    $colorIdxBg = 0x27;
3875
                    break;
3876 2
                case '00CCFF':
3877
                    $colorIdxBg = 0x28;
3878
                    break;
3879 2
                case 'CCFFFF':
3880
                    $colorIdxBg = 0x29;
3881
                    break;
3882 2
                case 'CCFFCC':
3883
                    $colorIdxBg = 0x2A;
3884
                    break;
3885 2
                case 'FFFF99':
3886
                    $colorIdxBg = 0x2B;
3887
                    break;
3888 2
                case '99CCFF':
3889
                    $colorIdxBg = 0x2C;
3890
                    break;
3891 2
                case 'FF99CC':
3892
                    $colorIdxBg = 0x2D;
3893
                    break;
3894 2
                case 'CC99FF':
3895
                    $colorIdxBg = 0x2E;
3896
                    break;
3897 2
                case 'FFCC99':
3898
                    $colorIdxBg = 0x2F;
3899
                    break;
3900 2
                case '3366FF':
3901
                    $colorIdxBg = 0x30;
3902
                    break;
3903 2
                case '33CCCC':
3904
                    $colorIdxBg = 0x31;
3905
                    break;
3906 2
                case '99CC00':
3907
                    $colorIdxBg = 0x32;
3908
                    break;
3909 2
                case 'FFCC00':
3910
                    $colorIdxBg = 0x33;
3911
                    break;
3912 2
                case 'FF9900':
3913
                    $colorIdxBg = 0x34;
3914
                    break;
3915 2
                case 'FF6600':
3916
                    $colorIdxBg = 0x35;
3917
                    break;
3918 2
                case '666699':
3919
                    $colorIdxBg = 0x36;
3920
                    break;
3921 2
                case '969696':
3922
                    $colorIdxBg = 0x37;
3923
                    break;
3924 2
                case '003366':
3925
                    $colorIdxBg = 0x38;
3926
                    break;
3927 2
                case '339966':
3928
                    $colorIdxBg = 0x39;
3929
                    break;
3930 2
                case '003300':
3931
                    $colorIdxBg = 0x3A;
3932
                    break;
3933 2
                case '333300':
3934
                    $colorIdxBg = 0x3B;
3935
                    break;
3936 2
                case '993300':
3937
                    $colorIdxBg = 0x3C;
3938
                    break;
3939 2
                case '993366':
3940
                    $colorIdxBg = 0x3D;
3941
                    break;
3942 2
                case '333399':
3943
                    $colorIdxBg = 0x3E;
3944
                    break;
3945 2
                case '333333':
3946
                    $colorIdxBg = 0x3F;
3947
                    break;
3948
                default:
3949 2
                          $colorIdxBg = 0x41;
3950 2
                    break;
3951
            }
3952
            // Fg Color
3953 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...
3954 2
                case '000000':
3955
                    $colorIdxFg = 0x08;
3956
                    break;
3957 2
                case 'FFFFFF':
3958
                    $colorIdxFg = 0x09;
3959
                    break;
3960 2
                case 'FF0000':
3961
                    $colorIdxFg = 0x0A;
3962
                    break;
3963 2
                case '00FF00':
3964
                    $colorIdxFg = 0x0B;
3965
                    break;
3966 2
                case '0000FF':
3967
                    $colorIdxFg = 0x0C;
3968
                    break;
3969 2
                case 'FFFF00':
3970
                    $colorIdxFg = 0x0D;
3971
                    break;
3972 2
                case 'FF00FF':
3973
                    $colorIdxFg = 0x0E;
3974
                    break;
3975 2
                case '00FFFF':
3976
                    $colorIdxFg = 0x0F;
3977
                    break;
3978 2
                case '800000':
3979
                    $colorIdxFg = 0x10;
3980
                    break;
3981 2
                case '008000':
3982
                    $colorIdxFg = 0x11;
3983
                    break;
3984 2
                case '000080':
3985
                    $colorIdxFg = 0x12;
3986
                    break;
3987 2
                case '808000':
3988
                    $colorIdxFg = 0x13;
3989
                    break;
3990 2
                case '800080':
3991
                    $colorIdxFg = 0x14;
3992
                    break;
3993 2
                case '008080':
3994
                    $colorIdxFg = 0x15;
3995
                    break;
3996 2
                case 'C0C0C0':
3997
                    $colorIdxFg = 0x16;
3998
                    break;
3999 2
                case '808080':
4000
                    $colorIdxFg = 0x17;
4001
                    break;
4002 2
                case '9999FF':
4003
                    $colorIdxFg = 0x18;
4004
                    break;
4005 2
                case '993366':
4006
                    $colorIdxFg = 0x19;
4007
                    break;
4008 2
                case 'FFFFCC':
4009
                    $colorIdxFg = 0x1A;
4010
                    break;
4011 2
                case 'CCFFFF':
4012
                    $colorIdxFg = 0x1B;
4013
                    break;
4014 2
                case '660066':
4015
                    $colorIdxFg = 0x1C;
4016
                    break;
4017 2
                case 'FF8080':
4018
                    $colorIdxFg = 0x1D;
4019
                    break;
4020 2
                case '0066CC':
4021
                    $colorIdxFg = 0x1E;
4022
                    break;
4023 2
                case 'CCCCFF':
4024
                    $colorIdxFg = 0x1F;
4025
                    break;
4026 2
                case '000080':
4027
                    $colorIdxFg = 0x20;
4028
                    break;
4029 2
                case 'FF00FF':
4030
                    $colorIdxFg = 0x21;
4031
                    break;
4032 2
                case 'FFFF00':
4033
                    $colorIdxFg = 0x22;
4034
                    break;
4035 2
                case '00FFFF':
4036
                    $colorIdxFg = 0x23;
4037
                    break;
4038 2
                case '800080':
4039
                    $colorIdxFg = 0x24;
4040
                    break;
4041 2
                case '800000':
4042
                    $colorIdxFg = 0x25;
4043
                    break;
4044 2
                case '008080':
4045
                    $colorIdxFg = 0x26;
4046
                    break;
4047 2
                case '0000FF':
4048
                    $colorIdxFg = 0x27;
4049
                    break;
4050 2
                case '00CCFF':
4051
                    $colorIdxFg = 0x28;
4052
                    break;
4053 2
                case 'CCFFFF':
4054
                    $colorIdxFg = 0x29;
4055
                    break;
4056 2
                case 'CCFFCC':
4057
                    $colorIdxFg = 0x2A;
4058
                    break;
4059 2
                case 'FFFF99':
4060
                    $colorIdxFg = 0x2B;
4061
                    break;
4062 2
                case '99CCFF':
4063
                    $colorIdxFg = 0x2C;
4064
                    break;
4065 2
                case 'FF99CC':
4066
                    $colorIdxFg = 0x2D;
4067
                    break;
4068 2
                case 'CC99FF':
4069
                    $colorIdxFg = 0x2E;
4070
                    break;
4071 2
                case 'FFCC99':
4072
                    $colorIdxFg = 0x2F;
4073
                    break;
4074 2
                case '3366FF':
4075
                    $colorIdxFg = 0x30;
4076
                    break;
4077 2
                case '33CCCC':
4078
                    $colorIdxFg = 0x31;
4079
                    break;
4080 2
                case '99CC00':
4081
                    $colorIdxFg = 0x32;
4082
                    break;
4083 2
                case 'FFCC00':
4084
                    $colorIdxFg = 0x33;
4085
                    break;
4086 2
                case 'FF9900':
4087
                    $colorIdxFg = 0x34;
4088
                    break;
4089 2
                case 'FF6600':
4090
                    $colorIdxFg = 0x35;
4091
                    break;
4092 2
                case '666699':
4093
                    $colorIdxFg = 0x36;
4094
                    break;
4095 2
                case '969696':
4096
                    $colorIdxFg = 0x37;
4097
                    break;
4098 2
                case '003366':
4099
                    $colorIdxFg = 0x38;
4100
                    break;
4101 2
                case '339966':
4102
                    $colorIdxFg = 0x39;
4103
                    break;
4104 2
                case '003300':
4105
                    $colorIdxFg = 0x3A;
4106
                    break;
4107 2
                case '333300':
4108
                    $colorIdxFg = 0x3B;
4109
                    break;
4110 2
                case '993300':
4111
                    $colorIdxFg = 0x3C;
4112
                    break;
4113 2
                case '993366':
4114
                    $colorIdxFg = 0x3D;
4115
                    break;
4116 2
                case '333399':
4117
                    $colorIdxFg = 0x3E;
4118
                    break;
4119 2
                case '333333':
4120
                    $colorIdxFg = 0x3F;
4121
                    break;
4122
                default:
4123 2
                          $colorIdxFg = 0x40;
4124 2
                    break;
4125
            }
4126 2
            $dataBlockFill = pack('v', $blockFillPatternStyle);
4127 2
            $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7));
4128
        }
4129 2
        if ($bFormatProt == 1) {
4130
            $dataBlockProtection = 0;
4131
            if ($conditional->getStyle()->getProtection()->getLocked() == \PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED) {
4132
                $dataBlockProtection = 1;
4133
            }
4134
            if ($conditional->getStyle()->getProtection()->getHidden() == \PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED) {
4135
                $dataBlockProtection = 1 << 1;
4136
            }
4137
        }
4138
4139 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...
4140 2
        if ($bFormatFont == 1) { // Block Formatting : OK
4141 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...
4142
        }
4143 2
        if ($bFormatAlign == 1) {
4144
            $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...
4145
        }
4146 2
        if ($bFormatBorder == 1) {
4147
            $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...
4148
        }
4149 2
        if ($bFormatFill == 1) { // Block Formatting : OK
4150 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...
4151
        }
4152 2
        if ($bFormatProt == 1) {
4153
            $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...
4154
        }
4155 2
        if (!is_null($operand1)) {
4156 2
            $data .= $operand1;
4157
        }
4158 2
        if (!is_null($operand2)) {
4159 1
            $data .= $operand2;
4160
        }
4161 2
        $header = pack('vv', $record, strlen($data));
4162 2
        $this->append($header . $data);
4163 2
    }
4164
4165
    /**
4166
     * Write CFHeader record
4167
     */
4168 2
    private function writeCFHeader()
4169
    {
4170 2
        $record = 0x01B0; // Record identifier
4171 2
        $length = 0x0016; // Bytes to follow
4172
4173 2
        $numColumnMin = null;
4174 2
        $numColumnMax = null;
4175 2
        $numRowMin = null;
4176 2
        $numRowMax = null;
4177 2
        $arrConditional = [];
4178 2
        foreach ($this->phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
4179 2
            foreach ($conditionalStyles as $conditional) {
4180 2
                if ($conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION
4181 2
                        || $conditional->getConditionType() == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS) {
4182 2
                    if (!in_array($conditional->getHashCode(), $arrConditional)) {
4183 2
                        $arrConditional[] = $conditional->getHashCode();
4184
                    }
4185
                    // Cells
4186 2
                    $arrCoord = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($cellCoordinate);
4187 2
                    if (!is_numeric($arrCoord[0])) {
4188 2
                        $arrCoord[0] = \PhpOffice\PhpSpreadsheet\Cell::columnIndexFromString($arrCoord[0]);
4189
                    }
4190 2
                    if (is_null($numColumnMin) || ($numColumnMin > $arrCoord[0])) {
4191 2
                        $numColumnMin = $arrCoord[0];
4192
                    }
4193 2
                    if (is_null($numColumnMax) || ($numColumnMax < $arrCoord[0])) {
4194 2
                        $numColumnMax = $arrCoord[0];
4195
                    }
4196 2
                    if (is_null($numRowMin) || ($numRowMin > $arrCoord[1])) {
4197 2
                        $numRowMin = $arrCoord[1];
4198
                    }
4199 2
                    if (is_null($numRowMax) || ($numRowMax < $arrCoord[1])) {
4200 2
                        $numRowMax = $arrCoord[1];
4201
                    }
4202
                }
4203
            }
4204
        }
4205 2
        $needRedraw = 1;
4206 2
        $cellRange = pack('vvvv', $numRowMin - 1, $numRowMax - 1, $numColumnMin - 1, $numColumnMax - 1);
4207
4208 2
        $header = pack('vv', $record, $length);
4209 2
        $data = pack('vv', count($arrConditional), $needRedraw);
4210 2
        $data .= $cellRange;
4211 2
        $data .= pack('v', 0x0001);
4212 2
        $data .= $cellRange;
4213 2
        $this->append($header . $data);
4214 2
    }
4215
}
4216