Completed
Push — develop ( 03f96a...8c66af )
by Adrien
19:36
created

Xls::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
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
 *
24
 * @copyright  Copyright (c) 2006 - 2015 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
25
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
26
 */
27
class Xls 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\Xls\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 Xls Writer.
94
     *
95
     * @param    \PhpOffice\PhpSpreadsheet\Spreadsheet    $spreadsheet    PhpSpreadsheet object
96
     */
97 38
    public function __construct(\PhpOffice\PhpSpreadsheet\Spreadsheet $spreadsheet)
98
    {
99 38
        $this->spreadsheet = $spreadsheet;
100
101 38
        $this->parser = new Xls\Parser();
102 38
    }
103
104
    /**
105
     * Save Spreadsheet to file.
106
     *
107
     * @param    string        $pFilename
108
     *
109
     * @throws    \PhpOffice\PhpSpreadsheet\Writer\Exception
110
     */
111 38
    public function save($pFilename = null)
112
    {
113
        // garbage collect
114 38
        $this->spreadsheet->garbageCollect();
115
116 38
        $saveDebugLog = \PhpOffice\PhpSpreadsheet\Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
117 38
        \PhpOffice\PhpSpreadsheet\Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
118 38
        $saveDateReturnType = \PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType();
119 38
        \PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType(\PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL);
120
121
        // initialize colors array
122 38
        $this->colors = [];
123
124
        // Initialise workbook writer
125 38
        $this->writerWorkbook = new Xls\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 38
        $countSheets = $this->spreadsheet->getSheetCount();
129 38
        for ($i = 0; $i < $countSheets; ++$i) {
130 38
            $this->writerWorksheets[$i] = new Xls\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 38
        $this->buildWorksheetEschers();
135 38
        $this->buildWorkbookEscher();
136
137
        // add 15 identical cell style Xfs
138
        // for now, we use the first cellXf instead of cellStyleXf
139 38
        $cellXfCollection = $this->spreadsheet->getCellXfCollection();
140 38
        for ($i = 0; $i < 15; ++$i) {
141 38
            $this->writerWorkbook->addXfWriter($cellXfCollection[0], true);
142
        }
143
144
        // add all the cell Xfs
145 38
        foreach ($this->spreadsheet->getCellXfCollection() as $style) {
146 38
            $this->writerWorkbook->addXfWriter($style, false);
147
        }
148
149
        // add fonts from rich text eleemnts
150 38
        for ($i = 0; $i < $countSheets; ++$i) {
151 38
            foreach ($this->writerWorksheets[$i]->phpSheet->getCellCollection() as $cellID) {
152 38
                $cell = $this->writerWorksheets[$i]->phpSheet->getCell($cellID);
153 38
                $cVal = $cell->getValue();
154 38
                if ($cVal instanceof \PhpOffice\PhpSpreadsheet\RichText) {
155 9
                    $elements = $cVal->getRichTextElements();
156 9
                    foreach ($elements as $element) {
157 9
                        if ($element instanceof \PhpOffice\PhpSpreadsheet\RichText\Run) {
158 9
                            $font = $element->getFont();
159 38
                            $this->writerWorksheets[$i]->fontHashIndex[$font->getHashCode()] = $this->writerWorkbook->addFont($font);
160
                        }
161
                    }
162
                }
163
            }
164
        }
165
166
        // initialize OLE file
167 38
        $workbookStreamName = 'Workbook';
168 38
        $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 38
        $worksheetSizes = [];
173 38
        for ($i = 0; $i < $countSheets; ++$i) {
174 38
            $this->writerWorksheets[$i]->close();
175 38
            $worksheetSizes[] = $this->writerWorksheets[$i]->_datasize;
176
        }
177
178
        // add binary data for global workbook stream
179 38
        $OLE->append($this->writerWorkbook->writeWorkbook($worksheetSizes));
180
181
        // add binary data for sheet streams
182 38
        for ($i = 0; $i < $countSheets; ++$i) {
183 38
            $OLE->append($this->writerWorksheets[$i]->getData());
184
        }
185
186 38
        $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 38 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 38
            $OLE_DocumentSummaryInformation = new \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\File(\PhpOffice\PhpSpreadsheet\Shared\OLE::ascToUcs(chr(5) . 'DocumentSummaryInformation'));
190 38
            $OLE_DocumentSummaryInformation->append($this->documentSummaryInformation);
191
        }
192
193 38
        $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 38 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 38
            $OLE_SummaryInformation = new \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\File(\PhpOffice\PhpSpreadsheet\Shared\OLE::ascToUcs(chr(5) . 'SummaryInformation'));
197 38
            $OLE_SummaryInformation->append($this->summaryInformation);
198
        }
199
200
        // define OLE Parts
201 38
        $arrRootData = [$OLE];
202
        // initialize OLE Properties file
203 38
        if (isset($OLE_SummaryInformation)) {
204 38
            $arrRootData[] = $OLE_SummaryInformation;
205
        }
206
        // initialize OLE Extended Properties file
207 38
        if (isset($OLE_DocumentSummaryInformation)) {
208 38
            $arrRootData[] = $OLE_DocumentSummaryInformation;
209
        }
210
211 38
        $root = new \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\Root(time(), time(), $arrRootData);
212
        // save the OLE file
213 38
        $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 38
        \PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType($saveDateReturnType);
216 38
        \PhpOffice\PhpSpreadsheet\Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
217 38
    }
218
219
    /**
220
     * Build the Worksheet Escher objects.
221
     */
222 38
    private function buildWorksheetEschers()
223
    {
224
        // 1-based index to BstoreContainer
225 38
        $blipIndex = 0;
226 38
        $lastReducedSpId = 0;
227 38
        $lastSpId = 0;
228
229 38
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
230
            // sheet index
231 38
            $sheetIndex = $sheet->getParent()->getIndex($sheet);
232
233 38
            $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...
234
235
            // check if there are any shapes for this sheet
236 38
            $filterRange = $sheet->getAutoFilter()->getRange();
237 38
            if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) {
238 30
                continue;
239
            }
240
241
            // create intermediate Escher object
242 10
            $escher = new \PhpOffice\PhpSpreadsheet\Shared\Escher();
243
244
            // dgContainer
245 10
            $dgContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer();
246
247
            // set the drawing index (we use sheet index + 1)
248 10
            $dgId = $sheet->getParent()->getIndex($sheet) + 1;
249 10
            $dgContainer->setDgId($dgId);
250 10
            $escher->setDgContainer($dgContainer);
251
252
            // spgrContainer
253 10
            $spgrContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer();
254 10
            $dgContainer->setSpgrContainer($spgrContainer);
255
256
            // add one shape which is the group shape
257 10
            $spContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer();
258 10
            $spContainer->setSpgr(true);
259 10
            $spContainer->setSpType(0);
260 10
            $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
261 10
            $spgrContainer->addChild($spContainer);
262
263
            // add the shapes
264
265 10
            $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...
266
267 10
            foreach ($sheet->getDrawingCollection() as $drawing) {
268 7
                ++$blipIndex;
269
270 7
                ++$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...
271
272
                // add the shape
273 7
                $spContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer();
274
275
                // set the shape type
276 7
                $spContainer->setSpType(0x004B);
277
                // set the shape flag
278 7
                $spContainer->setSpFlag(0x02);
279
280
                // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
281 7
                $reducedSpId = $countShapes[$sheetIndex];
282 7
                $spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
283 7
                $spContainer->setSpId($spId);
284
285
                // keep track of last reducedSpId
286 7
                $lastReducedSpId = $reducedSpId;
287
288
                // keep track of last spId
289 7
                $lastSpId = $spId;
290
291
                // set the BLIP index
292 7
                $spContainer->setOPT(0x4104, $blipIndex);
293
294
                // set coordinates and offsets, client anchor
295 7
                $coordinates = $drawing->getCoordinates();
296 7
                $offsetX = $drawing->getOffsetX();
297 7
                $offsetY = $drawing->getOffsetY();
298 7
                $width = $drawing->getWidth();
299 7
                $height = $drawing->getHeight();
300
301 7
                $twoAnchor = \PhpOffice\PhpSpreadsheet\Shared\Xls::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);
302
303 7
                $spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
304 7
                $spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
305 7
                $spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
306 7
                $spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
307 7
                $spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
308 7
                $spContainer->setEndOffsetY($twoAnchor['endOffsetY']);
309
310 7
                $spgrContainer->addChild($spContainer);
311
            }
312
313
            // AutoFilters
314 10
            if (!empty($filterRange)) {
315 3
                $rangeBounds = \PhpOffice\PhpSpreadsheet\Cell::rangeBoundaries($filterRange);
316 3
                $iNumColStart = $rangeBounds[0][0];
317 3
                $iNumColEnd = $rangeBounds[1][0];
318
319 3
                $iInc = $iNumColStart;
320 3
                while ($iInc <= $iNumColEnd) {
321 3
                    ++$countShapes[$sheetIndex];
322
323
                    // create an Drawing Object for the dropdown
324 3
                    $oDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing();
325
                    // get the coordinates of drawing
326 3
                    $cDrawing = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1];
327 3
                    $oDrawing->setCoordinates($cDrawing);
328 3
                    $oDrawing->setWorksheet($sheet);
329
330
                    // add the shape
331 3
                    $spContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer();
332
                    // set the shape type
333 3
                    $spContainer->setSpType(0x00C9);
334
                    // set the shape flag
335 3
                    $spContainer->setSpFlag(0x01);
336
337
                    // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
338 3
                    $reducedSpId = $countShapes[$sheetIndex];
339 3
                    $spId = $reducedSpId | ($sheet->getParent()->getIndex($sheet) + 1) << 10;
340 3
                    $spContainer->setSpId($spId);
341
342
                    // keep track of last reducedSpId
343 3
                    $lastReducedSpId = $reducedSpId;
344
345
                    // keep track of last spId
346 3
                    $lastSpId = $spId;
347
348 3
                    $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping
349 3
                    $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape
350 3
                    $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest
351 3
                    $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash
352 3
                    $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint
353
354
                    // set coordinates and offsets, client anchor
355 3
                    $endCoordinates = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($iInc - 1);
356 3
                    $endCoordinates .= $rangeBounds[0][1] + 1;
357
358 3
                    $spContainer->setStartCoordinates($cDrawing);
359 3
                    $spContainer->setStartOffsetX(0);
360 3
                    $spContainer->setStartOffsetY(0);
361 3
                    $spContainer->setEndCoordinates($endCoordinates);
362 3
                    $spContainer->setEndOffsetX(0);
363 3
                    $spContainer->setEndOffsetY(0);
364
365 3
                    $spgrContainer->addChild($spContainer);
366 3
                    ++$iInc;
367
                }
368
            }
369
370
            // identifier clusters, used for workbook Escher object
371 10
            $this->IDCLs[$dgId] = $lastReducedSpId;
372
373
            // set last shape index
374 10
            $dgContainer->setLastSpId($lastSpId);
375
376
            // set the Escher object
377 10
            $this->writerWorksheets[$sheetIndex]->setEscher($escher);
378
        }
379 38
    }
380
381
    /**
382
     * Build the Escher object corresponding to the MSODRAWINGGROUP record.
383
     */
384 38
    private function buildWorkbookEscher()
385
    {
386 38
        $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...
387
388
        // any drawings in this workbook?
389 38
        $found = false;
390 38
        foreach ($this->spreadsheet->getAllSheets() as $sheet) {
391 38
            if (count($sheet->getDrawingCollection()) > 0) {
392 10
                $found = true;
393 38
                break;
394
            }
395
        }
396
397
        // nothing to do if there are no drawings
398 38
        if (!$found) {
399 29
            return;
400
        }
401
402
        // if we reach here, then there are drawings in the workbook
403 10
        $escher = new \PhpOffice\PhpSpreadsheet\Shared\Escher();
404
405
        // dggContainer
406 10
        $dggContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer();
407 10
        $escher->setDggContainer($dggContainer);
408
409
        // set IDCLs (identifier clusters)
410 10
        $dggContainer->setIDCLs($this->IDCLs);
411
412
        // this loop is for determining maximum shape identifier of all drawing
413 10
        $spIdMax = 0;
414 10
        $totalCountShapes = 0;
415 10
        $countDrawings = 0;
416
417 10
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
418 10
            $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet
419
420 10
            if (count($sheet->getDrawingCollection()) > 0) {
421 10
                ++$countDrawings;
422
423 10
                foreach ($sheet->getDrawingCollection() as $drawing) {
424 10
                    ++$sheetCountShapes;
425 10
                    ++$totalCountShapes;
426
427 10
                    $spId = $sheetCountShapes | ($this->spreadsheet->getIndex($sheet) + 1) << 10;
428 10
                    $spIdMax = max($spId, $spIdMax);
429
                }
430
            }
431
        }
432
433 10
        $dggContainer->setSpIdMax($spIdMax + 1);
434 10
        $dggContainer->setCDgSaved($countDrawings);
435 10
        $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing
436
437
        // bstoreContainer
438 10
        $bstoreContainer = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer();
439 10
        $dggContainer->setBstoreContainer($bstoreContainer);
440
441
        // the BSE's (all the images)
442 10
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
443 10
            foreach ($sheet->getDrawingCollection() as $drawing) {
444 10
                if (!extension_loaded('gd')) {
445
                    throw new \RuntimeException('Saving images in xls requires gd extension');
446
                }
447 10
                if ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing) {
448 5
                    $filename = $drawing->getPath();
449
450 5
                    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...
451
452
                    switch ($imageFormat) {
453 5
                        case 1: // GIF, not supported by BIFF8, we convert to PNG
454
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
455
                            ob_start();
456
                            imagepng(imagecreatefromgif($filename));
457
                            $blipData = ob_get_contents();
458
                            ob_end_clean();
459
                            break;
460 5
                        case 2: // JPEG
461 5
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_JPEG;
462 5
                            $blipData = file_get_contents($filename);
463 5
                            break;
464 5
                        case 3: // PNG
465 5
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
466 5
                            $blipData = file_get_contents($filename);
467 5
                            break;
468
                        case 6: // Windows DIB (BMP), we convert to PNG
469
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
470
                            ob_start();
471
                            imagepng(\PhpOffice\PhpSpreadsheet\Shared\Drawing::imagecreatefrombmp($filename));
472
                            $blipData = ob_get_contents();
473
                            ob_end_clean();
474
                            break;
475
                        default:
476
                            continue 2;
477
                    }
478
479 5
                    $blip = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\Blip();
480 5
                    $blip->setData($blipData);
481
482 5
                    $BSE = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE();
483 5
                    $BSE->setBlipType($blipType);
484 5
                    $BSE->setBlip($blip);
485
486 5
                    $bstoreContainer->addBSE($BSE);
487 3
                } elseif ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) {
488 2
                    switch ($drawing->getRenderingFunction()) {
489 2
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_JPEG:
490 2
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_JPEG;
491 2
                            $renderingFunction = 'imagejpeg';
492 2
                            break;
493 2
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_GIF:
494 2
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_PNG:
495
                        case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::RENDERING_DEFAULT:
496 2
                            $blipType = \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::BLIPTYPE_PNG;
497 2
                            $renderingFunction = 'imagepng';
498 2
                            break;
499
                    }
500
501 2
                    ob_start();
502 2
                    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...
503 2
                    $blipData = ob_get_contents();
504 2
                    ob_end_clean();
505
506 2
                    $blip = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\Blip();
507 2
                    $blip->setData($blipData);
508
509 2
                    $BSE = new \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE();
510 2
                    $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...
511 2
                    $BSE->setBlip($blip);
512
513 10
                    $bstoreContainer->addBSE($BSE);
514
                }
515
            }
516
        }
517
518
        // Set the Escher object
519 10
        $this->writerWorkbook->setEscher($escher);
520 10
    }
521
522
    /**
523
     * Build the OLE Part for DocumentSummary Information.
524
     *
525
     * @return string
526
     */
527 38
    private function writeDocumentSummaryInformation()
528
    {
529
        // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
530 38
        $data = pack('v', 0xFFFE);
531
        // 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...
532 38
        $data .= pack('v', 0x0000);
533
        // offset: 4; size: 2; OS version
534 38
        $data .= pack('v', 0x0106);
535
        // offset: 6; size: 2; OS indicator
536 38
        $data .= pack('v', 0x0002);
537
        // offset: 8; size: 16
538 38
        $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
539
        // offset: 24; size: 4; section count
540 38
        $data .= pack('V', 0x0001);
541
542
        // 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
543 38
        $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9);
544
        // offset: 44; size: 4; offset of the start
545 38
        $data .= pack('V', 0x30);
546
547
        // SECTION
548 38
        $dataSection = [];
549 38
        $dataSection_NumProps = 0;
550 38
        $dataSection_Summary = '';
551 38
        $dataSection_Content = '';
552
553
        // GKPIDDSI_CODEPAGE: CodePage
554 38
        $dataSection[] = [
555
            'summary' => ['pack' => 'V', 'data' => 0x01],
556
            'offset' => ['pack' => 'V'],
557
            'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
558
            'data' => ['data' => 1252],
559
        ];
560 38
        ++$dataSection_NumProps;
561
562
        // GKPIDDSI_CATEGORY : Category
563 38 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...
564 31
            $dataProp = $this->spreadsheet->getProperties()->getCategory();
565 31
            $dataSection[] = [
566 31
                'summary' => ['pack' => 'V', 'data' => 0x02],
567
                'offset' => ['pack' => 'V'],
568
                'type' => ['pack' => 'V', 'data' => 0x1E],
569 31
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
570
            ];
571 31
            ++$dataSection_NumProps;
572
        }
573
        // GKPIDDSI_VERSION :Version of the application that wrote the property storage
574 38
        $dataSection[] = [
575
            'summary' => ['pack' => 'V', 'data' => 0x17],
576
            'offset' => ['pack' => 'V'],
577
            'type' => ['pack' => 'V', 'data' => 0x03],
578
            'data' => ['pack' => 'V', 'data' => 0x000C0000],
579
        ];
580 38
        ++$dataSection_NumProps;
581
        // GKPIDDSI_SCALE : FALSE
582 38
        $dataSection[] = [
583
            'summary' => ['pack' => 'V', 'data' => 0x0B],
584
            'offset' => ['pack' => 'V'],
585
            'type' => ['pack' => 'V', 'data' => 0x0B],
586
            'data' => ['data' => false],
587
        ];
588 38
        ++$dataSection_NumProps;
589
        // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application
590 38
        $dataSection[] = [
591
            'summary' => ['pack' => 'V', 'data' => 0x10],
592
            'offset' => ['pack' => 'V'],
593
            'type' => ['pack' => 'V', 'data' => 0x0B],
594
            'data' => ['data' => false],
595
        ];
596 38
        ++$dataSection_NumProps;
597
        // GKPIDDSI_SHAREDOC : FALSE
598 38
        $dataSection[] = [
599
            'summary' => ['pack' => 'V', 'data' => 0x13],
600
            'offset' => ['pack' => 'V'],
601
            'type' => ['pack' => 'V', 'data' => 0x0B],
602
            'data' => ['data' => false],
603
        ];
604 38
        ++$dataSection_NumProps;
605
        // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application
606 38
        $dataSection[] = [
607
            'summary' => ['pack' => 'V', 'data' => 0x16],
608
            'offset' => ['pack' => 'V'],
609
            'type' => ['pack' => 'V', 'data' => 0x0B],
610
            'data' => ['data' => false],
611
        ];
612 38
        ++$dataSection_NumProps;
613
614
        // GKPIDDSI_DOCSPARTS
615
        // 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...
616
        // 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...
617
        // cElements
618 38
        $dataProp = pack('v', 0x0001);
619 38
        $dataProp .= pack('v', 0x0000);
620
        // array of UnalignedLpstr
621
        // cch
622 38
        $dataProp .= pack('v', 0x000A);
623 38
        $dataProp .= pack('v', 0x0000);
624
        // value
625 38
        $dataProp .= 'Worksheet' . chr(0);
626
627 38
        $dataSection[] = [
628 38
            'summary' => ['pack' => 'V', 'data' => 0x0D],
629
            'offset' => ['pack' => 'V'],
630
            'type' => ['pack' => 'V', 'data' => 0x101E],
631 38
            'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
632
        ];
633 38
        ++$dataSection_NumProps;
634
635
        // GKPIDDSI_HEADINGPAIR
636
        // VtVecHeadingPairValue
637
        // cElements
638 38
        $dataProp = pack('v', 0x0002);
639 38
        $dataProp .= pack('v', 0x0000);
640
        // Array of vtHeadingPair
641
        // vtUnalignedString - headingString
642
        // stringType
643 38
        $dataProp .= pack('v', 0x001E);
644
        // padding
645 38
        $dataProp .= pack('v', 0x0000);
646
        // UnalignedLpstr
647
        // cch
648 38
        $dataProp .= pack('v', 0x0013);
649 38
        $dataProp .= pack('v', 0x0000);
650
        // value
651 38
        $dataProp .= 'Feuilles de calcul';
652
        // vtUnalignedString - headingParts
653
        // wType : 0x0003 = 32 bit signed integer
654 38
        $dataProp .= pack('v', 0x0300);
655
        // padding
656 38
        $dataProp .= pack('v', 0x0000);
657
        // value
658 38
        $dataProp .= pack('v', 0x0100);
659 38
        $dataProp .= pack('v', 0x0000);
660 38
        $dataProp .= pack('v', 0x0000);
661 38
        $dataProp .= pack('v', 0x0000);
662
663 38
        $dataSection[] = [
664 38
            'summary' => ['pack' => 'V', 'data' => 0x0C],
665
            'offset' => ['pack' => 'V'],
666
            'type' => ['pack' => 'V', 'data' => 0x100C],
667 38
            'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
668
        ];
669 38
        ++$dataSection_NumProps;
670
671
        //         4     Section Length
672
        //        4     Property count
673
        //        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...
674 38
        $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
675 38
        foreach ($dataSection as $dataProp) {
676
            // Summary
677 38
            $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
678
            // Offset
679 38
            $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
680
            // DataType
681 38
            $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
682
            // Data
683 38
            if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
684 38
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
685
686 38
                $dataSection_Content_Offset += 4 + 4;
687 38
            } elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
688 38
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
689
690 38
                $dataSection_Content_Offset += 4 + 4;
691 38
            } elseif ($dataProp['type']['data'] == 0x0B) { // Boolean
692 38
                if ($dataProp['data']['data'] == false) {
693 38
                    $dataSection_Content .= pack('V', 0x0000);
694
                } else {
695
                    $dataSection_Content .= pack('V', 0x0001);
696
                }
697 38
                $dataSection_Content_Offset += 4 + 4;
698 38 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...
699
                // Null-terminated string
700 31
                $dataProp['data']['data'] .= chr(0);
701 31
                $dataProp['data']['length'] += 1;
702
                // Complete the string with null string for being a %4
703 31
                $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
704 31
                $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
705
706 31
                $dataSection_Content .= pack('V', $dataProp['data']['length']);
707 31
                $dataSection_Content .= $dataProp['data']['data'];
708
709 31
                $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
710 38
            } elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
711
                $dataSection_Content .= $dataProp['data']['data'];
712
713
                $dataSection_Content_Offset += 4 + 8;
714
            } else {
715
                // Data Type Not Used at the moment
716 38
                $dataSection_Content .= $dataProp['data']['data'];
717
718 38
                $dataSection_Content_Offset += 4 + $dataProp['data']['length'];
719
            }
720
        }
721
        // Now $dataSection_Content_Offset contains the size of the content
722
723
        // section header
724
        // offset: $secOffset; size: 4; section length
725
        //         + x  Size of the content (summary + content)
726 38
        $data .= pack('V', $dataSection_Content_Offset);
727
        // offset: $secOffset+4; size: 4; property count
728 38
        $data .= pack('V', $dataSection_NumProps);
729
        // Section Summary
730 38
        $data .= $dataSection_Summary;
731
        // Section Content
732 38
        $data .= $dataSection_Content;
733
734 38
        return $data;
735
    }
736
737
    /**
738
     * Build the OLE Part for Summary Information.
739
     *
740
     * @return string
741
     */
742 38
    private function writeSummaryInformation()
743
    {
744
        // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark)
745 38
        $data = pack('v', 0xFFFE);
746
        // 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...
747 38
        $data .= pack('v', 0x0000);
748
        // offset: 4; size: 2; OS version
749 38
        $data .= pack('v', 0x0106);
750
        // offset: 6; size: 2; OS indicator
751 38
        $data .= pack('v', 0x0002);
752
        // offset: 8; size: 16
753 38
        $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00);
754
        // offset: 24; size: 4; section count
755 38
        $data .= pack('V', 0x0001);
756
757
        // 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
758 38
        $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3);
759
        // offset: 44; size: 4; offset of the start
760 38
        $data .= pack('V', 0x30);
761
762
        // SECTION
763 38
        $dataSection = [];
764 38
        $dataSection_NumProps = 0;
765 38
        $dataSection_Summary = '';
766 38
        $dataSection_Content = '';
767
768
        // CodePage : CP-1252
769 38
        $dataSection[] = [
770
            'summary' => ['pack' => 'V', 'data' => 0x01],
771
            'offset' => ['pack' => 'V'],
772
            'type' => ['pack' => 'V', 'data' => 0x02], // 2 byte signed integer
773
            'data' => ['data' => 1252],
774
        ];
775 38
        ++$dataSection_NumProps;
776
777
        //    Title
778 38 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...
779 37
            $dataProp = $this->spreadsheet->getProperties()->getTitle();
780 37
            $dataSection[] = [
781 37
                'summary' => ['pack' => 'V', 'data' => 0x02],
782
                'offset' => ['pack' => 'V'],
783
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
784 37
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
785
            ];
786 37
            ++$dataSection_NumProps;
787
        }
788
        //    Subject
789 38 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...
790 32
            $dataProp = $this->spreadsheet->getProperties()->getSubject();
791 32
            $dataSection[] = [
792 32
                'summary' => ['pack' => 'V', 'data' => 0x03],
793
                'offset' => ['pack' => 'V'],
794
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
795 32
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
796
            ];
797 32
            ++$dataSection_NumProps;
798
        }
799
        //    Author (Creator)
800 38 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...
801 38
            $dataProp = $this->spreadsheet->getProperties()->getCreator();
802 38
            $dataSection[] = [
803 38
                'summary' => ['pack' => 'V', 'data' => 0x04],
804
                'offset' => ['pack' => 'V'],
805
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
806 38
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
807
            ];
808 38
            ++$dataSection_NumProps;
809
        }
810
        //    Keywords
811 38 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...
812 32
            $dataProp = $this->spreadsheet->getProperties()->getKeywords();
813 32
            $dataSection[] = [
814 32
                'summary' => ['pack' => 'V', 'data' => 0x05],
815
                'offset' => ['pack' => 'V'],
816
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
817 32
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
818
            ];
819 32
            ++$dataSection_NumProps;
820
        }
821
        //    Comments (Description)
822 38 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...
823 31
            $dataProp = $this->spreadsheet->getProperties()->getDescription();
824 31
            $dataSection[] = [
825 31
                'summary' => ['pack' => 'V', 'data' => 0x06],
826
                'offset' => ['pack' => 'V'],
827
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
828 31
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
829
            ];
830 31
            ++$dataSection_NumProps;
831
        }
832
        //    Last Saved By (LastModifiedBy)
833 38 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...
834 38
            $dataProp = $this->spreadsheet->getProperties()->getLastModifiedBy();
835 38
            $dataSection[] = [
836 38
                'summary' => ['pack' => 'V', 'data' => 0x08],
837
                'offset' => ['pack' => 'V'],
838
                'type' => ['pack' => 'V', 'data' => 0x1E], // null-terminated string prepended by dword string length
839 38
                'data' => ['data' => $dataProp, 'length' => strlen($dataProp)],
840
            ];
841 38
            ++$dataSection_NumProps;
842
        }
843
        //    Created Date/Time
844 38 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...
845 38
            $dataProp = $this->spreadsheet->getProperties()->getCreated();
846 38
            $dataSection[] = [
847 38
                'summary' => ['pack' => 'V', 'data' => 0x0C],
848
                'offset' => ['pack' => 'V'],
849
                'type' => ['pack' => 'V', 'data' => 0x40], // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
850 38
                'data' => ['data' => \PhpOffice\PhpSpreadsheet\Shared\OLE::localDateToOLE($dataProp)],
851
            ];
852 38
            ++$dataSection_NumProps;
853
        }
854
        //    Modified Date/Time
855 38 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...
856 38
            $dataProp = $this->spreadsheet->getProperties()->getModified();
857 38
            $dataSection[] = [
858 38
                'summary' => ['pack' => 'V', 'data' => 0x0D],
859
                'offset' => ['pack' => 'V'],
860
                'type' => ['pack' => 'V', 'data' => 0x40], // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
861 38
                'data' => ['data' => \PhpOffice\PhpSpreadsheet\Shared\OLE::localDateToOLE($dataProp)],
862
            ];
863 38
            ++$dataSection_NumProps;
864
        }
865
        //    Security
866 38
        $dataSection[] = [
867
            'summary' => ['pack' => 'V', 'data' => 0x13],
868
            'offset' => ['pack' => 'V'],
869
            'type' => ['pack' => 'V', 'data' => 0x03], // 4 byte signed integer
870
            'data' => ['data' => 0x00],
871
        ];
872 38
        ++$dataSection_NumProps;
873
874
        //         4     Section Length
875
        //        4     Property count
876
        //        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...
877 38
        $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8;
878 38
        foreach ($dataSection as $dataProp) {
879
            // Summary
880 38
            $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']);
881
            // Offset
882 38
            $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset);
883
            // DataType
884 38
            $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']);
885
            // Data
886 38
            if ($dataProp['type']['data'] == 0x02) { // 2 byte signed integer
887 38
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
888
889 38
                $dataSection_Content_Offset += 4 + 4;
890 38
            } elseif ($dataProp['type']['data'] == 0x03) { // 4 byte signed integer
891 38
                $dataSection_Content .= pack('V', $dataProp['data']['data']);
892
893 38
                $dataSection_Content_Offset += 4 + 4;
894 38 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...
895
                // Null-terminated string
896 38
                $dataProp['data']['data'] .= chr(0);
897 38
                $dataProp['data']['length'] += 1;
898
                // Complete the string with null string for being a %4
899 38
                $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4) == 4 ? 0 : (4 - $dataProp['data']['length'] % 4));
900 38
                $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT);
901
902 38
                $dataSection_Content .= pack('V', $dataProp['data']['length']);
903 38
                $dataSection_Content .= $dataProp['data']['data'];
904
905 38
                $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']);
906 38
            } elseif ($dataProp['type']['data'] == 0x40) { // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601)
907 38
                $dataSection_Content .= $dataProp['data']['data'];
908
909 38
                $dataSection_Content_Offset += 4 + 8;
910
            }
911
                // Data Type Not Used at the moment
912
        }
913
        // Now $dataSection_Content_Offset contains the size of the content
914
915
        // section header
916
        // offset: $secOffset; size: 4; section length
917
        //         + x  Size of the content (summary + content)
918 38
        $data .= pack('V', $dataSection_Content_Offset);
919
        // offset: $secOffset+4; size: 4; property count
920 38
        $data .= pack('V', $dataSection_NumProps);
921
        // Section Summary
922 38
        $data .= $dataSection_Summary;
923
        // Section Content
924 38
        $data .= $dataSection_Content;
925
926 38
        return $data;
927
    }
928
}
929