Completed
Push — develop ( 39b55d...e2e982 )
by Adrien
19:14
created

Worksheet::writeMarginBottom()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 15
Ratio 100 %

Code Coverage

Tests 9
CRAP Score 2.004

Importance

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