Completed
Push — develop ( c5339b...ea5663 )
by Adrien
19:12
created

Xlsx::castToFormula()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 15
nc 3
nop 7
dl 0
loc 24
ccs 15
cts 15
cp 1
crap 4
rs 8.6845
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Reader;
4
5
use PhpOffice\PhpSpreadsheet\Cell;
6
use PhpOffice\PhpSpreadsheet\Document\Properties;
7
use PhpOffice\PhpSpreadsheet\NamedRange;
8
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Chart;
9
use PhpOffice\PhpSpreadsheet\ReferenceHelper;
10
use PhpOffice\PhpSpreadsheet\RichText;
11
use PhpOffice\PhpSpreadsheet\Settings;
12
use PhpOffice\PhpSpreadsheet\Shared\Date;
13
use PhpOffice\PhpSpreadsheet\Shared\Drawing;
14
use PhpOffice\PhpSpreadsheet\Shared\File;
15
use PhpOffice\PhpSpreadsheet\Shared\Font;
16
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
17
use PhpOffice\PhpSpreadsheet\Spreadsheet;
18
use PhpOffice\PhpSpreadsheet\Style;
19
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
20
use PhpOffice\PhpSpreadsheet\Worksheet;
21
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
22
use ZipArchive;
23
24
/**
25
 * Copyright (c) 2006 - 2016 PhpSpreadsheet.
26
 *
27
 * This library is free software; you can redistribute it and/or
28
 * modify it under the terms of the GNU Lesser General Public
29
 * License as published by the Free Software Foundation; either
30
 * version 2.1 of the License, or (at your option) any later version.
31
 *
32
 * This library is distributed in the hope that it will be useful,
33
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35
 * Lesser General Public License for more details.
36
 *
37
 * You should have received a copy of the GNU Lesser General Public
38
 * License along with this library; if not, write to the Free Software
39
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
40
 *
41
 * @category   PhpSpreadsheet
42
 *
43
 * @copyright  Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
44
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
45
 */
46
class Xlsx extends BaseReader implements IReader
47
{
48
    /**
49
     * ReferenceHelper instance.
50
     *
51
     * @var ReferenceHelper
52
     */
53
    private $referenceHelper = null;
54
55
    /**
56
     * Xlsx\Theme instance.
57
     *
58
     * @var Xlsx\Theme
59
     */
60
    private static $theme = null;
61
62
    /**
63
     * Create a new Xlsx Reader instance.
64
     */
65 10
    public function __construct()
66
    {
67 10
        $this->readFilter = new DefaultReadFilter();
68 10
        $this->referenceHelper = ReferenceHelper::getInstance();
69 10
    }
70
71
    /**
72
     * Can the current IReader read the file?
73
     *
74
     * @param string $pFilename
75
     *
76
     * @throws Exception
77
     *
78
     * @return bool
79
     */
80 5
    public function canRead($pFilename)
81
    {
82 5
        File::assertFile($pFilename);
83
84 5
        $xl = false;
85
        // Load file
86 5
        $zip = new ZipArchive();
87 5
        if ($zip->open($pFilename) === true) {
88
            // check if it is an OOXML archive
89 5
            $rels = simplexml_load_string(
90 5
                $this->securityScan(
91 5
                    $this->getFromZipArchive($zip, '_rels/.rels')
92
                ),
93 5
                'SimpleXMLElement',
94 5
                Settings::getLibXmlLoaderOptions()
95
            );
96 5
            if ($rels !== false) {
97 5
                foreach ($rels->Relationship as $rel) {
98 5
                    switch ($rel['Type']) {
99 5
                        case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
100 5
                            if (basename($rel['Target']) == 'workbook.xml') {
101 5
                                $xl = true;
102
                            }
103 5
                            break;
104
                    }
105
                }
106
            }
107 5
            $zip->close();
108
        }
109
110 5
        return $xl;
111
    }
112
113
    /**
114
     * Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object.
115
     *
116
     * @param string $pFilename
117
     *
118
     * @throws Exception
119
     *
120
     * @return array
121
     */
122 1
    public function listWorksheetNames($pFilename)
123
    {
124 1
        File::assertFile($pFilename);
125
126 1
        $worksheetNames = [];
127
128 1
        $zip = new ZipArchive();
129 1
        $zip->open($pFilename);
130
131
        //    The files we're looking at here are small enough that simpleXML is more efficient than XMLReader
132 1
        $rels = simplexml_load_string(
133 1
            $this->securityScan($this->getFromZipArchive($zip, '_rels/.rels'))
134
        ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
135 1
        foreach ($rels->Relationship as $rel) {
136 1
            switch ($rel['Type']) {
137 1
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
138 1
                    $xmlWorkbook = simplexml_load_string(
139 1
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}"))
140
                    ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
141
142 1
                    if ($xmlWorkbook->sheets) {
143 1
                        foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
144
                            // Check if sheet should be skipped
145 1
                            $worksheetNames[] = (string) $eleSheet['name'];
146
                        }
147
                    }
148
            }
149
        }
150
151 1
        $zip->close();
152
153 1
        return $worksheetNames;
154
    }
155
156
    /**
157
     * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns).
158
     *
159
     * @param string $pFilename
160
     *
161
     * @throws Exception
162
     *
163
     * @return array
164
     */
165 1
    public function listWorksheetInfo($pFilename)
166
    {
167 1
        File::assertFile($pFilename);
168
169 1
        $worksheetInfo = [];
170
171 1
        $zip = new ZipArchive();
172 1
        $zip->open($pFilename);
173
174 1
        $rels = simplexml_load_string(
175
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
176 1
            $this->securityScan($this->getFromZipArchive($zip, '_rels/.rels')),
177 1
            'SimpleXMLElement',
178 1
            Settings::getLibXmlLoaderOptions()
179
        );
180 1
        foreach ($rels->Relationship as $rel) {
181 1
            if ($rel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument') {
182 1
                $dir = dirname($rel['Target']);
183 1
                $relsWorkbook = simplexml_load_string(
184
                    //~ http://schemas.openxmlformats.org/package/2006/relationships"
185 1
                    $this->securityScan(
186 1
                        $this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel['Target']) . '.rels')
187
                    ),
188 1
                    'SimpleXMLElement',
189 1
                    Settings::getLibXmlLoaderOptions()
190
                );
191 1
                $relsWorkbook->registerXPathNamespace('rel', 'http://schemas.openxmlformats.org/package/2006/relationships');
192
193 1
                $worksheets = [];
194 1
                foreach ($relsWorkbook->Relationship as $ele) {
195 1
                    if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') {
196 1
                        $worksheets[(string) $ele['Id']] = $ele['Target'];
197
                    }
198
                }
199
200 1
                $xmlWorkbook = simplexml_load_string(
201
                    //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
202 1
                    $this->securityScan(
203 1
                        $this->getFromZipArchive($zip, "{$rel['Target']}")
204
                    ),
205 1
                    'SimpleXMLElement',
206 1
                    Settings::getLibXmlLoaderOptions()
207
                );
208 1
                if ($xmlWorkbook->sheets) {
209 1
                    $dir = dirname($rel['Target']);
210
                    /** @var \SimpleXMLElement $eleSheet */
211 1
                    foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
212
                        $tmpInfo = [
213 1
                            'worksheetName' => (string) $eleSheet['name'],
214 1
                            'lastColumnLetter' => 'A',
215 1
                            'lastColumnIndex' => 0,
216 1
                            'totalRows' => 0,
217 1
                            'totalColumns' => 0,
218
                        ];
219
220 1
                        $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id')];
221
222 1
                        $xml = new \XMLReader();
223 1
                        $res = $xml->xml(
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...
224 1
                            $this->securityScanFile(
225 1
                                'zip://' . File::realpath($pFilename) . '#' . "$dir/$fileWorksheet"
226
                            ),
227 1
                            null,
228 1
                            Settings::getLibXmlLoaderOptions()
229
                        );
230 1
                        $xml->setParserProperty(2, true);
231
232 1
                        $currCells = 0;
233 1
                        while ($xml->read()) {
234 1
                            if ($xml->name == 'row' && $xml->nodeType == \XMLReader::ELEMENT) {
235 1
                                $row = $xml->getAttribute('r');
236 1
                                $tmpInfo['totalRows'] = $row;
237 1
                                $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
238 1
                                $currCells = 0;
239 1
                            } elseif ($xml->name == 'c' && $xml->nodeType == \XMLReader::ELEMENT) {
240 1
                                ++$currCells;
241
                            }
242
                        }
243 1
                        $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
244 1
                        $xml->close();
245
246 1
                        $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
247 1
                        $tmpInfo['lastColumnLetter'] = Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
248
249 1
                        $worksheetInfo[] = $tmpInfo;
250
                    }
251
                }
252
            }
253
        }
254
255 1
        $zip->close();
256
257 1
        return $worksheetInfo;
258
    }
259
260 1
    private static function castToBoolean($c)
261
    {
262 1
        $value = isset($c->v) ? (string) $c->v : null;
263 1
        if ($value == '0') {
264
            return false;
265 1
        } elseif ($value == '1') {
266 1
            return true;
267
        }
268
269
        return (bool) $c->v;
270
        return $value;
0 ignored issues
show
Unused Code introduced by
return $value; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
271
    }
272
273
    private static function castToError($c)
274
    {
275
        return isset($c->v) ? (string) $c->v : null;
276
    }
277
278 5
    private static function castToString($c)
279
    {
280 5
        return isset($c->v) ? (string) $c->v : null;
281
    }
282
283 3
    private function castToFormula($c, $r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType)
284
    {
285 3
        $cellDataType = 'f';
286 3
        $value = "={$c->f}";
287 3
        $calculatedValue = self::$castBaseType($c);
288
289
        // Shared formula?
290 3
        if (isset($c->f['t']) && strtolower((string) $c->f['t']) == 'shared') {
291 1
            $instance = (string) $c->f['si'];
292
293 1
            if (!isset($sharedFormulas[(string) $c->f['si']])) {
294 1
                $sharedFormulas[$instance] = ['master' => $r, 'formula' => $value];
295
            } else {
296 1
                $master = Cell::coordinateFromString($sharedFormulas[$instance]['master']);
297 1
                $current = Cell::coordinateFromString($r);
298
299 1
                $difference = [0, 0];
300 1
                $difference[0] = Cell::columnIndexFromString($current[0]) - Cell::columnIndexFromString($master[0]);
301 1
                $difference[1] = $current[1] - $master[1];
302
303 1
                $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]);
304
            }
305
        }
306 3
    }
307
308
    /**
309
     * @param ZipArchive $archive
310
     * @param string $fileName
311
     *
312
     * @return string
313
     */
314 10
    private function getFromZipArchive(ZipArchive $archive, $fileName = '')
315
    {
316
        // Root-relative paths
317 10
        if (strpos($fileName, '//') !== false) {
318
            $fileName = substr($fileName, strpos($fileName, '//') + 1);
319
        }
320 10
        $fileName = File::realpath($fileName);
321
322
        // Sadly, some 3rd party xlsx generators don't use consistent case for filenaming
323
        //    so we need to load case-insensitively from the zip file
324
325
        // Apache POI fixes
326 10
        $contents = $archive->getFromIndex(
327 10
            $archive->locateName($fileName, ZipArchive::FL_NOCASE)
328
        );
329 10
        if ($contents === false) {
330
            $contents = $archive->getFromIndex(
331
                $archive->locateName(substr($fileName, 1), ZipArchive::FL_NOCASE)
332
            );
333
        }
334
335 10
        return $contents;
336
    }
337
338
    /**
339
     * Loads Spreadsheet from file.
340
     *
341
     * @param string $pFilename
342
     *
343
     * @throws Exception
344
     *
345
     * @return Spreadsheet
346
     */
347 8
    public function load($pFilename)
348
    {
349 8
        File::assertFile($pFilename);
350
351
        // Initialisations
352 8
        $excel = new Spreadsheet();
353 8
        $excel->removeSheetByIndex(0);
354 8
        if (!$this->readDataOnly) {
355 8
            $excel->removeCellStyleXfByIndex(0); // remove the default style
356 8
            $excel->removeCellXfByIndex(0); // remove the default style
357
        }
358
359 8
        $zip = new ZipArchive();
360 8
        $zip->open($pFilename);
361
362
        //    Read the theme first, because we need the colour scheme when reading the styles
363 8
        $wbRels = simplexml_load_string(
364
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
365 8
            $this->securityScan($this->getFromZipArchive($zip, 'xl/_rels/workbook.xml.rels')),
366 8
            'SimpleXMLElement',
367 8
            Settings::getLibXmlLoaderOptions()
368
        );
369 8
        foreach ($wbRels->Relationship as $rel) {
370 8
            switch ($rel['Type']) {
371 8
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme':
372 8
                    $themeOrderArray = ['lt1', 'dk1', 'lt2', 'dk2'];
373 8
                    $themeOrderAdditional = count($themeOrderArray);
374
375 8
                    $xmlTheme = simplexml_load_string(
376 8
                        $this->securityScan($this->getFromZipArchive($zip, "xl/{$rel['Target']}")),
377 8
                        'SimpleXMLElement',
378 8
                        Settings::getLibXmlLoaderOptions()
379
                    );
380 8
                    if (is_object($xmlTheme)) {
381 8
                        $xmlThemeName = $xmlTheme->attributes();
382 8
                        $xmlTheme = $xmlTheme->children('http://schemas.openxmlformats.org/drawingml/2006/main');
383 8
                        $themeName = (string) $xmlThemeName['name'];
384
385 8
                        $colourScheme = $xmlTheme->themeElements->clrScheme->attributes();
386 8
                        $colourSchemeName = (string) $colourScheme['name'];
387 8
                        $colourScheme = $xmlTheme->themeElements->clrScheme->children('http://schemas.openxmlformats.org/drawingml/2006/main');
388
389 8
                        $themeColours = [];
390 8
                        foreach ($colourScheme as $k => $xmlColour) {
391 8
                            $themePos = array_search($k, $themeOrderArray);
392 8
                            if ($themePos === false) {
393 8
                                $themePos = $themeOrderAdditional++;
394
                            }
395 8
                            if (isset($xmlColour->sysClr)) {
396 8
                                $xmlColourData = $xmlColour->sysClr->attributes();
397 8
                                $themeColours[$themePos] = $xmlColourData['lastClr'];
398
                            } elseif (isset($xmlColour->srgbClr)) {
399 8
                                $xmlColourData = $xmlColour->srgbClr->attributes();
400 8
                                $themeColours[$themePos] = $xmlColourData['val'];
401
                            }
402
                        }
403 8
                        self::$theme = new Xlsx\Theme($themeName, $colourSchemeName, $themeColours);
404
                    }
405 8
                    break;
406
            }
407
        }
408
409 8
        $rels = simplexml_load_string(
410
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
411 8
            $this->securityScan($this->getFromZipArchive($zip, '_rels/.rels')),
412 8
            'SimpleXMLElement',
413 8
            Settings::getLibXmlLoaderOptions()
414
        );
415 8
        foreach ($rels->Relationship as $rel) {
416 8
            switch ($rel['Type']) {
417 8
                case 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties':
418 8
                    $xmlCore = simplexml_load_string(
419 8
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
420 8
                        'SimpleXMLElement',
421 8
                        Settings::getLibXmlLoaderOptions()
422
                    );
423 8
                    if (is_object($xmlCore)) {
424 8
                        $xmlCore->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
425 8
                        $xmlCore->registerXPathNamespace('dcterms', 'http://purl.org/dc/terms/');
426 8
                        $xmlCore->registerXPathNamespace('cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties');
427 8
                        $docProps = $excel->getProperties();
428 8
                        $docProps->setCreator((string) self::getArrayItem($xmlCore->xpath('dc:creator')));
429 8
                        $docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath('cp:lastModifiedBy')));
430 8
                        $docProps->setCreated(strtotime(self::getArrayItem($xmlCore->xpath('dcterms:created')))); //! respect xsi:type
0 ignored issues
show
Documentation introduced by
strtotime(self::getArray...th('dcterms:created'))) is of type integer, but the function expects a object<PhpOffice\PhpSpre...Document\datetime>|null.

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...
431 8
                        $docProps->setModified(strtotime(self::getArrayItem($xmlCore->xpath('dcterms:modified')))); //! respect xsi:type
0 ignored issues
show
Documentation introduced by
strtotime(self::getArray...h('dcterms:modified'))) is of type integer, but the function expects a object<PhpOffice\PhpSpre...Document\datetime>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
432 8
                        $docProps->setTitle((string) self::getArrayItem($xmlCore->xpath('dc:title')));
433 8
                        $docProps->setDescription((string) self::getArrayItem($xmlCore->xpath('dc:description')));
434 8
                        $docProps->setSubject((string) self::getArrayItem($xmlCore->xpath('dc:subject')));
435 8
                        $docProps->setKeywords((string) self::getArrayItem($xmlCore->xpath('cp:keywords')));
436 8
                        $docProps->setCategory((string) self::getArrayItem($xmlCore->xpath('cp:category')));
437
                    }
438 8
                    break;
439 8
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties':
440 8
                    $xmlCore = simplexml_load_string(
441 8
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
442 8
                        'SimpleXMLElement',
443 8
                        Settings::getLibXmlLoaderOptions()
444
                    );
445 8
                    if (is_object($xmlCore)) {
446 8
                        $docProps = $excel->getProperties();
447 8
                        if (isset($xmlCore->Company)) {
448 7
                            $docProps->setCompany((string) $xmlCore->Company);
449
                        }
450 8
                        if (isset($xmlCore->Manager)) {
451 5
                            $docProps->setManager((string) $xmlCore->Manager);
452
                        }
453
                    }
454 8
                    break;
455 8
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties':
456 1
                    $xmlCore = simplexml_load_string(
457 1
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
458 1
                        'SimpleXMLElement',
459 1
                        Settings::getLibXmlLoaderOptions()
460
                    );
461 1
                    if (is_object($xmlCore)) {
462 1
                        $docProps = $excel->getProperties();
463
                        /** @var \SimpleXMLElement $xmlProperty */
464 1
                        foreach ($xmlCore as $xmlProperty) {
465 1
                            $cellDataOfficeAttributes = $xmlProperty->attributes();
466 1
                            if (isset($cellDataOfficeAttributes['name'])) {
467 1
                                $propertyName = (string) $cellDataOfficeAttributes['name'];
468 1
                                $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes');
469 1
                                $attributeType = $cellDataOfficeChildren->getName();
470 1
                                $attributeValue = (string) $cellDataOfficeChildren->{$attributeType};
471 1
                                $attributeValue = Properties::convertProperty($attributeValue, $attributeType);
472 1
                                $attributeType = Properties::convertPropertyType($attributeType);
473 1
                                $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType);
474
                            }
475
                        }
476
                    }
477 1
                    break;
478
                //Ribbon
479 8
                case 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility':
480
                    $customUI = $rel['Target'];
481
                    if (!is_null($customUI)) {
482
                        $this->readRibbon($excel, $customUI, $zip);
483
                    }
484
                    break;
485 8
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
486 8
                    $dir = dirname($rel['Target']);
487 8
                    $relsWorkbook = simplexml_load_string(
488
                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
489 8
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel['Target']) . '.rels')),
490 8
                        'SimpleXMLElement',
491 8
                        Settings::getLibXmlLoaderOptions()
492
                    );
493 8
                    $relsWorkbook->registerXPathNamespace('rel', 'http://schemas.openxmlformats.org/package/2006/relationships');
494
495 8
                    $sharedStrings = [];
496 8
                    $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']"));
497 8
                    $xmlStrings = simplexml_load_string(
498
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
499 8
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
500 8
                        'SimpleXMLElement',
501 8
                        Settings::getLibXmlLoaderOptions()
502
                    );
503 8
                    if (isset($xmlStrings) && isset($xmlStrings->si)) {
504 8
                        foreach ($xmlStrings->si as $val) {
505 8
                            if (isset($val->t)) {
506 8
                                $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t);
507
                            } elseif (isset($val->r)) {
508 3
                                $sharedStrings[] = $this->parseRichText($val);
509
                            }
510
                        }
511
                    }
512
513 8
                    $worksheets = [];
514 8
                    $macros = $customUI = null;
0 ignored issues
show
Unused Code introduced by
$customUI 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...
515 8
                    foreach ($relsWorkbook->Relationship as $ele) {
516 8
                        switch ($ele['Type']) {
517 8
                            case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet':
518 8
                                $worksheets[(string) $ele['Id']] = $ele['Target'];
519 8
                                break;
520
                            // a vbaProject ? (: some macros)
521 8
                            case 'http://schemas.microsoft.com/office/2006/relationships/vbaProject':
522
                                $macros = $ele['Target'];
523 8
                                break;
524
                        }
525
                    }
526
527 8
                    if (!is_null($macros)) {
528
                        $macrosCode = $this->getFromZipArchive($zip, 'xl/vbaProject.bin'); //vbaProject.bin always in 'xl' dir and always named vbaProject.bin
529
                        if ($macrosCode !== false) {
530
                            $excel->setMacrosCode($macrosCode);
531
                            $excel->setHasMacros(true);
532
                            //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir
533
                            $Certificate = $this->getFromZipArchive($zip, 'xl/vbaProjectSignature.bin');
534
                            if ($Certificate !== false) {
535
                                $excel->setMacrosCertificate($Certificate);
536
                            }
537
                        }
538
                    }
539 8
                    $styles = [];
540 8
                    $cellStyles = [];
541 8
                    $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
542 8
                    $xmlStyles = simplexml_load_string(
543
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
544 8
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
545 8
                        'SimpleXMLElement',
546 8
                        Settings::getLibXmlLoaderOptions()
547
                    );
548 8
                    $numFmts = null;
549 8
                    if ($xmlStyles && $xmlStyles->numFmts[0]) {
550 5
                        $numFmts = $xmlStyles->numFmts[0];
551
                    }
552 8
                    if (isset($numFmts) && ($numFmts !== null)) {
553 5
                        $numFmts->registerXPathNamespace('sml', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
554
                    }
555 8
                    if (!$this->readDataOnly && $xmlStyles) {
556 8
                        foreach ($xmlStyles->cellXfs->xf as $xf) {
557 8
                            $numFmt = NumberFormat::FORMAT_GENERAL;
558
559 8
                            if ($xf['numFmtId']) {
560 8
                                if (isset($numFmts)) {
561 5
                                    $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
562
563 5
                                    if (isset($tmpNumFmt['formatCode'])) {
564 2
                                        $numFmt = (string) $tmpNumFmt['formatCode'];
565
                                    }
566
                                }
567
568
                                // We shouldn't override any of the built-in MS Excel values (values below id 164)
569
                                //  But there's a lot of naughty homebrew xlsx writers that do use "reserved" id values that aren't actually used
570
                                //  So we make allowance for them rather than lose formatting masks
571 8
                                if ((int) $xf['numFmtId'] < 164 &&
572 8
                                    NumberFormat::builtInFormatCode((int) $xf['numFmtId']) !== '') {
573 8
                                    $numFmt = NumberFormat::builtInFormatCode((int) $xf['numFmtId']);
574
                                }
575
                            }
576 8
                            $quotePrefix = false;
577 8
                            if (isset($xf['quotePrefix'])) {
578
                                $quotePrefix = (bool) $xf['quotePrefix'];
579
                            }
580
581
                            $style = (object) [
582 8
                                'numFmt' => $numFmt,
583 8
                                'font' => $xmlStyles->fonts->font[(int) ($xf['fontId'])],
584 8
                                'fill' => $xmlStyles->fills->fill[(int) ($xf['fillId'])],
585 8
                                'border' => $xmlStyles->borders->border[(int) ($xf['borderId'])],
586 8
                                'alignment' => $xf->alignment,
587 8
                                'protection' => $xf->protection,
588 8
                                'quotePrefix' => $quotePrefix,
589
                            ];
590 8
                            $styles[] = $style;
591
592
                            // add style to cellXf collection
593 8
                            $objStyle = new Style();
594 8
                            self::readStyle($objStyle, $style);
595 8
                            $excel->addCellXf($objStyle);
596
                        }
597
598 8
                        foreach ($xmlStyles->cellStyleXfs->xf as $xf) {
599 8
                            $numFmt = NumberFormat::FORMAT_GENERAL;
600 8
                            if ($numFmts && $xf['numFmtId']) {
601 5
                                $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
602 5
                                if (isset($tmpNumFmt['formatCode'])) {
603
                                    $numFmt = (string) $tmpNumFmt['formatCode'];
604 5
                                } elseif ((int) $xf['numFmtId'] < 165) {
605 5
                                    $numFmt = NumberFormat::builtInFormatCode((int) $xf['numFmtId']);
606
                                }
607
                            }
608
609
                            $cellStyle = (object) [
610 8
                                'numFmt' => $numFmt,
611 8
                                'font' => $xmlStyles->fonts->font[(int) ($xf['fontId'])],
612 8
                                'fill' => $xmlStyles->fills->fill[(int) ($xf['fillId'])],
613 8
                                'border' => $xmlStyles->borders->border[(int) ($xf['borderId'])],
614 8
                                'alignment' => $xf->alignment,
615 8
                                'protection' => $xf->protection,
616 8
                                'quotePrefix' => $quotePrefix,
0 ignored issues
show
Bug introduced by
The variable $quotePrefix 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...
617
                            ];
618 8
                            $cellStyles[] = $cellStyle;
619
620
                            // add style to cellStyleXf collection
621 8
                            $objStyle = new Style();
622 8
                            self::readStyle($objStyle, $cellStyle);
623 8
                            $excel->addCellStyleXf($objStyle);
624
                        }
625
                    }
626
627 8
                    $dxfs = [];
628 8
                    if (!$this->readDataOnly && $xmlStyles) {
629
                        //    Conditional Styles
630 8
                        if ($xmlStyles->dxfs) {
631 8
                            foreach ($xmlStyles->dxfs->dxf as $dxf) {
632
                                $style = new Style(false, true);
633
                                self::readStyle($style, $dxf);
634
                                $dxfs[] = $style;
635
                            }
636
                        }
637
                        //    Cell Styles
638 8
                        if ($xmlStyles->cellStyles) {
639 8
                            foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) {
640 8
                                if ((int) ($cellStyle['builtinId']) == 0) {
641 8
                                    if (isset($cellStyles[(int) ($cellStyle['xfId'])])) {
642
                                        // Set default style
643 8
                                        $style = new Style();
644 8
                                        self::readStyle($style, $cellStyles[(int) ($cellStyle['xfId'])]);
645
646
                                        // normal style, currently not using it for anything
647
                                    }
648
                                }
649
                            }
650
                        }
651
                    }
652
653 8
                    $xmlWorkbook = simplexml_load_string(
654
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
655 8
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
656 8
                        'SimpleXMLElement',
657 8
                        Settings::getLibXmlLoaderOptions()
658
                    );
659
660
                    // Set base date
661 8
                    if ($xmlWorkbook->workbookPr) {
662 8
                        Date::setExcelCalendar(Date::CALENDAR_WINDOWS_1900);
663 8
                        if (isset($xmlWorkbook->workbookPr['date1904'])) {
664
                            if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) {
665
                                Date::setExcelCalendar(Date::CALENDAR_MAC_1904);
666
                            }
667
                        }
668
                    }
669
670 8
                    $sheetId = 0; // keep track of new sheet id in final workbook
671 8
                    $oldSheetId = -1; // keep track of old sheet id in final workbook
672 8
                    $countSkippedSheets = 0; // keep track of number of skipped sheets
673 8
                    $mapSheetId = []; // mapping of sheet ids from old to new
674
675 8
                    $charts = $chartDetails = [];
676
677 8
                    if ($xmlWorkbook->sheets) {
678
                        /** @var \SimpleXMLElement $eleSheet */
679 8
                        foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
680 8
                            ++$oldSheetId;
681
682
                            // Check if sheet should be skipped
683 8
                            if (isset($this->loadSheetsOnly) && !in_array((string) $eleSheet['name'], $this->loadSheetsOnly)) {
684
                                ++$countSkippedSheets;
685
                                $mapSheetId[$oldSheetId] = null;
686
                                continue;
687
                            }
688
689
                            // Map old sheet id in original workbook to new sheet id.
690
                            // They will differ if loadSheetsOnly() is being used
691 8
                            $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets;
692
693
                            // Load sheet
694 8
                            $docSheet = $excel->createSheet();
695
                            //    Use false for $updateFormulaCellReferences to prevent adjustment of worksheet
696
                            //        references in formula cells... during the load, all formulae should be correct,
697
                            //        and we're simply bringing the worksheet name in line with the formula, not the
698
                            //        reverse
699 8
                            $docSheet->setTitle((string) $eleSheet['name'], false);
700 8
                            $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id')];
701 8
                            $xmlSheet = simplexml_load_string(
702
                                //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
703 8
                                $this->securityScan($this->getFromZipArchive($zip, "$dir/$fileWorksheet")),
704 8
                                'SimpleXMLElement',
705 8
                                Settings::getLibXmlLoaderOptions()
706
                            );
707
708 8
                            $sharedFormulas = [];
709
710 8
                            if (isset($eleSheet['state']) && (string) $eleSheet['state'] != '') {
711
                                $docSheet->setSheetState((string) $eleSheet['state']);
712
                            }
713
714 8
                            if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) {
715 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) {
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...
716
                                    $docSheet->getSheetView()->setZoomScale((int) ($xmlSheet->sheetViews->sheetView['zoomScale']));
717
                                }
718 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) {
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...
719
                                    $docSheet->getSheetView()->setZoomScaleNormal((int) ($xmlSheet->sheetViews->sheetView['zoomScaleNormal']));
720
                                }
721 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['view'])) {
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...
722
                                    $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']);
723
                                }
724 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) {
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...
725 5
                                    $docSheet->setShowGridLines(self::boolean((string) $xmlSheet->sheetViews->sheetView['showGridLines']));
726
                                }
727 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) {
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...
728 5
                                    $docSheet->setShowRowColHeaders(self::boolean((string) $xmlSheet->sheetViews->sheetView['showRowColHeaders']));
729
                                }
730 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) {
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...
731
                                    $docSheet->setRightToLeft(self::boolean((string) $xmlSheet->sheetViews->sheetView['rightToLeft']));
732
                                }
733 8
                                if (isset($xmlSheet->sheetViews->sheetView->pane)) {
734 1
                                    if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
735 1
                                        $docSheet->freezePane((string) $xmlSheet->sheetViews->sheetView->pane['topLeftCell']);
736
                                    } else {
737
                                        $xSplit = 0;
738
                                        $ySplit = 0;
739
740
                                        if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) {
741
                                            $xSplit = 1 + (int) ($xmlSheet->sheetViews->sheetView->pane['xSplit']);
742
                                        }
743
744
                                        if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) {
745
                                            $ySplit = 1 + (int) ($xmlSheet->sheetViews->sheetView->pane['ySplit']);
746
                                        }
747
748
                                        $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit);
749
                                    }
750
                                }
751
752 8
                                if (isset($xmlSheet->sheetViews->sheetView->selection)) {
753 8
                                    if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) {
754 8
                                        $sqref = (string) $xmlSheet->sheetViews->sheetView->selection['sqref'];
755 8
                                        $sqref = explode(' ', $sqref);
756 8
                                        $sqref = $sqref[0];
757 8
                                        $docSheet->setSelectedCells($sqref);
758
                                    }
759
                                }
760
                            }
761
762 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) {
763 2
                                if (isset($xmlSheet->sheetPr->tabColor['rgb'])) {
764 2
                                    $docSheet->getTabColor()->setARGB((string) $xmlSheet->sheetPr->tabColor['rgb']);
765
                                }
766
                            }
767 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) {
768
                                $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']);
769
                            }
770 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) {
771 5 View Code Duplication
                                if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) &&
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...
772 5
                                    !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) {
773
                                    $docSheet->setShowSummaryRight(false);
774
                                } else {
775 5
                                    $docSheet->setShowSummaryRight(true);
776
                                }
777
778 5 View Code Duplication
                                if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) &&
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 5
                                    !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) {
780
                                    $docSheet->setShowSummaryBelow(false);
781
                                } else {
782 5
                                    $docSheet->setShowSummaryBelow(true);
783
                                }
784
                            }
785
786 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) {
787
                                if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) &&
788
                                    !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) {
789
                                    $docSheet->getPageSetup()->setFitToPage(false);
790
                                } else {
791
                                    $docSheet->getPageSetup()->setFitToPage(true);
792
                                }
793
                            }
794
795 8
                            if (isset($xmlSheet->sheetFormatPr)) {
796 8
                                if (isset($xmlSheet->sheetFormatPr['customHeight']) &&
797
                                    self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) &&
798
                                    isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) {
799
                                    $docSheet->getDefaultRowDimension()->setRowHeight((float) $xmlSheet->sheetFormatPr['defaultRowHeight']);
800
                                }
801 8
                                if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) {
802
                                    $docSheet->getDefaultColumnDimension()->setWidth((float) $xmlSheet->sheetFormatPr['defaultColWidth']);
803
                                }
804 8
                                if (isset($xmlSheet->sheetFormatPr['zeroHeight']) &&
805
                                    ((string) $xmlSheet->sheetFormatPr['zeroHeight'] == '1')) {
806
                                    $docSheet->getDefaultRowDimension()->setZeroHeight(true);
807
                                }
808
                            }
809
810 8
                            if (isset($xmlSheet->cols) && !$this->readDataOnly) {
811 5
                                foreach ($xmlSheet->cols->col as $col) {
812 5
                                    for ($i = (int) ($col['min']) - 1; $i < (int) ($col['max']); ++$i) {
813 5
                                        if ($col['style'] && !$this->readDataOnly) {
814 3
                                            $docSheet->getColumnDimension(Cell::stringFromColumnIndex($i))->setXfIndex((int) ($col['style']));
815
                                        }
816 5
                                        if (self::boolean($col['hidden'])) {
817 1
                                            $docSheet->getColumnDimension(Cell::stringFromColumnIndex($i))->setVisible(false);
818
                                        }
819 5
                                        if (self::boolean($col['collapsed'])) {
820 1
                                            $docSheet->getColumnDimension(Cell::stringFromColumnIndex($i))->setCollapsed(true);
821
                                        }
822 5
                                        if ($col['outlineLevel'] > 0) {
823 1
                                            $docSheet->getColumnDimension(Cell::stringFromColumnIndex($i))->setOutlineLevel((int) ($col['outlineLevel']));
824
                                        }
825 5
                                        $docSheet->getColumnDimension(Cell::stringFromColumnIndex($i))->setWidth((float) ($col['width']));
826
827 5
                                        if ((int) ($col['max']) == 16384) {
828
                                            break;
829
                                        }
830
                                    }
831
                                }
832
                            }
833
834 8
                            if (isset($xmlSheet->printOptions) && !$this->readDataOnly) {
835 5
                                if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) {
836 5
                                    $docSheet->setShowGridlines(true);
837
                                }
838 5
                                if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) {
839
                                    $docSheet->setPrintGridlines(true);
840
                                }
841 5
                                if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) {
842
                                    $docSheet->getPageSetup()->setHorizontalCentered(true);
843
                                }
844 5
                                if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) {
845
                                    $docSheet->getPageSetup()->setVerticalCentered(true);
846
                                }
847
                            }
848
849 8
                            if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
850 8
                                foreach ($xmlSheet->sheetData->row as $row) {
851 8
                                    if ($row['ht'] && !$this->readDataOnly) {
852 1
                                        $docSheet->getRowDimension((int) ($row['r']))->setRowHeight((float) ($row['ht']));
853
                                    }
854 8
                                    if (self::boolean($row['hidden']) && !$this->readDataOnly) {
855
                                        $docSheet->getRowDimension((int) ($row['r']))->setVisible(false);
856
                                    }
857 8
                                    if (self::boolean($row['collapsed'])) {
858
                                        $docSheet->getRowDimension((int) ($row['r']))->setCollapsed(true);
859
                                    }
860 8
                                    if ($row['outlineLevel'] > 0) {
861
                                        $docSheet->getRowDimension((int) ($row['r']))->setOutlineLevel((int) ($row['outlineLevel']));
862
                                    }
863 8
                                    if ($row['s'] && !$this->readDataOnly) {
864
                                        $docSheet->getRowDimension((int) ($row['r']))->setXfIndex((int) ($row['s']));
865
                                    }
866
867 8
                                    foreach ($row->c as $c) {
868 8
                                        $r = (string) $c['r'];
869 8
                                        $cellDataType = (string) $c['t'];
870 8
                                        $value = null;
871 8
                                        $calculatedValue = null;
872
873
                                        // Read cell?
874 8
                                        if ($this->getReadFilter() !== null) {
875 8
                                            $coordinates = Cell::coordinateFromString($r);
876
877 8
                                            if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) {
878 1
                                                continue;
879
                                            }
880
                                        }
881
882
                                        // Read cell!
883
                                        switch ($cellDataType) {
884 8
                                            case 's':
885 8
                                                if ((string) $c->v != '') {
886 8
                                                    $value = $sharedStrings[(int) ($c->v)];
887
888 8
                                                    if ($value instanceof RichText) {
889 1
                                                        $value = clone $value;
890
                                                    }
891
                                                } else {
892
                                                    $value = '';
893
                                                }
894 8
                                                break;
895 6
                                            case 'b':
896 1
                                                if (!isset($c->f)) {
897 1
                                                    $value = self::castToBoolean($c);
898
                                                } else {
899
                                                    // Formula
900
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean');
901
                                                    if (isset($c->f['t'])) {
902
                                                        $att = [];
0 ignored issues
show
Unused Code introduced by
$att 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...
903
                                                        $att = $c->f;
904
                                                        $docSheet->getCell($r)->setFormulaAttributes($att);
905
                                                    }
906
                                                }
907 1
                                                break;
908 5 View Code Duplication
                                            case 'inlineStr':
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...
909 2
                                                if (isset($c->f)) {
910
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
911
                                                } else {
912 2
                                                    $value = $this->parseRichText($c->is);
913
                                                }
914 2
                                                break;
915 5 View Code Duplication
                                            case 'e':
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...
916
                                                if (!isset($c->f)) {
917
                                                    $value = self::castToError($c);
918
                                                } else {
919
                                                    // Formula
920
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
921
                                                }
922
                                                break;
923
                                            default:
924 5
                                                if (!isset($c->f)) {
925 5
                                                    $value = self::castToString($c);
926
                                                } else {
927
                                                    // Formula
928 3
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToString');
929
                                                }
930 5
                                                break;
931
                                        }
932
933
                                        // Check for numeric values
934 8
                                        if (is_numeric($value) && $cellDataType != 's') {
935 5
                                            if ($value == (int) $value) {
936 5
                                                $value = (int) $value;
937
                                            } elseif ($value == (float) $value) {
938
                                                $value = (float) $value;
939
                                            } elseif ($value == (float) $value) {
940
                                                $value = (float) $value;
941
                                            }
942
                                        }
943
944
                                        // Rich text?
945 8
                                        if ($value instanceof RichText && $this->readDataOnly) {
946
                                            $value = $value->getPlainText();
947
                                        }
948
949 8
                                        $cell = $docSheet->getCell($r);
950
                                        // Assign value
951 8
                                        if ($cellDataType != '') {
952 8
                                            $cell->setValueExplicit($value, $cellDataType);
953
                                        } else {
954 5
                                            $cell->setValue($value);
955
                                        }
956 8
                                        if ($calculatedValue !== null) {
957 3
                                            $cell->setCalculatedValue($calculatedValue);
958
                                        }
959
960
                                        // Style information?
961 8
                                        if ($c['s'] && !$this->readDataOnly) {
962
                                            // no style index means 0, it seems
963 5
                                            $cell->setXfIndex(isset($styles[(int) ($c['s'])]) ?
964 8
                                                (int) ($c['s']) : 0);
965
                                        }
966
                                    }
967
                                }
968
                            }
969
970 8
                            $conditionals = [];
971 8
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
972
                                foreach ($xmlSheet->conditionalFormatting as $conditional) {
973
                                    foreach ($conditional->cfRule as $cfRule) {
974
                                        if (((string) $cfRule['type'] == Style\Conditional::CONDITION_NONE || (string) $cfRule['type'] == Style\Conditional::CONDITION_CELLIS || (string) $cfRule['type'] == Style\Conditional::CONDITION_CONTAINSTEXT || (string) $cfRule['type'] == Style\Conditional::CONDITION_EXPRESSION) && isset($dxfs[(int) ($cfRule['dxfId'])])) {
975
                                            $conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
976
                                        }
977
                                    }
978
                                }
979
980
                                foreach ($conditionals as $ref => $cfRules) {
981
                                    ksort($cfRules);
982
                                    $conditionalStyles = [];
983
                                    foreach ($cfRules as $cfRule) {
984
                                        $objConditional = new Style\Conditional();
985
                                        $objConditional->setConditionType((string) $cfRule['type']);
986
                                        $objConditional->setOperatorType((string) $cfRule['operator']);
987
988
                                        if ((string) $cfRule['text'] != '') {
989
                                            $objConditional->setText((string) $cfRule['text']);
990
                                        }
991
992
                                        if (count($cfRule->formula) > 1) {
993
                                            foreach ($cfRule->formula as $formula) {
994
                                                $objConditional->addCondition((string) $formula);
995
                                            }
996
                                        } else {
997
                                            $objConditional->addCondition((string) $cfRule->formula);
998
                                        }
999
                                        $objConditional->setStyle(clone $dxfs[(int) ($cfRule['dxfId'])]);
1000
                                        $conditionalStyles[] = $objConditional;
1001
                                    }
1002
1003
                                    // Extract all cell references in $ref
1004
                                    $cellBlocks = explode(' ', str_replace('$', '', strtoupper($ref)));
1005
                                    foreach ($cellBlocks as $cellBlock) {
1006
                                        $docSheet->getStyle($cellBlock)->setConditionalStyles($conditionalStyles);
1007
                                    }
1008
                                }
1009
                            }
1010
1011 8
                            $aKeys = ['sheet', 'objects', 'scenarios', 'formatCells', 'formatColumns', 'formatRows', 'insertColumns', 'insertRows', 'insertHyperlinks', 'deleteColumns', 'deleteRows', 'selectLockedCells', 'sort', 'autoFilter', 'pivotTables', 'selectUnlockedCells'];
1012 8
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
1013 5
                                foreach ($aKeys as $key) {
1014 5
                                    $method = 'set' . ucfirst($key);
1015 5
                                    $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key]));
1016
                                }
1017
                            }
1018
1019 8
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
1020 5
                                $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection['password'], true);
1021 5
                                if ($xmlSheet->protectedRanges->protectedRange) {
1022 2
                                    foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
1023 2
                                        $docSheet->protectCells((string) $protectedRange['sqref'], (string) $protectedRange['password'], true);
1024
                                    }
1025
                                }
1026
                            }
1027
1028 8
                            if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
1029
                                $autoFilterRange = (string) $xmlSheet->autoFilter['ref'];
1030
                                if (strpos($autoFilterRange, ':') !== false) {
1031
                                    $autoFilter = $docSheet->getAutoFilter();
1032
                                    $autoFilter->setRange($autoFilterRange);
1033
1034
                                    foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) {
1035
                                        $column = $autoFilter->getColumnByOffset((int) $filterColumn['colId']);
1036
                                        //    Check for standard filters
1037
                                        if ($filterColumn->filters) {
1038
                                            $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER);
1039
                                            $filters = $filterColumn->filters;
1040
                                            if ((isset($filters['blank'])) && ($filters['blank'] == 1)) {
1041
                                                //    Operator is undefined, but always treated as EQUAL
1042
                                                $column->createRule()->setRule(null, '')->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_FILTER);
1043
                                            }
1044
                                            //    Standard filters are always an OR join, so no join rule needs to be set
1045
                                            //    Entries can be either filter elements
1046 View Code Duplication
                                            foreach ($filters->filter as $filterRule) {
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...
1047
                                                //    Operator is undefined, but always treated as EQUAL
1048
                                                $column->createRule()->setRule(null, (string) $filterRule['val'])->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_FILTER);
1049
                                            }
1050
                                            //    Or Date Group elements
1051
                                            foreach ($filters->dateGroupItem as $dateGroupItem) {
1052
                                                $column->createRule()->setRule(
1053
                                                    //    Operator is undefined, but always treated as EQUAL
1054
                                                    null,
1055
                                                    [
1056
                                                        'year' => (string) $dateGroupItem['year'],
1057
                                                        'month' => (string) $dateGroupItem['month'],
1058
                                                        'day' => (string) $dateGroupItem['day'],
1059
                                                        'hour' => (string) $dateGroupItem['hour'],
1060
                                                        'minute' => (string) $dateGroupItem['minute'],
1061
                                                        'second' => (string) $dateGroupItem['second'],
1062
                                                    ],
1063
                                                    (string) $dateGroupItem['dateTimeGrouping']
1064
                                                )
1065
                                                ->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP);
1066
                                            }
1067
                                        }
1068
                                        //    Check for custom filters
1069
                                        if ($filterColumn->customFilters) {
1070
                                            $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
1071
                                            $customFilters = $filterColumn->customFilters;
1072
                                            //    Custom filters can an AND or an OR join;
1073
                                            //        and there should only ever be one or two entries
1074
                                            if ((isset($customFilters['and'])) && ($customFilters['and'] == 1)) {
1075
                                                $column->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND);
1076
                                            }
1077 View Code Duplication
                                            foreach ($customFilters->customFilter as $filterRule) {
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...
1078
                                                $column->createRule()->setRule(
1079
                                                    (string) $filterRule['operator'],
1080
                                                    (string) $filterRule['val']
1081
                                                )
1082
                                                ->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
1083
                                            }
1084
                                        }
1085
                                        //    Check for dynamic filters
1086
                                        if ($filterColumn->dynamicFilter) {
1087
                                            $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
1088
                                            //    We should only ever have one dynamic filter
1089
                                            foreach ($filterColumn->dynamicFilter as $filterRule) {
1090
                                                $column->createRule()->setRule(
1091
                                                    //    Operator is undefined, but always treated as EQUAL
1092
                                                    null,
1093
                                                    (string) $filterRule['val'],
1094
                                                    (string) $filterRule['type']
1095
                                                )
1096
                                                ->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
1097
                                                if (isset($filterRule['val'])) {
1098
                                                    $column->setAttribute('val', (string) $filterRule['val']);
1099
                                                }
1100
                                                if (isset($filterRule['maxVal'])) {
1101
                                                    $column->setAttribute('maxVal', (string) $filterRule['maxVal']);
1102
                                                }
1103
                                            }
1104
                                        }
1105
                                        //    Check for dynamic filters
1106
                                        if ($filterColumn->top10) {
1107
                                            $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER);
1108
                                            //    We should only ever have one top10 filter
1109
                                            foreach ($filterColumn->top10 as $filterRule) {
1110
                                                $column->createRule()->setRule(
1111
                                                    (((isset($filterRule['percent'])) && ($filterRule['percent'] == 1))
1112
                                                        ? Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT
1113
                                                        : Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE
1114
                                                    ),
1115
                                                    (string) $filterRule['val'],
1116
                                                    (((isset($filterRule['top'])) && ($filterRule['top'] == 1))
1117
                                                        ? Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP
1118
                                                        : Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM
1119
                                                    )
1120
                                                )
1121
                                                ->setRuleType(Column\Rule::AUTOFILTER_RULETYPE_TOPTENFILTER);
1122
                                            }
1123
                                        }
1124
                                    }
1125
                                }
1126
                            }
1127
1128 8
                            if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
1129 4
                                foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) {
1130 4
                                    $mergeRef = (string) $mergeCell['ref'];
1131 4
                                    if (strpos($mergeRef, ':') !== false) {
1132 4
                                        $docSheet->mergeCells((string) $mergeCell['ref']);
1133
                                    }
1134
                                }
1135
                            }
1136
1137 8
                            if ($xmlSheet && $xmlSheet->pageMargins && !$this->readDataOnly) {
1138 8
                                $docPageMargins = $docSheet->getPageMargins();
1139 8
                                $docPageMargins->setLeft((float) ($xmlSheet->pageMargins['left']));
1140 8
                                $docPageMargins->setRight((float) ($xmlSheet->pageMargins['right']));
1141 8
                                $docPageMargins->setTop((float) ($xmlSheet->pageMargins['top']));
1142 8
                                $docPageMargins->setBottom((float) ($xmlSheet->pageMargins['bottom']));
1143 8
                                $docPageMargins->setHeader((float) ($xmlSheet->pageMargins['header']));
1144 8
                                $docPageMargins->setFooter((float) ($xmlSheet->pageMargins['footer']));
1145
                            }
1146
1147 8
                            if ($xmlSheet && $xmlSheet->pageSetup && !$this->readDataOnly) {
1148 8
                                $docPageSetup = $docSheet->getPageSetup();
1149
1150 8
                                if (isset($xmlSheet->pageSetup['orientation'])) {
1151 8
                                    $docPageSetup->setOrientation((string) $xmlSheet->pageSetup['orientation']);
1152
                                }
1153 8
                                if (isset($xmlSheet->pageSetup['paperSize'])) {
1154 8
                                    $docPageSetup->setPaperSize((int) ($xmlSheet->pageSetup['paperSize']));
1155
                                }
1156 8
                                if (isset($xmlSheet->pageSetup['scale'])) {
1157 5
                                    $docPageSetup->setScale((int) ($xmlSheet->pageSetup['scale']), false);
1158
                                }
1159 8 View Code Duplication
                                if (isset($xmlSheet->pageSetup['fitToHeight']) && (int) ($xmlSheet->pageSetup['fitToHeight']) >= 0) {
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...
1160 5
                                    $docPageSetup->setFitToHeight((int) ($xmlSheet->pageSetup['fitToHeight']), false);
1161
                                }
1162 8 View Code Duplication
                                if (isset($xmlSheet->pageSetup['fitToWidth']) && (int) ($xmlSheet->pageSetup['fitToWidth']) >= 0) {
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...
1163 5
                                    $docPageSetup->setFitToWidth((int) ($xmlSheet->pageSetup['fitToWidth']), false);
1164
                                }
1165 8
                                if (isset($xmlSheet->pageSetup['firstPageNumber']) && isset($xmlSheet->pageSetup['useFirstPageNumber']) &&
1166
                                    self::boolean((string) $xmlSheet->pageSetup['useFirstPageNumber'])) {
1167
                                    $docPageSetup->setFirstPageNumber((int) ($xmlSheet->pageSetup['firstPageNumber']));
1168
                                }
1169
                            }
1170
1171 8
                            if ($xmlSheet && $xmlSheet->headerFooter && !$this->readDataOnly) {
1172 5
                                $docHeaderFooter = $docSheet->getHeaderFooter();
1173
1174 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['differentOddEven']) &&
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...
1175 5
                                    self::boolean((string) $xmlSheet->headerFooter['differentOddEven'])) {
1176
                                    $docHeaderFooter->setDifferentOddEven(true);
1177
                                } else {
1178 5
                                    $docHeaderFooter->setDifferentOddEven(false);
1179
                                }
1180 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['differentFirst']) &&
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...
1181 5
                                    self::boolean((string) $xmlSheet->headerFooter['differentFirst'])) {
1182
                                    $docHeaderFooter->setDifferentFirst(true);
1183
                                } else {
1184 5
                                    $docHeaderFooter->setDifferentFirst(false);
1185
                                }
1186 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['scaleWithDoc']) &&
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...
1187 5
                                    !self::boolean((string) $xmlSheet->headerFooter['scaleWithDoc'])) {
1188
                                    $docHeaderFooter->setScaleWithDocument(false);
1189
                                } else {
1190 5
                                    $docHeaderFooter->setScaleWithDocument(true);
1191
                                }
1192 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['alignWithMargins']) &&
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...
1193 5
                                    !self::boolean((string) $xmlSheet->headerFooter['alignWithMargins'])) {
1194 1
                                    $docHeaderFooter->setAlignWithMargins(false);
1195
                                } else {
1196 4
                                    $docHeaderFooter->setAlignWithMargins(true);
1197
                                }
1198
1199 5
                                $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader);
1200 5
                                $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter);
1201 5
                                $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader);
1202 5
                                $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter);
1203 5
                                $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader);
1204 5
                                $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter);
1205
                            }
1206
1207 8
                            if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->readDataOnly) {
1208
                                foreach ($xmlSheet->rowBreaks->brk as $brk) {
1209
                                    if ($brk['man']) {
1210
                                        $docSheet->setBreak("A$brk[id]", Worksheet::BREAK_ROW);
1211
                                    }
1212
                                }
1213
                            }
1214 8
                            if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->readDataOnly) {
1215
                                foreach ($xmlSheet->colBreaks->brk as $brk) {
1216
                                    if ($brk['man']) {
1217
                                        $docSheet->setBreak(Cell::stringFromColumnIndex((string) $brk['id']) . '1', Worksheet::BREAK_COLUMN);
1218
                                    }
1219
                                }
1220
                            }
1221
1222 8
                            if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) {
1223
                                foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) {
1224
                                    // Uppercase coordinate
1225
                                    $range = strtoupper($dataValidation['sqref']);
1226
                                    $rangeSet = explode(' ', $range);
1227
                                    foreach ($rangeSet as $range) {
1228
                                        $stRange = $docSheet->shrinkRangeToFit($range);
1229
1230
                                        // Extract all cell references in $range
1231
                                        foreach (Cell::extractAllCellReferencesInRange($stRange) as $reference) {
1232
                                            // Create validation
1233
                                            $docValidation = $docSheet->getCell($reference)->getDataValidation();
1234
                                            $docValidation->setType((string) $dataValidation['type']);
1235
                                            $docValidation->setErrorStyle((string) $dataValidation['errorStyle']);
1236
                                            $docValidation->setOperator((string) $dataValidation['operator']);
1237
                                            $docValidation->setAllowBlank($dataValidation['allowBlank'] != 0);
1238
                                            $docValidation->setShowDropDown($dataValidation['showDropDown'] == 0);
1239
                                            $docValidation->setShowInputMessage($dataValidation['showInputMessage'] != 0);
1240
                                            $docValidation->setShowErrorMessage($dataValidation['showErrorMessage'] != 0);
1241
                                            $docValidation->setErrorTitle((string) $dataValidation['errorTitle']);
1242
                                            $docValidation->setError((string) $dataValidation['error']);
1243
                                            $docValidation->setPromptTitle((string) $dataValidation['promptTitle']);
1244
                                            $docValidation->setPrompt((string) $dataValidation['prompt']);
1245
                                            $docValidation->setFormula1((string) $dataValidation->formula1);
1246
                                            $docValidation->setFormula2((string) $dataValidation->formula2);
1247
                                        }
1248
                                    }
1249
                                }
1250
                            }
1251
1252
                            // Add hyperlinks
1253 8
                            $hyperlinks = [];
1254 8
                            if (!$this->readDataOnly) {
1255
                                // Locate hyperlink relations
1256 8
                                if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1257 8
                                    $relsWorksheet = simplexml_load_string(
1258
                                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
1259 8
                                        $this->securityScan(
1260 8
                                            $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1261
                                        ),
1262 8
                                        'SimpleXMLElement',
1263 8
                                        Settings::getLibXmlLoaderOptions()
1264
                                    );
1265 8
                                    foreach ($relsWorksheet->Relationship as $ele) {
1266 5
                                        if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink') {
1267 2
                                            $hyperlinks[(string) $ele['Id']] = (string) $ele['Target'];
1268
                                        }
1269
                                    }
1270
                                }
1271
1272
                                // Loop through hyperlinks
1273 8
                                if ($xmlSheet && $xmlSheet->hyperlinks) {
1274
                                    /** @var \SimpleXMLElement $hyperlink */
1275 2
                                    foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) {
1276
                                        // Link url
1277 2
                                        $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1278
1279 2
                                        foreach (Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
1280 2
                                            $cell = $docSheet->getCell($cellReference);
1281 2
                                            if (isset($linkRel['id'])) {
1282 2
                                                $hyperlinkUrl = $hyperlinks[(string) $linkRel['id']];
1283 2
                                                if (isset($hyperlink['location'])) {
1284
                                                    $hyperlinkUrl .= '#' . (string) $hyperlink['location'];
1285
                                                }
1286 2
                                                $cell->getHyperlink()->setUrl($hyperlinkUrl);
1287 2
                                            } elseif (isset($hyperlink['location'])) {
1288 2
                                                $cell->getHyperlink()->setUrl('sheet://' . (string) $hyperlink['location']);
1289
                                            }
1290
1291
                                            // Tooltip
1292 2
                                            if (isset($hyperlink['tooltip'])) {
1293 2
                                                $cell->getHyperlink()->setTooltip((string) $hyperlink['tooltip']);
1294
                                            }
1295
                                        }
1296
                                    }
1297
                                }
1298
                            }
1299
1300
                            // Add comments
1301 8
                            $comments = [];
1302 8
                            $vmlComments = [];
1303 8
                            if (!$this->readDataOnly) {
1304
                                // Locate comment relations
1305 8
                                if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1306 8
                                    $relsWorksheet = simplexml_load_string(
1307
                                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
1308 8
                                        $this->securityScan(
1309 8
                                            $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1310
                                        ),
1311 8
                                        'SimpleXMLElement',
1312 8
                                        Settings::getLibXmlLoaderOptions()
1313
                                    );
1314 8
                                    foreach ($relsWorksheet->Relationship as $ele) {
1315 5
                                        if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments') {
1316 2
                                            $comments[(string) $ele['Id']] = (string) $ele['Target'];
1317
                                        }
1318 5
                                        if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing') {
1319 2
                                            $vmlComments[(string) $ele['Id']] = (string) $ele['Target'];
1320
                                        }
1321
                                    }
1322
                                }
1323
1324
                                // Loop through comments
1325 8
                                foreach ($comments as $relName => $relPath) {
1326
                                    // Load comments file
1327 2
                                    $relPath = File::realpath(dirname("$dir/$fileWorksheet") . '/' . $relPath);
1328 2
                                    $commentsFile = simplexml_load_string(
1329 2
                                        $this->securityScan($this->getFromZipArchive($zip, $relPath)),
1330 2
                                        'SimpleXMLElement',
1331 2
                                        Settings::getLibXmlLoaderOptions()
1332
                                    );
1333
1334
                                    // Utility variables
1335 2
                                    $authors = [];
1336
1337
                                    // Loop through authors
1338 2
                                    foreach ($commentsFile->authors->author as $author) {
1339 2
                                        $authors[] = (string) $author;
1340
                                    }
1341
1342
                                    // Loop through contents
1343 2
                                    foreach ($commentsFile->commentList->comment as $comment) {
1344 2
                                        if (!empty($comment['authorId'])) {
1345
                                            $docSheet->getComment((string) $comment['ref'])->setAuthor($authors[(string) $comment['authorId']]);
1346
                                        }
1347 2
                                        $docSheet->getComment((string) $comment['ref'])->setText($this->parseRichText($comment->text));
1348
                                    }
1349
                                }
1350
1351
                                // Loop through VML comments
1352 8
                                foreach ($vmlComments as $relName => $relPath) {
1353
                                    // Load VML comments file
1354 2
                                    $relPath = File::realpath(dirname("$dir/$fileWorksheet") . '/' . $relPath);
1355 2
                                    $vmlCommentsFile = simplexml_load_string(
1356 2
                                        $this->securityScan($this->getFromZipArchive($zip, $relPath)),
1357 2
                                        'SimpleXMLElement',
1358 2
                                        Settings::getLibXmlLoaderOptions()
1359
                                    );
1360 2
                                    $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1361
1362 2
                                    $shapes = $vmlCommentsFile->xpath('//v:shape');
1363 2
                                    foreach ($shapes as $shape) {
1364 2
                                        $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1365
1366 2
                                        if (isset($shape['style'])) {
1367 2
                                            $style = (string) $shape['style'];
1368 2
                                            $fillColor = strtoupper(substr((string) $shape['fillcolor'], 1));
1369 2
                                            $column = null;
1370 2
                                            $row = null;
1371
1372 2
                                            $clientData = $shape->xpath('.//x:ClientData');
1373 2
                                            if (is_array($clientData) && !empty($clientData)) {
1374 2
                                                $clientData = $clientData[0];
1375
1376 2
                                                if (isset($clientData['ObjectType']) && (string) $clientData['ObjectType'] == 'Note') {
1377 2
                                                    $temp = $clientData->xpath('.//x:Row');
1378 2
                                                    if (is_array($temp)) {
1379 2
                                                        $row = $temp[0];
1380
                                                    }
1381
1382 2
                                                    $temp = $clientData->xpath('.//x:Column');
1383 2
                                                    if (is_array($temp)) {
1384 2
                                                        $column = $temp[0];
1385
                                                    }
1386
                                                }
1387
                                            }
1388
1389 2
                                            if (($column !== null) && ($row !== null)) {
1390
                                                // Set comment properties
1391 2
                                                $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1);
1392 2
                                                $comment->getFillColor()->setRGB($fillColor);
1393
1394
                                                // Parse style
1395 2
                                                $styleArray = explode(';', str_replace(' ', '', $style));
1396 2
                                                foreach ($styleArray as $stylePair) {
1397 2
                                                    $stylePair = explode(':', $stylePair);
1398
1399 2
                                                    if ($stylePair[0] == 'margin-left') {
1400 2
                                                        $comment->setMarginLeft($stylePair[1]);
1401
                                                    }
1402 2
                                                    if ($stylePair[0] == 'margin-top') {
1403 2
                                                        $comment->setMarginTop($stylePair[1]);
1404
                                                    }
1405 2
                                                    if ($stylePair[0] == 'width') {
1406 2
                                                        $comment->setWidth($stylePair[1]);
1407
                                                    }
1408 2
                                                    if ($stylePair[0] == 'height') {
1409 2
                                                        $comment->setHeight($stylePair[1]);
1410
                                                    }
1411 2
                                                    if ($stylePair[0] == 'visibility') {
1412 2
                                                        $comment->setVisible($stylePair[1] == 'visible');
1413
                                                    }
1414
                                                }
1415
                                            }
1416
                                        }
1417
                                    }
1418
                                }
1419
1420
                                // Header/footer images
1421 8
                                if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->readDataOnly) {
1422
                                    if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1423
                                        $relsWorksheet = simplexml_load_string(
1424
                                            //~ http://schemas.openxmlformats.org/package/2006/relationships"
1425
                                            $this->securityScan(
1426
                                                $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1427
                                            ),
1428
                                            'SimpleXMLElement',
1429
                                            Settings::getLibXmlLoaderOptions()
1430
                                        );
1431
                                        $vmlRelationship = '';
1432
1433
                                        foreach ($relsWorksheet->Relationship as $ele) {
1434
                                            if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing') {
1435
                                                $vmlRelationship = self::dirAdd("$dir/$fileWorksheet", $ele['Target']);
1436
                                            }
1437
                                        }
1438
1439
                                        if ($vmlRelationship != '') {
1440
                                            // Fetch linked images
1441
                                            $relsVML = simplexml_load_string(
1442
                                                //~ http://schemas.openxmlformats.org/package/2006/relationships"
1443
                                                $this->securityScan(
1444
                                                    $this->getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels')
1445
                                                ),
1446
                                                'SimpleXMLElement',
1447
                                                Settings::getLibXmlLoaderOptions()
1448
                                            );
1449
                                            $drawings = [];
1450 View Code Duplication
                                            foreach ($relsVML->Relationship as $ele) {
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...
1451
                                                if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1452
                                                    $drawings[(string) $ele['Id']] = self::dirAdd($vmlRelationship, $ele['Target']);
1453
                                                }
1454
                                            }
1455
1456
                                            // Fetch VML document
1457
                                            $vmlDrawing = simplexml_load_string(
1458
                                                $this->securityScan($this->getFromZipArchive($zip, $vmlRelationship)),
1459
                                                'SimpleXMLElement',
1460
                                                Settings::getLibXmlLoaderOptions()
1461
                                            );
1462
                                            $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1463
1464
                                            $hfImages = [];
1465
1466
                                            $shapes = $vmlDrawing->xpath('//v:shape');
1467
                                            foreach ($shapes as $idx => $shape) {
1468
                                                $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1469
                                                $imageData = $shape->xpath('//v:imagedata');
1470
1471
                                                if (!$imageData) {
1472
                                                    continue;
1473
                                                }
1474
1475
                                                $imageData = $imageData[$idx];
1476
1477
                                                $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office');
1478
                                                $style = self::toCSSArray((string) $shape['style']);
1479
1480
                                                $hfImages[(string) $shape['id']] = new Worksheet\HeaderFooterDrawing();
1481
                                                if (isset($imageData['title'])) {
1482
                                                    $hfImages[(string) $shape['id']]->setName((string) $imageData['title']);
1483
                                                }
1484
1485
                                                $hfImages[(string) $shape['id']]->setPath('zip://' . File::realpath($pFilename) . '#' . $drawings[(string) $imageData['relid']], false);
1486
                                                $hfImages[(string) $shape['id']]->setResizeProportional(false);
1487
                                                $hfImages[(string) $shape['id']]->setWidth($style['width']);
1488
                                                $hfImages[(string) $shape['id']]->setHeight($style['height']);
1489
                                                if (isset($style['margin-left'])) {
1490
                                                    $hfImages[(string) $shape['id']]->setOffsetX($style['margin-left']);
1491
                                                }
1492
                                                $hfImages[(string) $shape['id']]->setOffsetY($style['margin-top']);
1493
                                                $hfImages[(string) $shape['id']]->setResizeProportional(true);
1494
                                            }
1495
1496
                                            $docSheet->getHeaderFooter()->setImages($hfImages);
1497
                                        }
1498
                                    }
1499
                                }
1500
                            }
1501
1502
                            // TODO: Autoshapes from twoCellAnchors!
1503 8
                            if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1504 8
                                $relsWorksheet = simplexml_load_string(
1505
                                    //~ http://schemas.openxmlformats.org/package/2006/relationships"
1506 8
                                    $this->securityScan(
1507 8
                                        $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1508
                                    ),
1509 8
                                    'SimpleXMLElement',
1510 8
                                    Settings::getLibXmlLoaderOptions()
1511
                                );
1512 8
                                $drawings = [];
1513 8 View Code Duplication
                                foreach ($relsWorksheet->Relationship as $ele) {
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...
1514 5
                                    if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing') {
1515 3
                                        $drawings[(string) $ele['Id']] = self::dirAdd("$dir/$fileWorksheet", $ele['Target']);
1516
                                    }
1517
                                }
1518 8
                                if ($xmlSheet->drawing && !$this->readDataOnly) {
1519 3
                                    foreach ($xmlSheet->drawing as $drawing) {
1520 3
                                        $fileDrawing = $drawings[(string) self::getArrayItem($drawing->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id')];
1521 3
                                        $relsDrawing = simplexml_load_string(
1522
                                            //~ http://schemas.openxmlformats.org/package/2006/relationships"
1523 3
                                            $this->securityScan(
1524 3
                                                $this->getFromZipArchive($zip, dirname($fileDrawing) . '/_rels/' . basename($fileDrawing) . '.rels')
1525
                                            ),
1526 3
                                            'SimpleXMLElement',
1527 3
                                            Settings::getLibXmlLoaderOptions()
1528
                                        );
1529 3
                                        $images = [];
1530
1531 3
                                        if ($relsDrawing && $relsDrawing->Relationship) {
1532 3
                                            foreach ($relsDrawing->Relationship as $ele) {
1533 3
                                                if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1534 3
                                                    $images[(string) $ele['Id']] = self::dirAdd($fileDrawing, $ele['Target']);
1535 1
                                                } elseif ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart') {
1536 1
                                                    if ($this->includeCharts) {
1537 1
                                                        $charts[self::dirAdd($fileDrawing, $ele['Target'])] = [
1538 1
                                                            'id' => (string) $ele['Id'],
1539 1
                                                            'sheet' => $docSheet->getTitle(),
1540
                                                        ];
1541
                                                    }
1542
                                                }
1543
                                            }
1544
                                        }
1545 3
                                        $xmlDrawing = simplexml_load_string(
1546 3
                                            $this->securityScan($this->getFromZipArchive($zip, $fileDrawing)),
1547 3
                                            'SimpleXMLElement',
1548 3
                                            Settings::getLibXmlLoaderOptions()
1549 3
                                        )->children('http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
1550
1551 3
                                        if ($xmlDrawing->oneCellAnchor) {
1552 2
                                            foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) {
1553 2
                                                if ($oneCellAnchor->pic->blipFill) {
1554
                                                    /** @var \SimpleXMLElement $blip */
1555 2
                                                    $blip = $oneCellAnchor->pic->blipFill->children('http://schemas.openxmlformats.org/drawingml/2006/main')->blip;
1556
                                                    /** @var \SimpleXMLElement $xfrm */
1557 2
                                                    $xfrm = $oneCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->xfrm;
1558
                                                    /** @var \SimpleXMLElement $outerShdw */
1559 2
                                                    $outerShdw = $oneCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->effectLst->outerShdw;
1560 2
                                                    $objDrawing = new Worksheet\Drawing();
1561 2
                                                    $objDrawing->setName((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'name'));
1562 2
                                                    $objDrawing->setDescription((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'descr'));
1563 2
                                                    $objDrawing->setPath(
1564 2
                                                        'zip://' . File::realpath($pFilename) . '#' .
1565 2
                                                        $images[(string) self::getArrayItem(
1566 2
                                                            $blip->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
1567 2
                                                            'embed'
1568
                                                        )],
1569 2
                                                        false
1570
                                                    );
1571 2
                                                    $objDrawing->setCoordinates(Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1));
1572 2
                                                    $objDrawing->setOffsetX(Drawing::EMUToPixels($oneCellAnchor->from->colOff));
1573 2
                                                    $objDrawing->setOffsetY(Drawing::EMUToPixels($oneCellAnchor->from->rowOff));
1574 2
                                                    $objDrawing->setResizeProportional(false);
1575 2
                                                    $objDrawing->setWidth(Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), 'cx')));
1576 2
                                                    $objDrawing->setHeight(Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), 'cy')));
1577 2
                                                    if ($xfrm) {
1578 2
                                                        $objDrawing->setRotation(Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), 'rot')));
1579
                                                    }
1580 2 View Code Duplication
                                                    if ($outerShdw) {
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...
1581 2
                                                        $shadow = $objDrawing->getShadow();
1582 2
                                                        $shadow->setVisible(true);
1583 2
                                                        $shadow->setBlurRadius(Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'blurRad')));
1584 2
                                                        $shadow->setDistance(Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'dist')));
1585 2
                                                        $shadow->setDirection(Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), 'dir')));
1586 2
                                                        $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), 'algn'));
1587 2
                                                        $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), 'val'));
1588 2
                                                        $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), 'val') / 1000);
1589
                                                    }
1590 2
                                                    $objDrawing->setWorksheet($docSheet);
1591
                                                } else {
1592
                                                    //    ? Can charts be positioned with a oneCellAnchor ?
1593
                                                    $coordinates = Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1);
0 ignored issues
show
Unused Code introduced by
$coordinates 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...
1594
                                                    $offsetX = Drawing::EMUToPixels($oneCellAnchor->from->colOff);
0 ignored issues
show
Unused Code introduced by
$offsetX 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...
1595
                                                    $offsetY = Drawing::EMUToPixels($oneCellAnchor->from->rowOff);
0 ignored issues
show
Unused Code introduced by
$offsetY 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...
1596
                                                    $width = Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), 'cx'));
0 ignored issues
show
Unused Code introduced by
$width 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...
1597
                                                    $height = Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), 'cy'));
0 ignored issues
show
Unused Code introduced by
$height 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...
1598
                                                }
1599
                                            }
1600
                                        }
1601 3
                                        if ($xmlDrawing->twoCellAnchor) {
1602 1
                                            foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) {
1603 1
                                                if ($twoCellAnchor->pic->blipFill) {
1604 1
                                                    $blip = $twoCellAnchor->pic->blipFill->children('http://schemas.openxmlformats.org/drawingml/2006/main')->blip;
1605 1
                                                    $xfrm = $twoCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->xfrm;
1606 1
                                                    $outerShdw = $twoCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->effectLst->outerShdw;
1607 1
                                                    $objDrawing = new Worksheet\Drawing();
1608 1
                                                    $objDrawing->setName((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'name'));
1609 1
                                                    $objDrawing->setDescription((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'descr'));
1610 1
                                                    $objDrawing->setPath(
1611 1
                                                        'zip://' . File::realpath($pFilename) . '#' .
1612 1
                                                        $images[(string) self::getArrayItem(
1613 1
                                                            $blip->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
1614 1
                                                            'embed'
1615
                                                        )],
1616 1
                                                        false
1617
                                                    );
1618 1
                                                    $objDrawing->setCoordinates(Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1));
1619 1
                                                    $objDrawing->setOffsetX(Drawing::EMUToPixels($twoCellAnchor->from->colOff));
1620 1
                                                    $objDrawing->setOffsetY(Drawing::EMUToPixels($twoCellAnchor->from->rowOff));
1621 1
                                                    $objDrawing->setResizeProportional(false);
1622
1623 1
                                                    if ($xfrm) {
1624 1
                                                        $objDrawing->setWidth(Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), 'cx')));
1625 1
                                                        $objDrawing->setHeight(Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), 'cy')));
1626 1
                                                        $objDrawing->setRotation(Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), 'rot')));
1627
                                                    }
1628 1 View Code Duplication
                                                    if ($outerShdw) {
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...
1629
                                                        $shadow = $objDrawing->getShadow();
1630
                                                        $shadow->setVisible(true);
1631
                                                        $shadow->setBlurRadius(Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'blurRad')));
1632
                                                        $shadow->setDistance(Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'dist')));
1633
                                                        $shadow->setDirection(Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), 'dir')));
1634
                                                        $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), 'algn'));
1635
                                                        $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), 'val'));
1636
                                                        $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), 'val') / 1000);
1637
                                                    }
1638 1
                                                    $objDrawing->setWorksheet($docSheet);
1639 1
                                                } elseif (($this->includeCharts) && ($twoCellAnchor->graphicFrame)) {
1640 1
                                                    $fromCoordinate = Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1);
1641 1
                                                    $fromOffsetX = Drawing::EMUToPixels($twoCellAnchor->from->colOff);
1642 1
                                                    $fromOffsetY = Drawing::EMUToPixels($twoCellAnchor->from->rowOff);
1643 1
                                                    $toCoordinate = Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1);
1644 1
                                                    $toOffsetX = Drawing::EMUToPixels($twoCellAnchor->to->colOff);
1645 1
                                                    $toOffsetY = Drawing::EMUToPixels($twoCellAnchor->to->rowOff);
1646 1
                                                    $graphic = $twoCellAnchor->graphicFrame->children('http://schemas.openxmlformats.org/drawingml/2006/main')->graphic;
1647
                                                    /** @var \SimpleXMLElement $chartRef */
1648 1
                                                    $chartRef = $graphic->graphicData->children('http://schemas.openxmlformats.org/drawingml/2006/chart')->chart;
1649 1
                                                    $thisChart = (string) $chartRef->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1650
1651 1
                                                    $chartDetails[$docSheet->getTitle() . '!' . $thisChart] = [
1652 1
                                                        'fromCoordinate' => $fromCoordinate,
1653 1
                                                        'fromOffsetX' => $fromOffsetX,
1654 1
                                                        'fromOffsetY' => $fromOffsetY,
1655 1
                                                        'toCoordinate' => $toCoordinate,
1656 1
                                                        'toOffsetX' => $toOffsetX,
1657 1
                                                        'toOffsetY' => $toOffsetY,
1658 1
                                                        'worksheetTitle' => $docSheet->getTitle(),
1659
                                                    ];
1660
                                                }
1661
                                            }
1662
                                        }
1663
                                    }
1664
                                }
1665
                            }
1666
1667
                            // Loop through definedNames
1668 8
                            if ($xmlWorkbook->definedNames) {
1669 5
                                foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1670
                                    // Extract range
1671 1
                                    $extractedRange = (string) $definedName;
1672 1 View Code Duplication
                                    if (($spos = strpos($extractedRange, '!')) !== false) {
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...
1673 1
                                        $extractedRange = substr($extractedRange, 0, $spos) . str_replace('$', '', substr($extractedRange, $spos));
1674
                                    } else {
1675
                                        $extractedRange = str_replace('$', '', $extractedRange);
1676
                                    }
1677
1678
                                    // Valid range?
1679 1
                                    if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') {
1680
                                        continue;
1681
                                    }
1682
1683
                                    // Some definedNames are only applicable if we are on the same sheet...
1684 1
                                    if ((string) $definedName['localSheetId'] != '' && (string) $definedName['localSheetId'] == $sheetId) {
1685
                                        // Switch on type
1686 1
                                        switch ((string) $definedName['name']) {
1687 1
                                            case '_xlnm._FilterDatabase':
1688
                                                if ((string) $definedName['hidden'] !== '1') {
1689
                                                    $extractedRange = explode(',', $extractedRange);
1690
                                                    foreach ($extractedRange as $range) {
1691
                                                        $autoFilterRange = $range;
1692
                                                        if (strpos($autoFilterRange, ':') !== false) {
1693
                                                            $docSheet->getAutoFilter()->setRange($autoFilterRange);
1694
                                                        }
1695
                                                    }
1696
                                                }
1697
                                                break;
1698 1
                                            case '_xlnm.Print_Titles':
1699
                                                // Split $extractedRange
1700 1
                                                $extractedRange = explode(',', $extractedRange);
1701
1702
                                                // Set print titles
1703 1
                                                foreach ($extractedRange as $range) {
1704 1
                                                    $matches = [];
1705 1
                                                    $range = str_replace('$', '', $range);
1706
1707
                                                    // check for repeating columns, e g. 'A:A' or 'A:D'
1708 1
                                                    if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) {
1709
                                                        $docSheet->getPageSetup()->setColumnsToRepeatAtLeft([$matches[1], $matches[2]]);
1710 1
                                                    } elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) {
1711
                                                        // check for repeating rows, e.g. '1:1' or '1:5'
1712 1
                                                        $docSheet->getPageSetup()->setRowsToRepeatAtTop([$matches[1], $matches[2]]);
1713
                                                    }
1714
                                                }
1715 1
                                                break;
1716
                                            case '_xlnm.Print_Area':
1717
                                                $rangeSets = preg_split("/'(.*?)'(?:![A-Z0-9]+:[A-Z0-9]+,?)/", $extractedRange, PREG_SPLIT_NO_EMPTY);
1718
                                                $newRangeSets = [];
1719
                                                foreach ($rangeSets as $rangeSet) {
1720
                                                    $range = explode('!', $rangeSet); // FIXME: what if sheetname contains exclamation mark?
1721
                                                    $rangeSet = isset($range[1]) ? $range[1] : $range[0];
1722
                                                    if (strpos($rangeSet, ':') === false) {
1723
                                                        $rangeSet = $rangeSet . ':' . $rangeSet;
1724
                                                    }
1725
                                                    $newRangeSets[] = str_replace('$', '', $rangeSet);
1726
                                                }
1727
                                                $docSheet->getPageSetup()->setPrintArea(implode(',', $newRangeSets));
1728
                                                break;
1729
                                            default:
1730 1
                                                break;
1731
                                        }
1732
                                    }
1733
                                }
1734
                            }
1735
1736
                            // Next sheet id
1737 8
                            ++$sheetId;
1738
                        }
1739
1740
                        // Loop through definedNames
1741 8
                        if ($xmlWorkbook->definedNames) {
1742 5
                            foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1743
                                // Extract range
1744 1
                                $extractedRange = (string) $definedName;
1745 1 View Code Duplication
                                if (($spos = strpos($extractedRange, '!')) !== false) {
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...
1746 1
                                    $extractedRange = substr($extractedRange, 0, $spos) . str_replace('$', '', substr($extractedRange, $spos));
1747
                                } else {
1748
                                    $extractedRange = str_replace('$', '', $extractedRange);
1749
                                }
1750
1751
                                // Valid range?
1752 1
                                if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') {
1753
                                    continue;
1754
                                }
1755
1756
                                // Some definedNames are only applicable if we are on the same sheet...
1757 1
                                if ((string) $definedName['localSheetId'] != '') {
1758
                                    // Local defined name
1759
                                    // Switch on type
1760 1
                                    switch ((string) $definedName['name']) {
1761 1
                                        case '_xlnm._FilterDatabase':
1762 1
                                        case '_xlnm.Print_Titles':
1763
                                        case '_xlnm.Print_Area':
1764 1
                                            break;
1765
                                        default:
1766
                                            if ($mapSheetId[(int) $definedName['localSheetId']] !== null) {
1767
                                                $range = explode('!', (string) $definedName);
1768
                                                if (count($range) == 2) {
1769
                                                    $range[0] = str_replace("''", "'", $range[0]);
1770
                                                    $range[0] = str_replace("'", '', $range[0]);
1771
                                                    if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) {
1772
                                                        $extractedRange = str_replace('$', '', $range[1]);
1773
                                                        $scope = $docSheet->getParent()->getSheet($mapSheetId[(int) $definedName['localSheetId']]);
0 ignored issues
show
Bug introduced by
The variable $docSheet 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...
1774
                                                        $excel->addNamedRange(new NamedRange((string) $definedName['name'], $worksheet, $extractedRange, true, $scope));
1775
                                                    }
1776
                                                }
1777
                                            }
1778 1
                                            break;
1779
                                    }
1780
                                } elseif (!isset($definedName['localSheetId'])) {
1781
                                    // "Global" definedNames
1782
                                    $locatedSheet = null;
1783
                                    $extractedSheetName = '';
0 ignored issues
show
Unused Code introduced by
$extractedSheetName 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...
1784
                                    if (strpos((string) $definedName, '!') !== false) {
1785
                                        // Extract sheet name
1786
                                        $extractedSheetName = Worksheet::extractSheetTitle((string) $definedName, true);
1787
                                        $extractedSheetName = $extractedSheetName[0];
1788
1789
                                        // Locate sheet
1790
                                        $locatedSheet = $excel->getSheetByName($extractedSheetName);
1791
1792
                                        // Modify range
1793
                                        $range = explode('!', $extractedRange);
1794
                                        $extractedRange = isset($range[1]) ? $range[1] : $range[0];
1795
                                    }
1796
1797
                                    if ($locatedSheet !== null) {
1798
                                        $excel->addNamedRange(new NamedRange((string) $definedName['name'], $locatedSheet, $extractedRange, false));
1799
                                    }
1800
                                }
1801
                            }
1802
                        }
1803
                    }
1804
1805 8
                    if ((!$this->readDataOnly) || (!empty($this->loadSheetsOnly))) {
1806
                        // active sheet index
1807 8
                        $activeTab = (int) ($xmlWorkbook->bookViews->workbookView['activeTab']); // refers to old sheet index
1808
1809
                        // keep active sheet index if sheet is still loaded, else first sheet is set as the active
1810 8
                        if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
1811 8
                            $excel->setActiveSheetIndex($mapSheetId[$activeTab]);
1812
                        } else {
1813
                            if ($excel->getSheetCount() == 0) {
1814
                                $excel->createSheet();
1815
                            }
1816
                            $excel->setActiveSheetIndex(0);
1817
                        }
1818
                    }
1819 8
                    break;
1820
            }
1821
        }
1822
1823 8
        if (!$this->readDataOnly) {
1824 8
            $contentTypes = simplexml_load_string(
1825 8
                $this->securityScan(
1826 8
                    $this->getFromZipArchive($zip, '[Content_Types].xml')
1827
                ),
1828 8
                'SimpleXMLElement',
1829 8
                Settings::getLibXmlLoaderOptions()
1830
            );
1831 8
            foreach ($contentTypes->Override as $contentType) {
1832 8
                switch ($contentType['ContentType']) {
1833 8
                    case 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml':
1834 1
                        if ($this->includeCharts) {
1835 1
                            $chartEntryRef = ltrim($contentType['PartName'], '/');
1836 1
                            $chartElements = simplexml_load_string(
1837 1
                                $this->securityScan(
1838 1
                                    $this->getFromZipArchive($zip, $chartEntryRef)
1839
                                ),
1840 1
                                'SimpleXMLElement',
1841 1
                                Settings::getLibXmlLoaderOptions()
1842
                            );
1843 1
                            $objChart = Chart::readChart($chartElements, basename($chartEntryRef, '.xml'));
1844
1845 1
                            if (isset($charts[$chartEntryRef])) {
1846 1
                                $chartPositionRef = $charts[$chartEntryRef]['sheet'] . '!' . $charts[$chartEntryRef]['id'];
1847 1
                                if (isset($chartDetails[$chartPositionRef])) {
1848 1
                                    $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart);
1849 1
                                    $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet']));
1850 1
                                    $objChart->setTopLeftPosition($chartDetails[$chartPositionRef]['fromCoordinate'], $chartDetails[$chartPositionRef]['fromOffsetX'], $chartDetails[$chartPositionRef]['fromOffsetY']);
1851 8
                                    $objChart->setBottomRightPosition($chartDetails[$chartPositionRef]['toCoordinate'], $chartDetails[$chartPositionRef]['toOffsetX'], $chartDetails[$chartPositionRef]['toOffsetY']);
1852
                                }
1853
                            }
1854
                        }
1855
                }
1856
            }
1857
        }
1858
1859 8
        $zip->close();
1860
1861 8
        return $excel;
1862
    }
1863
1864 8
    private static function readColor($color, $background = false)
1865
    {
1866 8
        if (isset($color['rgb'])) {
1867 7
            return (string) $color['rgb'];
1868 4
        } elseif (isset($color['indexed'])) {
1869 3
            return Style\Color::indexedColor($color['indexed'] - 7, $background)->getARGB();
1870 3
        } elseif (isset($color['theme'])) {
1871 3
            if (self::$theme !== null) {
1872 3
                $returnColour = self::$theme->getColourByIndex((int) $color['theme']);
1873 3
                if (isset($color['tint'])) {
1874
                    $tintAdjust = (float) $color['tint'];
1875
                    $returnColour = Style\Color::changeBrightness($returnColour, $tintAdjust);
1876
                }
1877
1878 3
                return 'FF' . $returnColour;
1879
            }
1880
        }
1881
1882
        if ($background) {
1883
            return 'FFFFFFFF';
1884
        }
1885
1886
        return 'FF000000';
1887
    }
1888
1889
    /**
1890
     * @param Style $docStyle
1891
     * @param \stdClass|\SimpleXMLElement $style
1892
     */
1893 8
    private static function readStyle(Style $docStyle, $style)
1894
    {
1895 8
        $docStyle->getNumberFormat()->setFormatCode($style->numFmt);
1896
1897
        // font
1898 8
        if (isset($style->font)) {
1899 8
            $docStyle->getFont()->setName((string) $style->font->name['val']);
1900 8
            $docStyle->getFont()->setSize((string) $style->font->sz['val']);
1901 8 View Code Duplication
            if (isset($style->font->b)) {
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...
1902 7
                $docStyle->getFont()->setBold(!isset($style->font->b['val']) || self::boolean((string) $style->font->b['val']));
1903
            }
1904 8 View Code Duplication
            if (isset($style->font->i)) {
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...
1905 5
                $docStyle->getFont()->setItalic(!isset($style->font->i['val']) || self::boolean((string) $style->font->i['val']));
1906
            }
1907 8 View Code Duplication
            if (isset($style->font->strike)) {
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...
1908 5
                $docStyle->getFont()->setStrikethrough(!isset($style->font->strike['val']) || self::boolean((string) $style->font->strike['val']));
1909
            }
1910 8
            $docStyle->getFont()->getColor()->setARGB(self::readColor($style->font->color));
1911
1912 8 View Code Duplication
            if (isset($style->font->u) && !isset($style->font->u['val'])) {
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...
1913
                $docStyle->getFont()->setUnderline(Style\Font::UNDERLINE_SINGLE);
1914 5
            } elseif (isset($style->font->u) && isset($style->font->u['val'])) {
1915 5
                $docStyle->getFont()->setUnderline((string) $style->font->u['val']);
1916
            }
1917
1918 8 View Code Duplication
            if (isset($style->font->vertAlign) && isset($style->font->vertAlign['val'])) {
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...
1919
                $vertAlign = strtolower((string) $style->font->vertAlign['val']);
1920
                if ($vertAlign == 'superscript') {
1921
                    $docStyle->getFont()->setSuperScript(true);
1922
                }
1923
                if ($vertAlign == 'subscript') {
1924
                    $docStyle->getFont()->setSubScript(true);
1925
                }
1926
            }
1927
        }
1928
1929
        // fill
1930 8
        if (isset($style->fill)) {
1931 8
            if ($style->fill->gradientFill) {
1932
                /** @var \SimpleXMLElement $gradientFill */
1933 2
                $gradientFill = $style->fill->gradientFill[0];
1934 2
                if (!empty($gradientFill['type'])) {
1935 2
                    $docStyle->getFill()->setFillType((string) $gradientFill['type']);
1936
                }
1937 2
                $docStyle->getFill()->setRotation((float) ($gradientFill['degree']));
1938 2
                $gradientFill->registerXPathNamespace('sml', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
1939 2
                $docStyle->getFill()->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color));
1940 2
                $docStyle->getFill()->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color));
1941 8
            } elseif ($style->fill->patternFill) {
1942 8
                $patternType = (string) $style->fill->patternFill['patternType'] != '' ? (string) $style->fill->patternFill['patternType'] : 'solid';
1943 8
                $docStyle->getFill()->setFillType($patternType);
1944 8
                if ($style->fill->patternFill->fgColor) {
1945 3
                    $docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true));
1946
                } else {
1947 8
                    $docStyle->getFill()->getStartColor()->setARGB('FF000000');
1948
                }
1949 8
                if ($style->fill->patternFill->bgColor) {
1950 3
                    $docStyle->getFill()->getEndColor()->setARGB(self::readColor($style->fill->patternFill->bgColor, true));
1951
                }
1952
            }
1953
        }
1954
1955
        // border
1956 8
        if (isset($style->border)) {
1957 8
            $diagonalUp = self::boolean((string) $style->border['diagonalUp']);
1958 8
            $diagonalDown = self::boolean((string) $style->border['diagonalDown']);
1959 8
            if (!$diagonalUp && !$diagonalDown) {
1960 8
                $docStyle->getBorders()->setDiagonalDirection(Style\Borders::DIAGONAL_NONE);
1961
            } elseif ($diagonalUp && !$diagonalDown) {
1962
                $docStyle->getBorders()->setDiagonalDirection(Style\Borders::DIAGONAL_UP);
1963
            } elseif (!$diagonalUp && $diagonalDown) {
1964
                $docStyle->getBorders()->setDiagonalDirection(Style\Borders::DIAGONAL_DOWN);
1965
            } else {
1966
                $docStyle->getBorders()->setDiagonalDirection(Style\Borders::DIAGONAL_BOTH);
1967
            }
1968 8
            self::readBorder($docStyle->getBorders()->getLeft(), $style->border->left);
1969 8
            self::readBorder($docStyle->getBorders()->getRight(), $style->border->right);
1970 8
            self::readBorder($docStyle->getBorders()->getTop(), $style->border->top);
1971 8
            self::readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom);
1972 8
            self::readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal);
1973
        }
1974
1975
        // alignment
1976 8
        if (isset($style->alignment)) {
1977 8
            $docStyle->getAlignment()->setHorizontal((string) $style->alignment['horizontal']);
1978 8
            $docStyle->getAlignment()->setVertical((string) $style->alignment['vertical']);
1979
1980 8
            $textRotation = 0;
1981 8
            if ((int) $style->alignment['textRotation'] <= 90) {
1982 8
                $textRotation = (int) $style->alignment['textRotation'];
1983
            } elseif ((int) $style->alignment['textRotation'] > 90) {
1984
                $textRotation = 90 - (int) $style->alignment['textRotation'];
1985
            }
1986
1987 8
            $docStyle->getAlignment()->setTextRotation((int) $textRotation);
1988 8
            $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment['wrapText']));
1989 8
            $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment['shrinkToFit']));
1990 8
            $docStyle->getAlignment()->setIndent((int) ((string) $style->alignment['indent']) > 0 ? (int) ((string) $style->alignment['indent']) : 0);
1991 8
            $docStyle->getAlignment()->setReadorder((int) ((string) $style->alignment['readingOrder']) > 0 ? (int) ((string) $style->alignment['readingOrder']) : 0);
1992
        }
1993
1994
        // protection
1995 8
        if (isset($style->protection)) {
1996 8 View Code Duplication
            if (isset($style->protection['locked'])) {
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...
1997 2
                if (self::boolean((string) $style->protection['locked'])) {
1998
                    $docStyle->getProtection()->setLocked(Style\Protection::PROTECTION_PROTECTED);
1999
                } else {
2000 2
                    $docStyle->getProtection()->setLocked(Style\Protection::PROTECTION_UNPROTECTED);
2001
                }
2002
            }
2003
2004 8 View Code Duplication
            if (isset($style->protection['hidden'])) {
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...
2005
                if (self::boolean((string) $style->protection['hidden'])) {
2006
                    $docStyle->getProtection()->setHidden(Style\Protection::PROTECTION_PROTECTED);
2007
                } else {
2008
                    $docStyle->getProtection()->setHidden(Style\Protection::PROTECTION_UNPROTECTED);
2009
                }
2010
            }
2011
        }
2012
2013
        // top-level style settings
2014 8
        if (isset($style->quotePrefix)) {
2015 8
            $docStyle->setQuotePrefix($style->quotePrefix);
2016
        }
2017 8
    }
2018
2019
    /**
2020
     * @param Style\Border $docBorder
2021
     * @param \SimpleXMLElement $eleBorder
2022
     */
2023 8
    private static function readBorder($docBorder, $eleBorder)
2024
    {
2025 8
        if (isset($eleBorder['style'])) {
2026 2
            $docBorder->setBorderStyle((string) $eleBorder['style']);
2027
        }
2028 8
        if (isset($eleBorder->color)) {
2029 2
            $docBorder->getColor()->setARGB(self::readColor($eleBorder->color));
2030
        }
2031 8
    }
2032
2033
    /**
2034
     * @param \SimpleXMLElement | null $is
2035
     *
2036
     * @return RichText
2037
     */
2038 3
    private function parseRichText($is = null)
2039
    {
2040 3
        $value = new RichText();
2041
2042 3
        if (isset($is->t)) {
2043
            $value->createText(StringHelper::controlCharacterOOXML2PHP((string) $is->t));
2044
        } else {
2045 3
            if (is_object($is->r)) {
2046 3
                foreach ($is->r as $run) {
2047 3
                    if (!isset($run->rPr)) {
2048 3
                        $objText = $value->createText(StringHelper::controlCharacterOOXML2PHP((string) $run->t));
0 ignored issues
show
Unused Code introduced by
$objText 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...
2049
                    } else {
2050 3
                        $objText = $value->createTextRun(StringHelper::controlCharacterOOXML2PHP((string) $run->t));
2051
2052 3 View Code Duplication
                        if (isset($run->rPr->rFont['val'])) {
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...
2053 3
                            $objText->getFont()->setName((string) $run->rPr->rFont['val']);
2054
                        }
2055 3
                        if (isset($run->rPr->sz['val'])) {
2056 3
                            $objText->getFont()->setSize((string) $run->rPr->sz['val']);
2057
                        }
2058 3
                        if (isset($run->rPr->color)) {
2059 3
                            $objText->getFont()->setColor(new Style\Color(self::readColor($run->rPr->color)));
2060
                        }
2061 3 View Code Duplication
                        if ((isset($run->rPr->b['val']) && self::boolean((string) $run->rPr->b['val'])) ||
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...
2062 3
                            (isset($run->rPr->b) && !isset($run->rPr->b['val']))) {
2063 3
                            $objText->getFont()->setBold(true);
2064
                        }
2065 3 View Code Duplication
                        if ((isset($run->rPr->i['val']) && self::boolean((string) $run->rPr->i['val'])) ||
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...
2066 2
                            (isset($run->rPr->i) && !isset($run->rPr->i['val']))) {
2067 2
                            $objText->getFont()->setItalic(true);
2068
                        }
2069 3 View Code Duplication
                        if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign['val'])) {
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...
2070
                            $vertAlign = strtolower((string) $run->rPr->vertAlign['val']);
2071
                            if ($vertAlign == 'superscript') {
2072
                                $objText->getFont()->setSuperScript(true);
2073
                            }
2074
                            if ($vertAlign == 'subscript') {
2075
                                $objText->getFont()->setSubScript(true);
2076
                            }
2077
                        }
2078 3 View Code Duplication
                        if (isset($run->rPr->u) && !isset($run->rPr->u['val'])) {
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...
2079
                            $objText->getFont()->setUnderline(Style\Font::UNDERLINE_SINGLE);
2080 2
                        } elseif (isset($run->rPr->u) && isset($run->rPr->u['val'])) {
2081 2
                            $objText->getFont()->setUnderline((string) $run->rPr->u['val']);
2082
                        }
2083 3 View Code Duplication
                        if ((isset($run->rPr->strike['val']) && self::boolean((string) $run->rPr->strike['val'])) ||
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...
2084 2
                            (isset($run->rPr->strike) && !isset($run->rPr->strike['val']))) {
2085
                            $objText->getFont()->setStrikethrough(true);
2086
                        }
2087
                    }
2088
                }
2089
            }
2090
        }
2091
2092 3
        return $value;
2093
    }
2094
2095
    /**
2096
     * @param Spreadsheet $excel
2097
     * @param mixed $customUITarget
2098
     * @param mixed $zip
2099
     */
2100
    private function readRibbon(Spreadsheet $excel, $customUITarget, $zip)
2101
    {
2102
        $baseDir = dirname($customUITarget);
2103
        $nameCustomUI = basename($customUITarget);
2104
        // get the xml file (ribbon)
2105
        $localRibbon = $this->getFromZipArchive($zip, $customUITarget);
2106
        $customUIImagesNames = [];
2107
        $customUIImagesBinaries = [];
2108
        // something like customUI/_rels/customUI.xml.rels
2109
        $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels';
2110
        $dataRels = $this->getFromZipArchive($zip, $pathRels);
2111
        if ($dataRels) {
2112
            // exists and not empty if the ribbon have some pictures (other than internal MSO)
2113
            $UIRels = simplexml_load_string(
2114
                $this->securityScan($dataRels),
2115
                'SimpleXMLElement',
2116
                Settings::getLibXmlLoaderOptions()
2117
            );
2118
            if ($UIRels) {
2119
                // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image
2120
                foreach ($UIRels->Relationship as $ele) {
2121
                    if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
2122
                        // an image ?
2123
                        $customUIImagesNames[(string) $ele['Id']] = (string) $ele['Target'];
2124
                        $customUIImagesBinaries[(string) $ele['Target']] = $this->getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']);
2125
                    }
2126
                }
2127
            }
2128
        }
2129
        if ($localRibbon) {
2130
            $excel->setRibbonXMLData($customUITarget, $localRibbon);
2131
            if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) {
2132
                $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries);
2133
            } else {
2134
                $excel->setRibbonBinObjects(null);
2135
            }
2136
        } else {
2137
            $excel->setRibbonXMLData(null);
2138
            $excel->setRibbonBinObjects(null);
2139
        }
2140
    }
2141
2142 9
    private static function getArrayItem($array, $key = 0)
2143
    {
2144 9
        return isset($array[$key]) ? $array[$key] : null;
2145
    }
2146
2147 3
    private static function dirAdd($base, $add)
2148
    {
2149 3
        return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
2150
    }
2151
2152
    private static function toCSSArray($style)
2153
    {
2154
        $style = str_replace(["\r", "\n"], '', $style);
2155
2156
        $temp = explode(';', $style);
2157
        $style = [];
2158
        foreach ($temp as $item) {
2159
            $item = explode(':', $item);
2160
2161
            if (strpos($item[1], 'px') !== false) {
2162
                $item[1] = str_replace('px', '', $item[1]);
2163
            }
2164 View Code Duplication
            if (strpos($item[1], 'pt') !== false) {
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...
2165
                $item[1] = str_replace('pt', '', $item[1]);
2166
                $item[1] = Font::fontSizeToPixels($item[1]);
2167
            }
2168 View Code Duplication
            if (strpos($item[1], 'in') !== false) {
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...
2169
                $item[1] = str_replace('in', '', $item[1]);
2170
                $item[1] = Font::inchSizeToPixels($item[1]);
2171
            }
2172 View Code Duplication
            if (strpos($item[1], 'cm') !== false) {
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...
2173
                $item[1] = str_replace('cm', '', $item[1]);
2174
                $item[1] = Font::centimeterSizeToPixels($item[1]);
2175
            }
2176
2177
            $style[$item[0]] = $item[1];
2178
        }
2179
2180
        return $style;
2181
    }
2182
2183 8
    private static function boolean($value = null)
2184
    {
2185 8
        if (is_object($value)) {
2186 1
            $value = (string) $value;
2187
        }
2188 8
        if (is_numeric($value)) {
2189 6
            return (bool) $value;
2190
        }
2191
2192 8
        return $value === 'true' || $value === 'TRUE';
2193
    }
2194
}
2195