Completed
Push — develop ( 2922a1...cfa1fe )
by Adrien
24:40
created

Excel5::save()   F

Complexity

Conditions 17
Paths 3072

Size

Total Lines 108
Code Lines 54

Duplication

Lines 8
Ratio 7.41 %

Code Coverage

Tests 0
CRAP Score 306

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 17
eloc 54
nc 3072
nop 1
dl 8
loc 108
rs 2
c 1
b 0
f 0
ccs 0
cts 70
cp 0
crap 306

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer;
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
class Excel5 extends BaseWriter implements IWriter
28
{
29
    /**
30
     * PhpSpreadsheet object
31
     *
32
     * @var \PhpOffice\PhpSpreadsheet\Spreadsheet
33
     */
34
    private $spreadsheet;
35
36
    /**
37
     * Total number of shared strings in workbook
38
     *
39
     * @var int
40
     */
41
    private $strTotal = 0;
42
43
    /**
44
     * Number of unique shared strings in workbook
45
     *
46
     * @var int
47
     */
48
    private $strUnique = 0;
49
50
    /**
51
     * Array of unique shared strings in workbook
52
     *
53
     * @var array
54
     */
55
    private $strTable = [];
56
57
    /**
58
     * Color cache. Mapping between RGB value and color index.
59
     *
60
     * @var array
61
     */
62
    private $colors;
63
64
    /**
65
     * Formula parser
66
     *
67
     * @var \PhpOffice\PhpSpreadsheet\Writer\Excel5\Parser
68
     */
69
    private $parser;
70
71
    /**
72
     * Identifier clusters for drawings. Used in MSODRAWINGGROUP record.
73
     *
74
     * @var array
75
     */
76
    private $IDCLs;
77
78
    /**
79
     * Basic OLE object summary information
80
     *
81
     * @var array
82
     */
83
    private $summaryInformation;
84
85
    /**
86
     * Extended OLE object document summary information
87
     *
88
     * @var array
89
     */
90
    private $documentSummaryInformation;
91
92
    /**
93
     * Create a new Excel5 Writer
94
     *
95
     * @param    \PhpOffice\PhpSpreadsheet\Spreadsheet    $spreadsheet    PhpSpreadsheet object
96
     */
97
    public function __construct(\PhpOffice\PhpSpreadsheet\Spreadsheet $spreadsheet)
98
    {
99
        $this->spreadsheet = $spreadsheet;
100
101
        $this->parser = new Excel5\Parser();
102
    }
103
104
    /**
105
     * Save Spreadsheet to file
106
     *
107
     * @param    string        $pFilename
108
     * @throws    \PhpOffice\PhpSpreadsheet\Writer\Exception
109
     */
110
    public function save($pFilename = null)
111
    {
112
113
        // garbage collect
114
        $this->spreadsheet->garbageCollect();
115
116
        $saveDebugLog = \PhpOffice\PhpSpreadsheet\Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
117
        \PhpOffice\PhpSpreadsheet\Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
118
        $saveDateReturnType = \PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType();
119
        \PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType(\PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL);
120
121
        // initialize colors array
122
        $this->colors = [];
123
124
        // Initialise workbook writer
125
        $this->writerWorkbook = new Excel5\Workbook($this->spreadsheet, $this->strTotal, $this->strUnique, $this->strTable, $this->colors, $this->parser);
0 ignored issues
show
Bug introduced by
The property writerWorkbook 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...
126
127
        // Initialise worksheet writers
128
        $countSheets = $this->spreadsheet->getSheetCount();
129
        for ($i = 0; $i < $countSheets; ++$i) {
130
            $this->writerWorksheets[$i] = new Excel5\Worksheet($this->strTotal, $this->strUnique, $this->strTable, $this->colors, $this->parser, $this->preCalculateFormulas, $this->spreadsheet->getSheet($i));
0 ignored issues
show
Bug introduced by
The property writerWorksheets 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...
Documentation introduced by
$this->spreadsheet->getSheet($i) is of type object<PhpOffice\PhpSpreadsheet\Worksheet>, 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...
131
        }
132
133
        // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook.
134
        $this->buildWorksheetEschers();
135
        $this->buildWorkbookEscher();
136
137
        // add 15 identical cell style Xfs
138
        // for now, we use the first cellXf instead of cellStyleXf
139
        $cellXfCollection = $this->spreadsheet->getCellXfCollection();
140
        for ($i = 0; $i < 15; ++$i) {
141
            $this->writerWorkbook->addXfWriter($cellXfCollection[0], true);
142
        }
143
144
        // add all the cell Xfs
145
        foreach ($this->spreadsheet->getCellXfCollection() as $style) {
146
            $this->writerWorkbook->addXfWriter($style, false);
147
        }
148
149
        // add fonts from rich text eleemnts
150
        for ($i = 0; $i < $countSheets; ++$i) {
151
            foreach ($this->writerWorksheets[$i]->phpSheet->getCellCollection() as $cellID) {
152
                $cell = $this->writerWorksheets[$i]->phpSheet->getCell($cellID);
153
                $cVal = $cell->getValue();
154
                if ($cVal instanceof \PhpOffice\PhpSpreadsheet\RichText) {
155
                    $elements = $cVal->getRichTextElements();
156
                    foreach ($elements as $element) {
157
                        if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
158
                            $font = $element->getFont();
159
                            $this->writerWorksheets[$i]->fontHashIndex[$font->getHashCode()] = $this->writerWorkbook->addFont($font);
160
                        }
161
                    }
162
                }
163
            }
164
        }
165
166
        // initialize OLE file
167
        $workbookStreamName = 'Workbook';
168
        $OLE = new \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\File(\PhpOffice\PhpSpreadsheet\Shared\OLE::ascToUcs($workbookStreamName));
169
170
        // Write the worksheet streams before the global workbook stream,
171
        // because the byte sizes of these are needed in the global workbook stream
172
        $worksheetSizes = [];
173
        for ($i = 0; $i < $countSheets; ++$i) {
174
            $this->writerWorksheets[$i]->close();
175
            $worksheetSizes[] = $this->writerWorksheets[$i]->_datasize;
176
        }
177
178
        // add binary data for global workbook stream
179
        $OLE->append($this->writerWorkbook->writeWorkbook($worksheetSizes));
180
181
        // add binary data for sheet streams
182
        for ($i = 0; $i < $countSheets; ++$i) {
183
            $OLE->append($this->writerWorksheets[$i]->getData());
184
        }
185
186
        $this->documentSummaryInformation = $this->writeDocumentSummaryInformation();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->writeDocumentSummaryInformation() of type string is incompatible with the declared type array of property $documentSummaryInformation.

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...
187
        // initialize OLE Document Summary Information
188 View Code Duplication
        if (isset($this->documentSummaryInformation) && !empty($this->documentSummaryInformation)) {
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...
189
            $OLE_DocumentSummaryInformation = new \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\File(\PhpOffice\PhpSpreadsheet\Shared\OLE::ascToUcs(chr(5) . 'DocumentSummaryInformation'));
190
            $OLE_DocumentSummaryInformation->append($this->documentSummaryInformation);
191
        }
192
193
        $this->summaryInformation = $this->writeSummaryInformation();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->writeSummaryInformation() of type string is incompatible with the declared type array of property $summaryInformation.

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...
194
        // initialize OLE Summary Information
195 View Code Duplication
        if (isset($this->summaryInformation) && !empty($this->summaryInformation)) {
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...
196
            $OLE_SummaryInformation = new \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\File(\PhpOffice\PhpSpreadsheet\Shared\OLE::ascToUcs(chr(5) . 'SummaryInformation'));
197
            $OLE_SummaryInformation->append($this->summaryInformation);
198
        }
199
200
        // define OLE Parts
201
        $arrRootData = [$OLE];
202
        // initialize OLE Properties file
203
        if (isset($OLE_SummaryInformation)) {
204
            $arrRootData[] = $OLE_SummaryInformation;
205
        }
206
        // initialize OLE Extended Properties file
207
        if (isset($OLE_DocumentSummaryInformation)) {
208
            $arrRootData[] = $OLE_DocumentSummaryInformation;
209
        }
210
211
        $root = new \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\Root(time(), time(), $arrRootData);
212
        // save the OLE file
213
        $res = $root->save($pFilename);
0 ignored issues
show
Unused Code introduced by
$res 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...
214
215
        \PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType($saveDateReturnType);
216
        \PhpOffice\PhpSpreadsheet\Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
217
    }
218
219
    /**
220
     * Set temporary storage directory
221
     *
222
     * @deprecated
223
     * @param    string    $pValue        Temporary storage directory
224
     * @throws    \PhpOffice\PhpSpreadsheet\Writer\Exception    when directory does not exist
225
     * @return \PhpOffice\PhpSpreadsheet\Writer\Excel5
226
     */
227
    public function setTempDir($pValue = '')
0 ignored issues
show
Unused Code introduced by
The parameter $pValue is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
228
    {
229
        return $this;
230
    }
231
232
    /**
233
     * Build the Worksheet Escher objects
234
     */
235
    private function buildWorksheetEschers()
236
    {
237
        // 1-based index to BstoreContainer
238
        $blipIndex = 0;
239
        $lastReducedSpId = 0;
240
        $lastSpId = 0;
241
242
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
243
            // sheet index
244
            $sheetIndex = $sheet->getParent()->getIndex($sheet);
245
246
            $escher = null;
0 ignored issues
show
Unused Code introduced by
$escher 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...
247
248
            // check if there are any shapes for this sheet
249
            $filterRange = $sheet->getAutoFilter()->getRange();
250
            if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) {
251
                continue;
252
            }
253
254
            // create intermediate Escher object
255
            $escher = new \PhpOffice\PhpSpreadsheet\Shared\Escher();
256
257
            // dgContainer
258
            $dgContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer();
259
260
            // set the drawing index (we use sheet index + 1)
261
            $dgId = $sheet->getParent()->getIndex($sheet) + 1;
262
            $dgContainer->setDgId($dgId);
263
            $escher->setDgContainer($dgContainer);
264
265
            // spgrContainer
266
            $spgrContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer();
267
            $dgContainer->setSpgrContainer($spgrContainer);
268
269
            // add one shape which is the group shape
270
            $spContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer();
271
            $spContainer->setSpgr(true);
272
            $spContainer->setSpType(0);
273
            $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
274
            $spgrContainer->addChild($spContainer);
275
276
            // add the shapes
277
278
            $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet
0 ignored issues
show
Coding Style Comprehensibility introduced by
$countShapes was never initialized. Although not strictly required by PHP, it is generally a good practice to add $countShapes = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
279
280
            foreach ($sheet->getDrawingCollection() as $drawing) {
281
                ++$blipIndex;
282
283
                ++$countShapes[$sheetIndex];
0 ignored issues
show
Bug introduced by
The variable $countShapes 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...
284
285
                // add the shape
286
                $spContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer();
287
288
                // set the shape type
289
                $spContainer->setSpType(0x004B);
290
                // set the shape flag
291
                $spContainer->setSpFlag(0x02);
292
293
                // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
294
                $reducedSpId = $countShapes[$sheetIndex];
295
                $spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
296
                $spContainer->setSpId($spId);
297
298
                // keep track of last reducedSpId
299
                $lastReducedSpId = $reducedSpId;
300
301
                // keep track of last spId
302
                $lastSpId = $spId;
303
304
                // set the BLIP index
305
                $spContainer->setOPT(0x4104, $blipIndex);
306
307
                // set coordinates and offsets, client anchor
308
                $coordinates = $drawing->getCoordinates();
309
                $offsetX = $drawing->getOffsetX();
310
                $offsetY = $drawing->getOffsetY();
311
                $width = $drawing->getWidth();
312
                $height = $drawing->getHeight();
313
314
                $twoAnchor = \PhpOffice\PhpSpreadsheet\Shared\Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
315
316
                $spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
317
                $spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
318
                $spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
319
                $spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
320
                $spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
321
                $spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
322
323
                $spgrContainer->addChild($spContainer);
324
            }
325
326
            // AutoFilters
327
            if (!empty($filterRange)) {
328
                $rangeBounds = \PhpOffice\PhpSpreadsheet\Cell::rangeBoundaries($filterRange);
329
                $iNumColStart = $rangeBounds[0][0];
330
                $iNumColEnd = $rangeBounds[1][0];
331
332
                $iInc = $iNumColStart;
333
                while ($iInc <= $iNumColEnd) {
334
                    ++$countShapes[$sheetIndex];
335
336
                    // create an Drawing Object for the dropdown
337
                    $oDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing();
338
                    // get the coordinates of drawing
339
                    $cDrawing = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1];
340
                    $oDrawing->setCoordinates($cDrawing);
341
                    $oDrawing->setWorksheet($sheet);
342
343
                    // add the shape
344
                    $spContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer();
345
                    // set the shape type
346
                    $spContainer->setSpType(0x00C9);
347
                    // set the shape flag
348
                    $spContainer->setSpFlag(0x01);
349
350
                    // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
351
                    $reducedSpId = $countShapes[$sheetIndex];
352
                    $spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
353
                    $spContainer->setSpId($spId);
354
355
                    // keep track of last reducedSpId
356
                    $lastReducedSpId = $reducedSpId;
357
358
                    // keep track of last spId
359
                    $lastSpId = $spId;
360
361
                    $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping
362
                    $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape
363
                    $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest
364
                    $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash
365
                    $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint
366
367
                    // set coordinates and offsets, client anchor
368
                    $endCoordinates = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($iInc - 1);
369
                    $endCoordinates .= $rangeBounds[0][1] + 1;
370
371
                    $spContainer->setStartCoordinates($cDrawing);
372
                    $spContainer->setStartOffsetX(0);
373
                    $spContainer->setStartOffsetY(0);
374
                    $spContainer->setEndCoordinates($endCoordinates);
375
                    $spContainer->setEndOffsetX(0);
376
                    $spContainer->setEndOffsetY(0);
377
378
                    $spgrContainer->addChild($spContainer);
379
                    ++$iInc;
380
                }
381
            }
382
383
            // identifier clusters, used for workbook Escher object
384
            $this->IDCLs[$dgId] = $lastReducedSpId;
385
386
            // set last shape index
387
            $dgContainer->setLastSpId($lastSpId);
388
389
            // set the Escher object
390
            $this->writerWorksheets[$sheetIndex]->setEscher($escher);
391
        }
392
    }
393
394
    /**
395
     * Build the Escher object corresponding to the MSODRAWINGGROUP record
396
     */
397
    private function buildWorkbookEscher()
398
    {
399
        $escher = null;
0 ignored issues
show
Unused Code introduced by
$escher 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...
400
401
        // any drawings in this workbook?
402
        $found = false;
403
        foreach ($this->spreadsheet->getAllSheets() as $sheet) {
404
            if (count($sheet->getDrawingCollection()) > 0) {
405
                $found = true;
406
                break;
407
            }
408
        }
409
410
        // nothing to do if there are no drawings
411
        if (!$found) {
412
            return;
413
        }
414
415
        // if we reach here, then there are drawings in the workbook
416
        $escher = new \PhpOffice\PhpSpreadsheet\Shared\Escher();
417
418
        // dggContainer
419
        $dggContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer();
420
        $escher->setDggContainer($dggContainer);
421
422
        // set IDCLs (identifier clusters)
423
        $dggContainer->setIDCLs($this->IDCLs);
424
425
        // this loop is for determining maximum shape identifier of all drawing
426
        $spIdMax = 0;
427
        $totalCountShapes = 0;
428
        $countDrawings = 0;
429
430
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
431
            $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet
432
433
            if (count($sheet->getDrawingCollection()) > 0) {
434
                ++$countDrawings;
435
436
                foreach ($sheet->getDrawingCollection() as $drawing) {
437
                    ++$sheetCountShapes;
438
                    ++$totalCountShapes;
439
440
                    $spId = $sheetCountShapes | ($this->spreadsheet->getIndex($sheet) + 1) << 10;
441
                    $spIdMax = max($spId, $spIdMax);
442
                }
443
            }
444
        }
445
446
        $dggContainer->setSpIdMax($spIdMax + 1);
447
        $dggContainer->setCDgSaved($countDrawings);
448
        $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing
449
450
        // bstoreContainer
451
        $bstoreContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer();
452
        $dggContainer->setBstoreContainer($bstoreContainer);
453
454
        // the BSE's (all the images)
455
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
456
            foreach ($sheet->getDrawingCollection() as $drawing) {
457
                if ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing) {
458
                    $filename = $drawing->getPath();
459
460
                    list($imagesx, $imagesy, $imageFormat) = getimagesize($filename);
0 ignored issues
show
Unused Code introduced by
The assignment to $imagesx is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $imagesy is unused. Consider omitting it like so list($first,,$third).

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

Consider the following code example.

<?php

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

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

print $a . " - " . $c;

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

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
461
462
                    switch ($imageFormat) {
463
                        case 1: // GIF, not supported by BIFF8, we convert to PNG
464
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
465
                            ob_start();
466
                            imagepng(imagecreatefromgif($filename));
467
                            $blipData = ob_get_contents();
468
                            ob_end_clean();
469
                            break;
470
                        case 2: // JPEG
471
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_JPEG;
472
                            $blipData = file_get_contents($filename);
473
                            break;
474
                        case 3: // PNG
475
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
476
                            $blipData = file_get_contents($filename);
477
                            break;
478
                        case 6: // Windows DIB (BMP), we convert to PNG
479
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
480
                            ob_start();
481
                            imagepng(\PhpOffice\PhpSpreadsheet\Shared\Drawing::imagecreatefrombmp($filename));
482
                            $blipData = ob_get_contents();
483
                            ob_end_clean();
484
                            break;
485
                        default:
486
                            continue 2;
487
                    }
488
489
                    $blip = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\Blip();
490
                    $blip->setData($blipData);
491
492
                    $BSE = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE();
493
                    $BSE->setBlipType($blipType);
494
                    $BSE->setBlip($blip);
495
496
                    $bstoreContainer->addBSE($BSE);
497
                } elseif ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) {
498
                    switch ($drawing->getRenderingFunction()) {
499
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_JPEG:
500
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_JPEG;
501
                            $renderingFunction = 'imagejpeg';
502
                            break;
503
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_GIF:
504
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_PNG:
505
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_DEFAULT:
506
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
507
                            $renderingFunction = 'imagepng';
508
                            break;
509
                    }
510
511
                    ob_start();
512
                    call_user_func($renderingFunction, $drawing->getImageResource());
0 ignored issues
show
Bug introduced by
The variable $renderingFunction 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...
513
                    $blipData = ob_get_contents();
514
                    ob_end_clean();
515
516
                    $blip = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\Blip();
517
                    $blip->setData($blipData);
518
519
                    $BSE = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE();
520
                    $BSE->setBlipType($blipType);
0 ignored issues
show
Bug introduced by
The variable $blipType 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...
521
                    $BSE->setBlip($blip);
522
523
                    $bstoreContainer->addBSE($BSE);
524
                }
525
            }
526
        }
527
528
        // Set the Escher object
529
        $this->writerWorkbook->setEscher($escher);
530
    }
531
532
    /**
533
     * Build the OLE Part for DocumentSummary Information
534
     * @return string
535
     */
536
    private function writeDocumentSummaryInformation()
537
    {
538
        // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
539
        $data = pack('v', 0xFFFE);
540
        // offset: 2; size: 2;
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...
541
        $data .= pack('v', 0x0000);
542
        // offset: 4; size: 2; OS version
543
        $data .= pack('v', 0x0106);
544
        // offset: 6; size: 2; OS indicator
545
        $data .= pack('v', 0x0002);
546
        // offset: 8; size: 16
547
        $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
548
        // offset: 24; size: 4; section count
549
        $data .= pack('V', 0x0001);
550
551
        // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae
552
        $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9);
553
        // offset: 44; size: 4; offset of the start
554
        $data .= pack('V', 0x30);
555
556
        // SECTION
557
        $dataSection = [];
558
        $dataSection_NumProps = 0;
559
        $dataSection_Summary = '';
560
        $dataSection_Content = '';
561
562
        // GKPIDDSI_CODEPAGE: CodePage
563
        $dataSection[] = [
564
            'summary' => ['pack' => 'V', 'data' => 0x01],
565
            'offset' => ['pack' => 'V'],
566
            'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
567
            'data' => ['data' => 1252],
568
        ];
569
        ++$dataSection_NumProps;
570
571
        // GKPIDDSI_CATEGORY : Category
572 View Code Duplication
        if ($this->spreadsheet->getProperties()->getCategory()) {
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...
573
            $dataProp = $this->spreadsheet->getProperties()->getCategory();
574
            $dataSection[] = [
575
                'summary' => ['pack' => 'V', 'data' => 0x02],
576
                'offset' => ['pack' => 'V'],
577
                'type' => ['pack' => 'V', 'data' => 0x1E],
578
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
579
            ];
580
            ++$dataSection_NumProps;
581
        }
582
        // GKPIDDSI_VERSION :Version of the application that wrote the property storage
583
        $dataSection[] = [
584
            'summary' => ['pack' => 'V', 'data' => 0x17],
585
            'offset' => ['pack' => 'V'],
586
            'type' => ['pack' => 'V', 'data' => 0x03],
587
            'data' => ['pack' => 'V', 'data' => 0x000C0000],
588
        ];
589
        ++$dataSection_NumProps;
590
        // GKPIDDSI_SCALE : FALSE
591
        $dataSection[] = [
592
            'summary' => ['pack' => 'V', 'data' => 0x0B],
593
            'offset' => ['pack' => 'V'],
594
            'type' => ['pack' => 'V', 'data' => 0x0B],
595
            'data' => ['data' => false],
596
        ];
597
        ++$dataSection_NumProps;
598
        // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application
599
        $dataSection[] = [
600
            'summary' => ['pack' => 'V', 'data' => 0x10],
601
            'offset' => ['pack' => 'V'],
602
            'type' => ['pack' => 'V', 'data' => 0x0B],
603
            'data' => ['data' => false],
604
        ];
605
        ++$dataSection_NumProps;
606
        // GKPIDDSI_SHAREDOC : FALSE
607
        $dataSection[] = [
608
            'summary' => ['pack' => 'V', 'data' => 0x13],
609
            'offset' => ['pack' => 'V'],
610
            'type' => ['pack' => 'V', 'data' => 0x0B],
611
            'data' => ['data' => false],
612
        ];
613
        ++$dataSection_NumProps;
614
        // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application
615
        $dataSection[] = [
616
            'summary' => ['pack' => 'V', 'data' => 0x16],
617
            'offset' => ['pack' => 'V'],
618
            'type' => ['pack' => 'V', 'data' => 0x0B],
619
            'data' => ['data' => false],
620
        ];
621
        ++$dataSection_NumProps;
622
623
        // GKPIDDSI_DOCSPARTS
624
        // MS-OSHARED p75 (2.3.3.2.2.1)
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...
625
        // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9)
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...
626
        // cElements
627
        $dataProp = pack('v', 0x0001);
628
        $dataProp .= pack('v', 0x0000);
629
        // array of UnalignedLpstr
630
        // cch
631
        $dataProp .= pack('v', 0x000A);
632
        $dataProp .= pack('v', 0x0000);
633
        // value
634
        $dataProp .= 'Worksheet' . chr(0);
635
636
        $dataSection[] = [
637
            'summary' => ['pack' => 'V', 'data' => 0x0D],
638
            'offset' => ['pack' => 'V'],
639
            'type' => ['pack' => 'V', 'data' => 0x101E],
640
            'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
641
        ];
642
        ++$dataSection_NumProps;
643
644
        // GKPIDDSI_HEADINGPAIR
645
        // VtVecHeadingPairValue
646
        // cElements
647
        $dataProp = pack('v', 0x0002);
648
        $dataProp .= pack('v', 0x0000);
649
        // Array of vtHeadingPair
650
        // vtUnalignedString - headingString
651
        // stringType
652
        $dataProp .= pack('v', 0x001E);
653
        // padding
654
        $dataProp .= pack('v', 0x0000);
655
        // UnalignedLpstr
656
        // cch
657
        $dataProp .= pack('v', 0x0013);
658
        $dataProp .= pack('v', 0x0000);
659
        // value
660
        $dataProp .= 'Feuilles de calcul';
661
        // vtUnalignedString - headingParts
662
        // wType : 0x0003 = 32 bit signed integer
663
        $dataProp .= pack('v', 0x0300);
664
        // padding
665
        $dataProp .= pack('v', 0x0000);
666
        // value
667
        $dataProp .= pack('v', 0x0100);
668
        $dataProp .= pack('v', 0x0000);
669
        $dataProp .= pack('v', 0x0000);
670
        $dataProp .= pack('v', 0x0000);
671
672
        $dataSection[] = [
673
            'summary' => ['pack' => 'V', 'data' => 0x0C],
674
            'offset' => ['pack' => 'V'],
675
            'type' => ['pack' => 'V', 'data' => 0x100C],
676
            'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
677
        ];
678
        ++$dataSection_NumProps;
679
680
        //         4     Section Length
681
        //        4     Property count
682
        //        8 * $dataSection_NumProps (8 =  ID (4) + OffSet(4))
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% 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...
683
        $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
684
        foreach ($dataSection as $dataProp) {
685
            // Summary
686
            $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
687
            // Offset
688
            $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
689
            // DataType
690
            $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
691
            // Data
692
            if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
693
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
694
695
                $dataSection_Content_Offset += 4 + 4;
696
            } elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
697
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
698
699
                $dataSection_Content_Offset += 4 + 4;
700
            } elseif ($dataProp['type']['data'] == 0x0B) { // Boolean
701
                if ($dataProp['data']['data'] == false) {
702
                    $dataSection_Content .= pack('V', 0x0000);
703
                } else {
704
                    $dataSection_Content .= pack('V', 0x0001);
705
                }
706
                $dataSection_Content_Offset += 4 + 4;
707 View Code Duplication
            } elseif ($dataProp['type']['data'] == 0x1E) { // null-terminated string prepended by dword string length
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...
708
                // Null-terminated string
709
                $dataProp['data']['data'] .= chr(0);
710
                $dataProp['data']['length'] += 1;
711
                // Complete the string with null string for being a %4
712
                $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
713
                $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
714
715
                $dataSection_Content .= pack('V', $dataProp['data']['length']);
716
                $dataSection_Content .= $dataProp['data']['data'];
717
718
                $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
719
            } elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
720
                $dataSection_Content .= $dataProp['data']['data'];
721
722
                $dataSection_Content_Offset += 4 + 8;
723
            } else {
724
                // Data Type Not Used at the moment
725
                $dataSection_Content .= $dataProp['data']['data'];
726
727
                $dataSection_Content_Offset += 4 + $dataProp['data']['length'];
728
            }
729
        }
730
        // Now $dataSection_Content_Offset contains the size of the content
731
732
        // section header
733
        // offset: $secOffset; size: 4; section length
734
        //         + x  Size of the content (summary + content)
735
        $data .= pack('V', $dataSection_Content_Offset);
736
        // offset: $secOffset+4; size: 4; property count
737
        $data .= pack('V', $dataSection_NumProps);
738
        // Section Summary
739
        $data .= $dataSection_Summary;
740
        // Section Content
741
        $data .= $dataSection_Content;
742
743
        return $data;
744
    }
745
746
    /**
747
     * Build the OLE Part for Summary Information
748
     * @return string
749
     */
750
    private function writeSummaryInformation()
751
    {
752
        // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
753
        $data = pack('v', 0xFFFE);
754
        // offset: 2; size: 2;
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...
755
        $data .= pack('v', 0x0000);
756
        // offset: 4; size: 2; OS version
757
        $data .= pack('v', 0x0106);
758
        // offset: 6; size: 2; OS indicator
759
        $data .= pack('v', 0x0002);
760
        // offset: 8; size: 16
761
        $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
762
        // offset: 24; size: 4; section count
763
        $data .= pack('V', 0x0001);
764
765
        // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9
766
        $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3);
767
        // offset: 44; size: 4; offset of the start
768
        $data .= pack('V', 0x30);
769
770
        // SECTION
771
        $dataSection = [];
772
        $dataSection_NumProps = 0;
773
        $dataSection_Summary = '';
774
        $dataSection_Content = '';
775
776
        // CodePage : CP-1252
777
        $dataSection[] = [
778
            'summary' => ['pack' => 'V', 'data' => 0x01],
779
            'offset' => ['pack' => 'V'],
780
            'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
781
            'data' => ['data' => 1252],
782
        ];
783
        ++$dataSection_NumProps;
784
785
        //    Title
786 View Code Duplication
        if ($this->spreadsheet->getProperties()->getTitle()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
787
            $dataProp = $this->spreadsheet->getProperties()->getTitle();
788
            $dataSection[] = [
789
                'summary' => ['pack' => 'V', 'data' => 0x02],
790
                'offset' => ['pack' => 'V'],
791
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
792
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
793
            ];
794
            ++$dataSection_NumProps;
795
        }
796
        //    Subject
797 View Code Duplication
        if ($this->spreadsheet->getProperties()->getSubject()) {
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...
798
            $dataProp = $this->spreadsheet->getProperties()->getSubject();
799
            $dataSection[] = [
800
                'summary' => ['pack' => 'V', 'data' => 0x03],
801
                'offset' => ['pack' => 'V'],
802
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
803
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
804
            ];
805
            ++$dataSection_NumProps;
806
        }
807
        //    Author (Creator)
808 View Code Duplication
        if ($this->spreadsheet->getProperties()->getCreator()) {
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...
809
            $dataProp = $this->spreadsheet->getProperties()->getCreator();
810
            $dataSection[] = [
811
                'summary' => ['pack' => 'V', 'data' => 0x04],
812
                'offset' => ['pack' => 'V'],
813
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
814
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
815
            ];
816
            ++$dataSection_NumProps;
817
        }
818
        //    Keywords
819 View Code Duplication
        if ($this->spreadsheet->getProperties()->getKeywords()) {
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...
820
            $dataProp = $this->spreadsheet->getProperties()->getKeywords();
821
            $dataSection[] = [
822
                'summary' => ['pack' => 'V', 'data' => 0x05],
823
                'offset' => ['pack' => 'V'],
824
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
825
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
826
            ];
827
            ++$dataSection_NumProps;
828
        }
829
        //    Comments (Description)
830 View Code Duplication
        if ($this->spreadsheet->getProperties()->getDescription()) {
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...
831
            $dataProp = $this->spreadsheet->getProperties()->getDescription();
832
            $dataSection[] = [
833
                'summary' => ['pack' => 'V', 'data' => 0x06],
834
                'offset' => ['pack' => 'V'],
835
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
836
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
837
            ];
838
            ++$dataSection_NumProps;
839
        }
840
        //    Last Saved By (LastModifiedBy)
841 View Code Duplication
        if ($this->spreadsheet->getProperties()->getLastModifiedBy()) {
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...
842
            $dataProp = $this->spreadsheet->getProperties()->getLastModifiedBy();
843
            $dataSection[] = [
844
                'summary' => ['pack' => 'V', 'data' => 0x08],
845
                'offset' => ['pack' => 'V'],
846
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
847
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
848
            ];
849
            ++$dataSection_NumProps;
850
        }
851
        //    Created Date/Time
852 View Code Duplication
        if ($this->spreadsheet->getProperties()->getCreated()) {
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...
853
            $dataProp = $this->spreadsheet->getProperties()->getCreated();
854
            $dataSection[] = [
855
                'summary' => ['pack' => 'V', 'data' => 0x0C],
856
                'offset' => ['pack' => 'V'],
857
                'type' => ['pack' => 'V', 'data' => 0x40], // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
858
                'data' => ['data' => \PhpOffice\PhpSpreadsheet\Shared\OLE::localDateToOLE($dataProp)],
859
            ];
860
            ++$dataSection_NumProps;
861
        }
862
        //    Modified Date/Time
863 View Code Duplication
        if ($this->spreadsheet->getProperties()->getModified()) {
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...
864
            $dataProp = $this->spreadsheet->getProperties()->getModified();
865
            $dataSection[] = [
866
                'summary' => ['pack' => 'V', 'data' => 0x0D],
867
                'offset' => ['pack' => 'V'],
868
                'type' => ['pack' => 'V', 'data' => 0x40], // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
869
                'data' => ['data' => \PhpOffice\PhpSpreadsheet\Shared\OLE::localDateToOLE($dataProp)],
870
            ];
871
            ++$dataSection_NumProps;
872
        }
873
        //    Security
874
        $dataSection[] = [
875
            'summary' => ['pack' => 'V', 'data' => 0x13],
876
            'offset' => ['pack' => 'V'],
877
            'type' => ['pack' => 'V', 'data' => 0x03], // 4 byte signed integer
878
            'data' => ['data' => 0x00],
879
        ];
880
        ++$dataSection_NumProps;
881
882
        //         4     Section Length
883
        //        4     Property count
884
        //        8 * $dataSection_NumProps (8 =  ID (4) + OffSet(4))
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% 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...
885
        $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
886
        foreach ($dataSection as $dataProp) {
887
            // Summary
888
            $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
889
            // Offset
890
            $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
891
            // DataType
892
            $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
893
            // Data
894
            if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
895
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
896
897
                $dataSection_Content_Offset += 4 + 4;
898
            } elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
899
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
900
901
                $dataSection_Content_Offset += 4 + 4;
902 View Code Duplication
            } elseif ($dataProp['type']['data'] == 0x1E) { // null-terminated string prepended by dword string length
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...
903
                // Null-terminated string
904
                $dataProp['data']['data'] .= chr(0);
905
                $dataProp['data']['length'] += 1;
906
                // Complete the string with null string for being a %4
907
                $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
908
                $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
909
910
                $dataSection_Content .= pack('V', $dataProp['data']['length']);
911
                $dataSection_Content .= $dataProp['data']['data'];
912
913
                $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
914
            } elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
915
                $dataSection_Content .= $dataProp['data']['data'];
916
917
                $dataSection_Content_Offset += 4 + 8;
918
            } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if 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 else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
919
                // Data Type Not Used at the moment
920
            }
921
        }
922
        // Now $dataSection_Content_Offset contains the size of the content
923
924
        // section header
925
        // offset: $secOffset; size: 4; section length
926
        //         + x  Size of the content (summary + content)
927
        $data .= pack('V', $dataSection_Content_Offset);
928
        // offset: $secOffset+4; size: 4; property count
929
        $data .= pack('V', $dataSection_NumProps);
930
        // Section Summary
931
        $data .= $dataSection_Summary;
932
        // Section Content
933
        $data .= $dataSection_Content;
934
935
        return $data;
936
    }
937
}
938