Completed
Push — develop ( a06731...6d4488 )
by Adrien
21:40
created

Xls::setTempDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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