Completed
Push — develop ( 4fd8e7...d3e769 )
by Adrien
14:12 queued 07:04
created

Xlsx::listWorksheetInfo()   C

Complexity

Conditions 12
Paths 20

Size

Total Lines 94
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 156

Importance

Changes 0
Metric Value
cc 12
eloc 60
nc 20
nop 1
dl 0
loc 94
ccs 0
cts 59
cp 0
crap 156
rs 5.034
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\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 XMLReader;
23
use ZipArchive;
24
25
class Xlsx extends BaseReader implements IReader
26
{
27
    /**
28
     * ReferenceHelper instance.
29
     *
30
     * @var ReferenceHelper
31
     */
32
    private $referenceHelper;
33
34
    /**
35
     * Xlsx\Theme instance.
36
     *
37
     * @var Xlsx\Theme
38
     */
39
    private static $theme = null;
40
41
    /**
42
     * Create a new Xlsx Reader instance.
43
     */
44 8
    public function __construct()
45
    {
46 8
        $this->readFilter = new DefaultReadFilter();
47 8
        $this->referenceHelper = ReferenceHelper::getInstance();
48
    }
49
50
    /**
51
     * Can the current IReader read the file?
52
     *
53
     * @param string $pFilename
54
     *
55
     * @throws Exception
56
     *
57
     * @return bool
58
     */
59
    public function canRead($pFilename)
60
    {
61
        File::assertFile($pFilename);
62
63
        $xl = false;
64
        // Load file
65
        $zip = new ZipArchive();
66
        if ($zip->open($pFilename) === true) {
67
            // check if it is an OOXML archive
68
            $rels = simplexml_load_string(
69
                $this->securityScan(
70
                    $this->getFromZipArchive($zip, '_rels/.rels')
71
                ),
72
                'SimpleXMLElement',
73
                Settings::getLibXmlLoaderOptions()
74
            );
75
            if ($rels !== false) {
76
                foreach ($rels->Relationship as $rel) {
77
                    switch ($rel['Type']) {
78
                        case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
79
                            if (basename($rel['Target']) == 'workbook.xml') {
80
                                $xl = true;
81
                            }
82
83
                            break;
84
                    }
85
                }
86
            }
87
            $zip->close();
88
        }
89
90
        return $xl;
91
    }
92
93
    /**
94
     * Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object.
95
     *
96
     * @param string $pFilename
97
     *
98
     * @throws Exception
99
     *
100
     * @return array
101
     */
102
    public function listWorksheetNames($pFilename)
103
    {
104
        File::assertFile($pFilename);
105
106
        $worksheetNames = [];
107
108
        $zip = new ZipArchive();
109
        $zip->open($pFilename);
110
111
        //    The files we're looking at here are small enough that simpleXML is more efficient than XMLReader
112
        $rels = simplexml_load_string(
113
            $this->securityScan($this->getFromZipArchive($zip, '_rels/.rels'))
114
        ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
115
        foreach ($rels->Relationship as $rel) {
116
            switch ($rel['Type']) {
117
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
118
                    $xmlWorkbook = simplexml_load_string(
119
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}"))
120
                    ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
121
122
                    if ($xmlWorkbook->sheets) {
123
                        foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
124
                            // Check if sheet should be skipped
125
                            $worksheetNames[] = (string) $eleSheet['name'];
126
                        }
127
                    }
128
            }
129
        }
130
131
        $zip->close();
132
133
        return $worksheetNames;
134
    }
135
136
    /**
137
     * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns).
138
     *
139
     * @param string $pFilename
140
     *
141
     * @throws Exception
142
     *
143
     * @return array
144
     */
145
    public function listWorksheetInfo($pFilename)
146
    {
147
        File::assertFile($pFilename);
148
149
        $worksheetInfo = [];
150
151
        $zip = new ZipArchive();
152
        $zip->open($pFilename);
153
154
        $rels = simplexml_load_string(
155
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
156
            $this->securityScan($this->getFromZipArchive($zip, '_rels/.rels')),
157
            'SimpleXMLElement',
158
            Settings::getLibXmlLoaderOptions()
159
        );
160
        foreach ($rels->Relationship as $rel) {
161
            if ($rel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument') {
162
                $dir = dirname($rel['Target']);
163
                $relsWorkbook = simplexml_load_string(
164
                    //~ http://schemas.openxmlformats.org/package/2006/relationships"
165
                    $this->securityScan(
166
                        $this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel['Target']) . '.rels')
167
                    ),
168
                    'SimpleXMLElement',
169
                    Settings::getLibXmlLoaderOptions()
170
                );
171
                $relsWorkbook->registerXPathNamespace('rel', 'http://schemas.openxmlformats.org/package/2006/relationships');
172
173
                $worksheets = [];
174
                foreach ($relsWorkbook->Relationship as $ele) {
175
                    if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') {
176
                        $worksheets[(string) $ele['Id']] = $ele['Target'];
177
                    }
178
                }
179
180
                $xmlWorkbook = simplexml_load_string(
181
                    //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
182
                    $this->securityScan(
183
                        $this->getFromZipArchive($zip, "{$rel['Target']}")
184
                    ),
185
                    'SimpleXMLElement',
186
                    Settings::getLibXmlLoaderOptions()
187
                );
188
                if ($xmlWorkbook->sheets) {
189
                    $dir = dirname($rel['Target']);
190
                    /** @var \SimpleXMLElement $eleSheet */
191
                    foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
192
                        $tmpInfo = [
193
                            'worksheetName' => (string) $eleSheet['name'],
194
                            'lastColumnLetter' => 'A',
195
                            'lastColumnIndex' => 0,
196
                            'totalRows' => 0,
197
                            'totalColumns' => 0,
198
                        ];
199
200
                        $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id')];
201
202
                        $xml = new XMLReader();
203
                        $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...
204
                            $this->securityScanFile(
205
                                'zip://' . File::realpath($pFilename) . '#' . "$dir/$fileWorksheet"
206
                            ),
207
                            null,
208
                            Settings::getLibXmlLoaderOptions()
209
                        );
210
                        $xml->setParserProperty(2, true);
211
212
                        $currCells = 0;
213
                        while ($xml->read()) {
214
                            if ($xml->name == 'row' && $xml->nodeType == XMLReader::ELEMENT) {
215
                                $row = $xml->getAttribute('r');
216
                                $tmpInfo['totalRows'] = $row;
217
                                $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
218
                                $currCells = 0;
219
                            } elseif ($xml->name == 'c' && $xml->nodeType == XMLReader::ELEMENT) {
220
                                ++$currCells;
221
                            }
222
                        }
223
                        $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
224
                        $xml->close();
225
226
                        $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
227
                        $tmpInfo['lastColumnLetter'] = Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
228
229
                        $worksheetInfo[] = $tmpInfo;
230
                    }
231
                }
232
            }
233
        }
234
235
        $zip->close();
236
237
        return $worksheetInfo;
238
    }
239
240
    private static function castToBoolean($c)
241
    {
242
        $value = isset($c->v) ? (string) $c->v : null;
243
        if ($value == '0') {
244
            return false;
245
        } elseif ($value == '1') {
246
            return true;
247
        }
248
249
        return (bool) $c->v;
250
        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...
251
    }
252
253
    private static function castToError($c)
254
    {
255
        return isset($c->v) ? (string) $c->v : null;
256
    }
257
258
    private static function castToString($c)
259
    {
260
        return isset($c->v) ? (string) $c->v : null;
261
    }
262
263
    private function castToFormula($c, $r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType)
264
    {
265
        $cellDataType = 'f';
266
        $value = "={$c->f}";
267
        $calculatedValue = self::$castBaseType($c);
268
269
        // Shared formula?
270
        if (isset($c->f['t']) && strtolower((string) $c->f['t']) == 'shared') {
271
            $instance = (string) $c->f['si'];
272
273
            if (!isset($sharedFormulas[(string) $c->f['si']])) {
274
                $sharedFormulas[$instance] = ['master' => $r, 'formula' => $value];
275
            } else {
276
                $master = Cell::coordinateFromString($sharedFormulas[$instance]['master']);
277
                $current = Cell::coordinateFromString($r);
278
279
                $difference = [0, 0];
280
                $difference[0] = Cell::columnIndexFromString($current[0]) - Cell::columnIndexFromString($master[0]);
281
                $difference[1] = $current[1] - $master[1];
282
283
                $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]);
284
            }
285
        }
286
    }
287
288
    /**
289
     * @param ZipArchive $archive
290
     * @param string $fileName
291
     *
292
     * @return string
293
     */
294
    private function getFromZipArchive(ZipArchive $archive, $fileName = '')
295
    {
296
        // Root-relative paths
297
        if (strpos($fileName, '//') !== false) {
298
            $fileName = substr($fileName, strpos($fileName, '//') + 1);
299
        }
300
        $fileName = File::realpath($fileName);
301
302
        // Sadly, some 3rd party xlsx generators don't use consistent case for filenaming
303
        //    so we need to load case-insensitively from the zip file
304
305
        // Apache POI fixes
306
        $contents = $archive->getFromIndex(
307
            $archive->locateName($fileName, ZipArchive::FL_NOCASE)
308
        );
309
        if ($contents === false) {
310
            $contents = $archive->getFromIndex(
311
                $archive->locateName(substr($fileName, 1), ZipArchive::FL_NOCASE)
312
            );
313
        }
314
315
        return $contents;
316
    }
317
318
    /**
319
     * Loads Spreadsheet from file.
320
     *
321
     * @param string $pFilename
322
     *
323
     * @throws Exception
324
     *
325
     * @return Spreadsheet
326
     */
327
    public function load($pFilename)
328
    {
329
        File::assertFile($pFilename);
330
331
        // Initialisations
332
        $excel = new Spreadsheet();
333
        $excel->removeSheetByIndex(0);
334
        if (!$this->readDataOnly) {
335
            $excel->removeCellStyleXfByIndex(0); // remove the default style
336
            $excel->removeCellXfByIndex(0); // remove the default style
337
        }
338
339
        $zip = new ZipArchive();
340
        $zip->open($pFilename);
341
342
        //    Read the theme first, because we need the colour scheme when reading the styles
343
        $wbRels = simplexml_load_string(
344
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
345
            $this->securityScan($this->getFromZipArchive($zip, 'xl/_rels/workbook.xml.rels')),
346
            'SimpleXMLElement',
347
            Settings::getLibXmlLoaderOptions()
348
        );
349
        foreach ($wbRels->Relationship as $rel) {
350
            switch ($rel['Type']) {
351
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme':
352
                    $themeOrderArray = ['lt1', 'dk1', 'lt2', 'dk2'];
353
                    $themeOrderAdditional = count($themeOrderArray);
354
355
                    $xmlTheme = simplexml_load_string(
356
                        $this->securityScan($this->getFromZipArchive($zip, "xl/{$rel['Target']}")),
357
                        'SimpleXMLElement',
358
                        Settings::getLibXmlLoaderOptions()
359
                    );
360
                    if (is_object($xmlTheme)) {
361
                        $xmlThemeName = $xmlTheme->attributes();
362
                        $xmlTheme = $xmlTheme->children('http://schemas.openxmlformats.org/drawingml/2006/main');
363
                        $themeName = (string) $xmlThemeName['name'];
364
365
                        $colourScheme = $xmlTheme->themeElements->clrScheme->attributes();
366
                        $colourSchemeName = (string) $colourScheme['name'];
367
                        $colourScheme = $xmlTheme->themeElements->clrScheme->children('http://schemas.openxmlformats.org/drawingml/2006/main');
368
369
                        $themeColours = [];
370
                        foreach ($colourScheme as $k => $xmlColour) {
371
                            $themePos = array_search($k, $themeOrderArray);
372
                            if ($themePos === false) {
373
                                $themePos = $themeOrderAdditional++;
374
                            }
375
                            if (isset($xmlColour->sysClr)) {
376
                                $xmlColourData = $xmlColour->sysClr->attributes();
377
                                $themeColours[$themePos] = $xmlColourData['lastClr'];
378
                            } elseif (isset($xmlColour->srgbClr)) {
379
                                $xmlColourData = $xmlColour->srgbClr->attributes();
380
                                $themeColours[$themePos] = $xmlColourData['val'];
381
                            }
382
                        }
383
                        self::$theme = new Xlsx\Theme($themeName, $colourSchemeName, $themeColours);
384
                    }
385
386
                    break;
387
            }
388
        }
389
390
        $rels = simplexml_load_string(
391
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
392
            $this->securityScan($this->getFromZipArchive($zip, '_rels/.rels')),
393
            'SimpleXMLElement',
394
            Settings::getLibXmlLoaderOptions()
395
        );
396
        foreach ($rels->Relationship as $rel) {
397
            switch ($rel['Type']) {
398
                case 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties':
399
                    $xmlCore = simplexml_load_string(
400
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
401
                        'SimpleXMLElement',
402
                        Settings::getLibXmlLoaderOptions()
403
                    );
404
                    if (is_object($xmlCore)) {
405
                        $xmlCore->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
406
                        $xmlCore->registerXPathNamespace('dcterms', 'http://purl.org/dc/terms/');
407
                        $xmlCore->registerXPathNamespace('cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties');
408
                        $docProps = $excel->getProperties();
409
                        $docProps->setCreator((string) self::getArrayItem($xmlCore->xpath('dc:creator')));
410
                        $docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath('cp:lastModifiedBy')));
411
                        $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...heet\Document\datetime>.

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...
412
                        $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...heet\Document\datetime>.

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

This check looks for function calls that miss required arguments.

Loading history...
2139
            }
2140
        } else {
2141
            $excel->setRibbonXMLData(null);
0 ignored issues
show
Bug introduced by
The call to setRibbonXMLData() misses a required argument $xmlData.

This check looks for function calls that miss required arguments.

Loading history...
2142
            $excel->setRibbonBinObjects(null);
0 ignored issues
show
Bug introduced by
The call to setRibbonBinObjects() misses a required argument $BinObjectsData.

This check looks for function calls that miss required arguments.

Loading history...
2143
        }
2144
    }
2145
2146
    private static function getArrayItem($array, $key = 0)
2147
    {
2148
        return isset($array[$key]) ? $array[$key] : null;
2149
    }
2150
2151
    private static function dirAdd($base, $add)
2152
    {
2153
        return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
2154
    }
2155
2156
    private static function toCSSArray($style)
2157
    {
2158
        $style = str_replace(["\r", "\n"], '', $style);
2159
2160
        $temp = explode(';', $style);
2161
        $style = [];
2162
        foreach ($temp as $item) {
2163
            $item = explode(':', $item);
2164
2165
            if (strpos($item[1], 'px') !== false) {
2166
                $item[1] = str_replace('px', '', $item[1]);
2167
            }
2168 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...
2169
                $item[1] = str_replace('pt', '', $item[1]);
2170
                $item[1] = Font::fontSizeToPixels($item[1]);
2171
            }
2172 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...
2173
                $item[1] = str_replace('in', '', $item[1]);
2174
                $item[1] = Font::inchSizeToPixels($item[1]);
2175
            }
2176 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...
2177
                $item[1] = str_replace('cm', '', $item[1]);
2178
                $item[1] = Font::centimeterSizeToPixels($item[1]);
2179
            }
2180
2181
            $style[$item[0]] = $item[1];
2182
        }
2183
2184
        return $style;
2185
    }
2186
2187
    private static function boolean($value)
2188
    {
2189
        if (is_object($value)) {
2190
            $value = (string) $value;
2191
        }
2192
        if (is_numeric($value)) {
2193
            return (bool) $value;
2194
        }
2195
2196
        return $value === 'true' || $value === 'TRUE';
2197
    }
2198
}
2199