Completed
Push — develop ( e1f81f...539a89 )
by Adrien
16:11
created

Excel2007::listWorksheetNames()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 46
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 25
nc 6
nop 1
dl 0
loc 46
rs 8.4751
c 1
b 0
f 0
1
<?php
2
3
namespace PhpSpreadsheet\Reader;
4
5
/**
6
 * Copyright (c) 2006 - 2016 PhpSpreadsheet
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
 *
22
 * @category   PhpSpreadsheet
23
 * @copyright  Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
24
 * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
25
 * @version    ##VERSION##, ##DATE##
26
 */
27
class Excel2007 extends BaseReader implements IReader
28
{
29
    /**
30
     * ReferenceHelper instance
31
     *
32
     * @var \PhpSpreadsheet\ReferenceHelper
33
     */
34
    private $referenceHelper = null;
35
36
    /**
37
     * Excel2007\Theme instance
38
     *
39
     * @var Excel2007\Theme
40
     */
41
    private static $theme = null;
42
43
    /**
44
     * Create a new Excel2007 Reader instance
45
     */
46
    public function __construct()
47
    {
48
        $this->readFilter = new DefaultReadFilter();
49
        $this->referenceHelper = \PhpSpreadsheet\ReferenceHelper::getInstance();
50
    }
51
52
    /**
53
     * Can the current IReader read the file?
54
     *
55
     * @param    string         $pFilename
56
     * @return   boolean
57
     * @throws   Exception
58
     */
59
    public function canRead($pFilename)
60
    {
61
        // Check if file exists
62
        if (!file_exists($pFilename)) {
63
            throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
64
        }
65
66
        $zipClass = \PhpSpreadsheet\Settings::getZipClass();
67
68
        // Check if zip class exists
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
69
//        if (!class_exists($zipClass, false)) {
70
//            throw new Exception($zipClass . " library is not enabled");
71
//        }
72
73
        $xl = false;
74
        // Load file
75
        $zip = new $zipClass;
76
        if ($zip->open($pFilename) === true) {
77
            // check if it is an OOXML archive
78
            $rels = simplexml_load_string(
79
                $this->securityScan(
80
                    $this->getFromZipArchive($zip, "_rels/.rels")
81
                ),
82
                'SimpleXMLElement',
83
                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
84
            );
85
            if ($rels !== false) {
86
                foreach ($rels->Relationship as $rel) {
87
                    switch ($rel["Type"]) {
88
                        case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
89
                            if (basename($rel["Target"]) == 'workbook.xml') {
90
                                $xl = true;
91
                            }
92
                            break;
93
                    }
94
                }
95
            }
96
            $zip->close();
97
        }
98
99
        return $xl;
100
    }
101
102
103
    /**
104
     * Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object
105
     *
106
     * @param    string         $pFilename
107
     * @throws   Exception
108
     */
109
    public function listWorksheetNames($pFilename)
110
    {
111
        // Check if file exists
112
        if (!file_exists($pFilename)) {
113
            throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
114
        }
115
116
        $worksheetNames = array();
117
118
        $zipClass = \PhpSpreadsheet\Settings::getZipClass();
119
120
        $zip = new $zipClass;
121
        $zip->open($pFilename);
122
123
        //    The files we're looking at here are small enough that simpleXML is more efficient than XMLReader
124
        $rels = simplexml_load_string(
125
            $this->securityScan(
126
                $this->getFromZipArchive($zip, "_rels/.rels"),
127
                'SimpleXMLElement',
0 ignored issues
show
Unused Code introduced by
The call to Excel2007::securityScan() has too many arguments starting with 'SimpleXMLElement'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
128
                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
129
            )
130
        ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
131
        foreach ($rels->Relationship as $rel) {
132
            switch ($rel["Type"]) {
133
                case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
134
                    $xmlWorkbook = simplexml_load_string(
135
                        $this->securityScan(
136
                            $this->getFromZipArchive($zip, "{$rel['Target']}"),
137
                            'SimpleXMLElement',
0 ignored issues
show
Unused Code introduced by
The call to Excel2007::securityScan() has too many arguments starting with 'SimpleXMLElement'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
138
                            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
139
                        )
140
                    );  //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
141
142
                    if ($xmlWorkbook->sheets) {
143
                        foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
144
                            // Check if sheet should be skipped
145
                            $worksheetNames[] = (string) $eleSheet["name"];
146
                        }
147
                    }
148
            }
149
        }
150
151
        $zip->close();
152
153
        return $worksheetNames;
154
    }
155
156
157
    /**
158
     * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
159
     *
160
     * @param   string     $pFilename
161
     * @throws  Exception
162
     */
163
    public function listWorksheetInfo($pFilename)
164
    {
165
        // Check if file exists
166
        if (!file_exists($pFilename)) {
167
            throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
168
        }
169
170
        $worksheetInfo = array();
171
172
        $zipClass = \PhpSpreadsheet\Settings::getZipClass();
173
174
        $zip = new $zipClass;
175
        $zip->open($pFilename);
176
177
        $rels = simplexml_load_string(
178
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
179
            $this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")),
180
            'SimpleXMLElement',
181
            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
182
        );
183
        foreach ($rels->Relationship as $rel) {
184
            if ($rel["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") {
185
                $dir = dirname($rel["Target"]);
186
                $relsWorkbook = simplexml_load_string(
187
                    //~ http://schemas.openxmlformats.org/package/2006/relationships"
188
                    $this->securityScan(
189
                        $this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")
190
                    ),
191
                    'SimpleXMLElement',
192
                    \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
193
                );
194
                $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships");
195
196
                $worksheets = array();
197
                foreach ($relsWorkbook->Relationship as $ele) {
198
                    if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") {
199
                        $worksheets[(string) $ele["Id"]] = $ele["Target"];
200
                    }
201
                }
202
203
                $xmlWorkbook = simplexml_load_string(
204
                    //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
205
                    $this->securityScan(
206
                        $this->getFromZipArchive($zip, "{$rel['Target']}")
207
                    ),
208
                    'SimpleXMLElement',
209
                    \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
210
                );
211
                if ($xmlWorkbook->sheets) {
212
                    $dir = dirname($rel["Target"]);
213
                    foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
214
                        $tmpInfo = array(
215
                            'worksheetName' => (string) $eleSheet["name"],
216
                            'lastColumnLetter' => 'A',
217
                            'lastColumnIndex' => 0,
218
                            'totalRows' => 0,
219
                            'totalColumns' => 0,
220
                        );
221
222
                        $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
223
224
                        $xml = new \XMLReader();
225
                        $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...
226
                            $this->securityScanFile(
227
                                'zip://'.\PhpSpreadsheet\Shared\File::realpath($pFilename).'#'."$dir/$fileWorksheet"
228
                            ),
229
                            null,
230
                            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
231
                        );
232
                        $xml->setParserProperty(2, true);
233
234
                        $currCells = 0;
235
                        while ($xml->read()) {
236
                            if ($xml->name == 'row' && $xml->nodeType == \XMLReader::ELEMENT) {
237
                                $row = $xml->getAttribute('r');
238
                                $tmpInfo['totalRows'] = $row;
239
                                $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
240
                                $currCells = 0;
241
                            } elseif ($xml->name == 'c' && $xml->nodeType == \XMLReader::ELEMENT) {
242
                                $currCells++;
243
                            }
244
                        }
245
                        $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'], $currCells);
246
                        $xml->close();
247
248
                        $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1;
249
                        $tmpInfo['lastColumnLetter'] = \PhpSpreadsheet\Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
250
251
                        $worksheetInfo[] = $tmpInfo;
252
                    }
253
                }
254
            }
255
        }
256
257
        $zip->close();
258
259
        return $worksheetInfo;
260
    }
261
262
    private static function castToBoolean($c)
263
    {
264
//        echo 'Initial Cast to Boolean', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
265
        $value = isset($c->v) ? (string) $c->v : null;
266
        if ($value == '0') {
267
            return false;
268
        } elseif ($value == '1') {
269
            return true;
270
        } else {
271
            return (bool)$c->v;
272
        }
273
        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...
274
    }
275
276
    private static function castToError($c)
277
    {
278
//        echo 'Initial Cast to Error', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
279
        return isset($c->v) ? (string) $c->v : null;
280
    }
281
282
    private static function castToString($c)
283
    {
284
//        echo 'Initial Cast to String, PHP_EOL;
285
        return isset($c->v) ? (string) $c->v : null;
286
    }
287
288
    private function castToFormula($c, $r, &$cellDataType, &$value, &$calculatedValue, &$sharedFormulas, $castBaseType)
289
    {
290
//        echo 'Formula', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
291
//        echo '$c->f is ', $c->f, PHP_EOL;
292
        $cellDataType       = 'f';
293
        $value              = "={$c->f}";
294
        $calculatedValue    = self::$castBaseType($c);
295
296
        // Shared formula?
297
        if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') {
298
//            echo 'SHARED FORMULA', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
299
            $instance = (string)$c->f['si'];
300
301
//            echo 'Instance ID = ', $instance, PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
302
//
303
//            echo 'Shared Formula Array:', PHP_EOL;
304
//            print_r($sharedFormulas);
305
            if (!isset($sharedFormulas[(string)$c->f['si']])) {
306
//                echo 'SETTING NEW SHARED FORMULA', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
307
//                echo 'Master is ', $r, PHP_EOL;
308
//                echo 'Formula is ', $value, PHP_EOL;
309
                $sharedFormulas[$instance] = array('master' => $r, 'formula' => $value);
310
//                echo 'New Shared Formula Array:', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
311
//                print_r($sharedFormulas);
312
            } else {
313
//                echo 'GETTING SHARED FORMULA', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
314
//                echo 'Master is ', $sharedFormulas[$instance]['master'], PHP_EOL;
315
//                echo 'Formula is ', $sharedFormulas[$instance]['formula'], PHP_EOL;
316
                $master = \PhpSpreadsheet\Cell::coordinateFromString($sharedFormulas[$instance]['master']);
317
                $current = \PhpSpreadsheet\Cell::coordinateFromString($r);
318
319
                $difference = array(0, 0);
320
                $difference[0] = \PhpSpreadsheet\Cell::columnIndexFromString($current[0]) - \PhpSpreadsheet\Cell::columnIndexFromString($master[0]);
321
                $difference[1] = $current[1] - $master[1];
322
323
                $value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]);
324
//                echo 'Adjusted Formula is ', $value, PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
325
            }
326
        }
327
    }
328
329
330
    private function getFromZipArchive($archive, $fileName = '')
331
    {
332
        // Root-relative paths
333
        if (strpos($fileName, '//') !== false) {
334
            $fileName = substr($fileName, strpos($fileName, '//') + 1);
335
        }
336
        $fileName = \PhpSpreadsheet\Shared\File::realpath($fileName);
337
338
        // Sadly, some 3rd party xlsx generators don't use consistent case for filenaming
339
        //    so we need to load case-insensitively from the zip file
340
341
        // Apache POI fixes
342
        $contents = $archive->getFromIndex(
343
            $archive->locateName($fileName, \ZipArchive::FL_NOCASE)
344
        );
345
        if ($contents === false) {
346
            $contents = $archive->getFromIndex(
347
                $archive->locateName(substr($fileName, 1), \ZipArchive::FL_NOCASE)
348
            );
349
        }
350
351
        return $contents;
352
    }
353
354
355
    /**
356
     * Loads Spreadsheet from file
357
     *
358
     * @param     string         $pFilename
359
     * @return    Spreadsheet
360
     * @throws    Exception
361
     */
362
    public function load($pFilename)
363
    {
364
        // Check if file exists
365
        if (!file_exists($pFilename)) {
366
            throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
367
        }
368
369
        // Initialisations
370
        $excel = new \PhpSpreadsheet\Spreadsheet;
371
        $excel->removeSheetByIndex(0);
372
        if (!$this->readDataOnly) {
373
            $excel->removeCellStyleXfByIndex(0); // remove the default style
374
            $excel->removeCellXfByIndex(0); // remove the default style
375
        }
376
377
        $zipClass = \PhpSpreadsheet\Settings::getZipClass();
378
379
        $zip = new $zipClass;
380
        $zip->open($pFilename);
381
382
        //    Read the theme first, because we need the colour scheme when reading the styles
383
        $wbRels = simplexml_load_string(
384
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
385
            $this->securityScan($this->getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")),
386
            'SimpleXMLElement',
387
            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
388
        );
389
        foreach ($wbRels->Relationship as $rel) {
390
            switch ($rel["Type"]) {
391
                case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme":
392
                    $themeOrderArray = array('lt1', 'dk1', 'lt2', 'dk2');
393
                    $themeOrderAdditional = count($themeOrderArray);
394
395
                    $xmlTheme = simplexml_load_string(
396
                        $this->securityScan($this->getFromZipArchive($zip, "xl/{$rel['Target']}")),
397
                        'SimpleXMLElement',
398
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
399
                    );
400
                    if (is_object($xmlTheme)) {
401
                        $xmlThemeName = $xmlTheme->attributes();
402
                        $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main");
403
                        $themeName = (string)$xmlThemeName['name'];
404
405
                        $colourScheme = $xmlTheme->themeElements->clrScheme->attributes();
406
                        $colourSchemeName = (string)$colourScheme['name'];
407
                        $colourScheme = $xmlTheme->themeElements->clrScheme->children("http://schemas.openxmlformats.org/drawingml/2006/main");
408
409
                        $themeColours = array();
410
                        foreach ($colourScheme as $k => $xmlColour) {
411
                            $themePos = array_search($k, $themeOrderArray);
412
                            if ($themePos === false) {
413
                                $themePos = $themeOrderAdditional++;
414
                            }
415
                            if (isset($xmlColour->sysClr)) {
416
                                $xmlColourData = $xmlColour->sysClr->attributes();
417
                                $themeColours[$themePos] = $xmlColourData['lastClr'];
418
                            } elseif (isset($xmlColour->srgbClr)) {
419
                                $xmlColourData = $xmlColour->srgbClr->attributes();
420
                                $themeColours[$themePos] = $xmlColourData['val'];
421
                            }
422
                        }
423
                        self::$theme = new Excel2007\Theme($themeName, $colourSchemeName, $themeColours);
424
                    }
425
                    break;
426
            }
427
        }
428
429
        $rels = simplexml_load_string(
430
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
431
            $this->securityScan($this->getFromZipArchive($zip, "_rels/.rels")),
432
            'SimpleXMLElement',
433
            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
434
        );
435
        foreach ($rels->Relationship as $rel) {
436
            switch ($rel["Type"]) {
437
                case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties":
438
                    $xmlCore = simplexml_load_string(
439
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
440
                        'SimpleXMLElement',
441
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
442
                    );
443
                    if (is_object($xmlCore)) {
444
                        $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/");
445
                        $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/");
446
                        $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
447
                        $docProps = $excel->getProperties();
448
                        $docProps->setCreator((string) self::getArrayItem($xmlCore->xpath("dc:creator")));
449
                        $docProps->setLastModifiedBy((string) self::getArrayItem($xmlCore->xpath("cp:lastModifiedBy")));
450
                        $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<PhpSpreadsheet\Document\datetime>|null.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
451
                        $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<PhpSpreadsheet\Document\datetime>|null.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
452
                        $docProps->setTitle((string) self::getArrayItem($xmlCore->xpath("dc:title")));
453
                        $docProps->setDescription((string) self::getArrayItem($xmlCore->xpath("dc:description")));
454
                        $docProps->setSubject((string) self::getArrayItem($xmlCore->xpath("dc:subject")));
455
                        $docProps->setKeywords((string) self::getArrayItem($xmlCore->xpath("cp:keywords")));
456
                        $docProps->setCategory((string) self::getArrayItem($xmlCore->xpath("cp:category")));
457
                    }
458
                    break;
459
                case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties":
460
                    $xmlCore = simplexml_load_string(
461
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
462
                        'SimpleXMLElement',
463
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
464
                    );
465
                    if (is_object($xmlCore)) {
466
                        $docProps = $excel->getProperties();
467
                        if (isset($xmlCore->Company)) {
468
                            $docProps->setCompany((string) $xmlCore->Company);
469
                        }
470
                        if (isset($xmlCore->Manager)) {
471
                            $docProps->setManager((string) $xmlCore->Manager);
472
                        }
473
                    }
474
                    break;
475
                case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties":
476
                    $xmlCore = simplexml_load_string(
477
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
478
                        'SimpleXMLElement',
479
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
480
                    );
481
                    if (is_object($xmlCore)) {
482
                        $docProps = $excel->getProperties();
483
                        foreach ($xmlCore as $xmlProperty) {
484
                            $cellDataOfficeAttributes = $xmlProperty->attributes();
485
                            if (isset($cellDataOfficeAttributes['name'])) {
486
                                $propertyName = (string) $cellDataOfficeAttributes['name'];
487
                                $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes');
488
                                $attributeType = $cellDataOfficeChildren->getName();
489
                                $attributeValue = (string) $cellDataOfficeChildren->{$attributeType};
490
                                $attributeValue = \PhpSpreadsheet\Document\Properties::convertProperty($attributeValue, $attributeType);
491
                                $attributeType = \PhpSpreadsheet\Document\Properties::convertPropertyType($attributeType);
492
                                $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType);
493
                            }
494
                        }
495
                    }
496
                    break;
497
                //Ribbon
498
                case "http://schemas.microsoft.com/office/2006/relationships/ui/extensibility":
499
                    $customUI = $rel['Target'];
500
                    if (!is_null($customUI)) {
501
                        $this->readRibbon($excel, $customUI, $zip);
502
                    }
503
                    break;
504
                case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
505
                    $dir = dirname($rel["Target"]);
506
                    $relsWorkbook = simplexml_load_string(
507
                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
508
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")),
509
                        'SimpleXMLElement',
510
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
511
                    );
512
                    $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships");
513
514
                    $sharedStrings = array();
515
                    $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']"));
516
                    $xmlStrings = simplexml_load_string(
517
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
518
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
519
                        'SimpleXMLElement',
520
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
521
                    );
522
                    if (isset($xmlStrings) && isset($xmlStrings->si)) {
523
                        foreach ($xmlStrings->si as $val) {
524
                            if (isset($val->t)) {
525
                                $sharedStrings[] = \PhpSpreadsheet\Shared\StringHelper::controlCharacterOOXML2PHP((string) $val->t);
526
                            } elseif (isset($val->r)) {
527
                                $sharedStrings[] = $this->parseRichText($val);
528
                            }
529
                        }
530
                    }
531
532
                    $worksheets = array();
533
                    $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...
534
                    foreach ($relsWorkbook->Relationship as $ele) {
535
                        switch ($ele['Type']) {
536
                            case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet":
537
                                $worksheets[(string) $ele["Id"]] = $ele["Target"];
538
                                break;
539
                            // a vbaProject ? (: some macros)
540
                            case "http://schemas.microsoft.com/office/2006/relationships/vbaProject":
541
                                $macros = $ele["Target"];
542
                                break;
543
                        }
544
                    }
545
546
                    if (!is_null($macros)) {
547
                        $macrosCode = $this->getFromZipArchive($zip, 'xl/vbaProject.bin');//vbaProject.bin always in 'xl' dir and always named vbaProject.bin
548
                        if ($macrosCode !== false) {
549
                            $excel->setMacrosCode($macrosCode);
550
                            $excel->setHasMacros(true);
551
                            //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir
552
                            $Certificate = $this->getFromZipArchive($zip, 'xl/vbaProjectSignature.bin');
553
                            if ($Certificate !== false) {
554
                                $excel->setMacrosCertificate($Certificate);
555
                            }
556
                        }
557
                    }
558
                    $styles     = array();
559
                    $cellStyles = array();
560
                    $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
561
                    $xmlStyles = simplexml_load_string(
562
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
563
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
564
                        'SimpleXMLElement',
565
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
566
                    );
567
                    $numFmts = null;
568
                    if ($xmlStyles && $xmlStyles->numFmts[0]) {
569
                        $numFmts = $xmlStyles->numFmts[0];
570
                    }
571
                    if (isset($numFmts) && ($numFmts !== null)) {
572
                        $numFmts->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
573
                    }
574
                    if (!$this->readDataOnly && $xmlStyles) {
575
                        foreach ($xmlStyles->cellXfs->xf as $xf) {
576
                            $numFmt = \PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL;
577
578
                            if ($xf["numFmtId"]) {
579
                                if (isset($numFmts)) {
580
                                    $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
581
582
                                    if (isset($tmpNumFmt["formatCode"])) {
583
                                        $numFmt = (string) $tmpNumFmt["formatCode"];
584
                                    }
585
                                }
586
587
                                // We shouldn't override any of the built-in MS Excel values (values below id 164)
588
                                //  But there's a lot of naughty homebrew xlsx writers that do use "reserved" id values that aren't actually used
589
                                //  So we make allowance for them rather than lose formatting masks
590
                                if ((int)$xf["numFmtId"] < 164 &&
591
                                    \PhpSpreadsheet\Style\NumberFormat::builtInFormatCode((int)$xf["numFmtId"]) !== '') {
592
                                    $numFmt = \PhpSpreadsheet\Style\NumberFormat::builtInFormatCode((int)$xf["numFmtId"]);
593
                                }
594
                            }
595
                            $quotePrefix = false;
596
                            if (isset($xf["quotePrefix"])) {
597
                                $quotePrefix = (boolean) $xf["quotePrefix"];
598
                            }
599
600
                            $style = (object) array(
601
                                "numFmt" => $numFmt,
602
                                "font" => $xmlStyles->fonts->font[intval($xf["fontId"])],
603
                                "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])],
604
                                "border" => $xmlStyles->borders->border[intval($xf["borderId"])],
605
                                "alignment" => $xf->alignment,
606
                                "protection" => $xf->protection,
607
                                "quotePrefix" => $quotePrefix,
608
                            );
609
                            $styles[] = $style;
610
611
                            // add style to cellXf collection
612
                            $objStyle = new \PhpSpreadsheet\Style;
613
                            self::readStyle($objStyle, $style);
614
                            $excel->addCellXf($objStyle);
615
                        }
616
617
                        foreach ($xmlStyles->cellStyleXfs->xf as $xf) {
618
                            $numFmt = \PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL;
619
                            if ($numFmts && $xf["numFmtId"]) {
620
                                $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
621
                                if (isset($tmpNumFmt["formatCode"])) {
622
                                    $numFmt = (string) $tmpNumFmt["formatCode"];
623
                                } elseif ((int)$xf["numFmtId"] < 165) {
624
                                    $numFmt = \PhpSpreadsheet\Style\NumberFormat::builtInFormatCode((int)$xf["numFmtId"]);
625
                                }
626
                            }
627
628
                            $cellStyle = (object) array(
629
                                "numFmt" => $numFmt,
630
                                "font" => $xmlStyles->fonts->font[intval($xf["fontId"])],
631
                                "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])],
632
                                "border" => $xmlStyles->borders->border[intval($xf["borderId"])],
633
                                "alignment" => $xf->alignment,
634
                                "protection" => $xf->protection,
635
                                "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...
636
                            );
637
                            $cellStyles[] = $cellStyle;
638
639
                            // add style to cellStyleXf collection
640
                            $objStyle = new \PhpSpreadsheet\Style;
641
                            self::readStyle($objStyle, $cellStyle);
642
                            $excel->addCellStyleXf($objStyle);
643
                        }
644
                    }
645
646
                    $dxfs = array();
647
                    if (!$this->readDataOnly && $xmlStyles) {
648
                        //    Conditional Styles
649
                        if ($xmlStyles->dxfs) {
650
                            foreach ($xmlStyles->dxfs->dxf as $dxf) {
651
                                $style = new \PhpSpreadsheet\Style(false, true);
652
                                self::readStyle($style, $dxf);
653
                                $dxfs[] = $style;
654
                            }
655
                        }
656
                        //    Cell Styles
657
                        if ($xmlStyles->cellStyles) {
658
                            foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) {
659
                                if (intval($cellStyle['builtinId']) == 0) {
660
                                    if (isset($cellStyles[intval($cellStyle['xfId'])])) {
661
                                        // Set default style
662
                                        $style = new \PhpSpreadsheet\Style;
663
                                        self::readStyle($style, $cellStyles[intval($cellStyle['xfId'])]);
664
665
                                        // normal style, currently not using it for anything
666
                                    }
667
                                }
668
                            }
669
                        }
670
                    }
671
672
                    $xmlWorkbook = simplexml_load_string(
673
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
674
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
675
                        'SimpleXMLElement',
676
                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
677
                    );
678
679
                    // Set base date
680
                    if ($xmlWorkbook->workbookPr) {
681
                        \PhpSpreadsheet\Shared\Date::setExcelCalendar(\PhpSpreadsheet\Shared\Date::CALENDAR_WINDOWS_1900);
682
                        if (isset($xmlWorkbook->workbookPr['date1904'])) {
683
                            if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) {
684
                                \PhpSpreadsheet\Shared\Date::setExcelCalendar(\PhpSpreadsheet\Shared\Date::CALENDAR_MAC_1904);
685
                            }
686
                        }
687
                    }
688
689
                    $sheetId = 0; // keep track of new sheet id in final workbook
690
                    $oldSheetId = -1; // keep track of old sheet id in final workbook
691
                    $countSkippedSheets = 0; // keep track of number of skipped sheets
692
                    $mapSheetId = array(); // mapping of sheet ids from old to new
693
694
                    $charts = $chartDetails = array();
695
696
                    if ($xmlWorkbook->sheets) {
697
                        foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
698
                            ++$oldSheetId;
699
700
                            // Check if sheet should be skipped
701
                            if (isset($this->loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->loadSheetsOnly)) {
702
                                ++$countSkippedSheets;
703
                                $mapSheetId[$oldSheetId] = null;
704
                                continue;
705
                            }
706
707
                            // Map old sheet id in original workbook to new sheet id.
708
                            // They will differ if loadSheetsOnly() is being used
709
                            $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets;
710
711
                            // Load sheet
712
                            $docSheet = $excel->createSheet();
713
                            //    Use false for $updateFormulaCellReferences to prevent adjustment of worksheet
714
                            //        references in formula cells... during the load, all formulae should be correct,
715
                            //        and we're simply bringing the worksheet name in line with the formula, not the
716
                            //        reverse
717
                            $docSheet->setTitle((string) $eleSheet["name"], false);
718
                            $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
719
                            $xmlSheet = simplexml_load_string(
720
                                //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
721
                                $this->securityScan($this->getFromZipArchive($zip, "$dir/$fileWorksheet")),
722
                                'SimpleXMLElement',
723
                                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
724
                            );
725
726
                            $sharedFormulas = array();
727
728
                            if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') {
729
                                $docSheet->setSheetState((string) $eleSheet["state"]);
730
                            }
731
732
                            if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) {
733 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...
734
                                    $docSheet->getSheetView()->setZoomScale(intval($xmlSheet->sheetViews->sheetView['zoomScale']));
735
                                }
736 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...
737
                                    $docSheet->getSheetView()->setZoomScaleNormal(intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']));
738
                                }
739
                                if (isset($xmlSheet->sheetViews->sheetView['view'])) {
740
                                    $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']);
741
                                }
742 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...
743
                                    $docSheet->setShowGridLines(self::boolean((string)$xmlSheet->sheetViews->sheetView['showGridLines']));
744
                                }
745 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...
746
                                    $docSheet->setShowRowColHeaders(self::boolean((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders']));
747
                                }
748 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...
749
                                    $docSheet->setRightToLeft(self::boolean((string)$xmlSheet->sheetViews->sheetView['rightToLeft']));
750
                                }
751
                                if (isset($xmlSheet->sheetViews->sheetView->pane)) {
752
                                    if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
753
                                        $docSheet->freezePane((string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell']);
754
                                    } else {
755
                                        $xSplit = 0;
756
                                        $ySplit = 0;
757
758 View Code Duplication
                                        if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) {
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...
759
                                            $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']);
760
                                        }
761
762 View Code Duplication
                                        if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) {
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...
763
                                            $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']);
764
                                        }
765
766
                                        $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit);
767
                                    }
768
                                }
769
770
                                if (isset($xmlSheet->sheetViews->sheetView->selection)) {
771
                                    if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) {
772
                                        $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref'];
773
                                        $sqref = explode(' ', $sqref);
774
                                        $sqref = $sqref[0];
775
                                        $docSheet->setSelectedCells($sqref);
776
                                    }
777
                                }
778
                            }
779
780
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) {
781
                                if (isset($xmlSheet->sheetPr->tabColor['rgb'])) {
782
                                    $docSheet->getTabColor()->setARGB((string)$xmlSheet->sheetPr->tabColor['rgb']);
783
                                }
784
                            }
785
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) {
786
                                $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']);
787
                            }
788
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) {
789 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...
790
                                    !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) {
791
                                    $docSheet->setShowSummaryRight(false);
792
                                } else {
793
                                    $docSheet->setShowSummaryRight(true);
794
                                }
795
796 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...
797
                                    !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) {
798
                                    $docSheet->setShowSummaryBelow(false);
799
                                } else {
800
                                    $docSheet->setShowSummaryBelow(true);
801
                                }
802
                            }
803
804
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) {
805
                                if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) &&
806
                                    !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) {
807
                                    $docSheet->getPageSetup()->setFitToPage(false);
808
                                } else {
809
                                    $docSheet->getPageSetup()->setFitToPage(true);
810
                                }
811
                            }
812
813
                            if (isset($xmlSheet->sheetFormatPr)) {
814
                                if (isset($xmlSheet->sheetFormatPr['customHeight']) &&
815
                                    self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) &&
816
                                    isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) {
817
                                    $docSheet->getDefaultRowDimension()->setRowHeight((float)$xmlSheet->sheetFormatPr['defaultRowHeight']);
818
                                }
819
                                if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) {
820
                                    $docSheet->getDefaultColumnDimension()->setWidth((float)$xmlSheet->sheetFormatPr['defaultColWidth']);
821
                                }
822
                                if (isset($xmlSheet->sheetFormatPr['zeroHeight']) &&
823
                                    ((string)$xmlSheet->sheetFormatPr['zeroHeight'] == '1')) {
824
                                    $docSheet->getDefaultRowDimension()->setZeroHeight(true);
825
                                }
826
                            }
827
828
                            if (isset($xmlSheet->cols) && !$this->readDataOnly) {
829
                                foreach ($xmlSheet->cols->col as $col) {
830
                                    for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) {
831
                                        if ($col["style"] && !$this->readDataOnly) {
832
                                            $docSheet->getColumnDimension(\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"]));
833
                                        }
834
                                        if (self::boolean($col["bestFit"])) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

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

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
835
                                            //$docSheet->getColumnDimension(\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setAutoSize(true);
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
836
                                        }
837
                                        if (self::boolean($col["hidden"])) {
838
                                            // echo \PhpSpreadsheet\Cell::stringFromColumnIndex($i), ': HIDDEN COLUMN',PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
839
                                            $docSheet->getColumnDimension(\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setVisible(false);
840
                                        }
841
                                        if (self::boolean($col["collapsed"])) {
842
                                            $docSheet->getColumnDimension(\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setCollapsed(true);
843
                                        }
844
                                        if ($col["outlineLevel"] > 0) {
845
                                            $docSheet->getColumnDimension(\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"]));
846
                                        }
847
                                        $docSheet->getColumnDimension(\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"]));
848
849
                                        if (intval($col["max"]) == 16384) {
850
                                            break;
851
                                        }
852
                                    }
853
                                }
854
                            }
855
856
                            if (isset($xmlSheet->printOptions) && !$this->readDataOnly) {
857
                                if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) {
858
                                    $docSheet->setShowGridlines(true);
859
                                }
860
                                if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) {
861
                                    $docSheet->setPrintGridlines(true);
862
                                }
863
                                if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) {
864
                                    $docSheet->getPageSetup()->setHorizontalCentered(true);
865
                                }
866
                                if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) {
867
                                    $docSheet->getPageSetup()->setVerticalCentered(true);
868
                                }
869
                            }
870
871
                            if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
872
                                foreach ($xmlSheet->sheetData->row as $row) {
873
                                    if ($row["ht"] && !$this->readDataOnly) {
874
                                        $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"]));
875
                                    }
876
                                    if (self::boolean($row["hidden"]) && !$this->readDataOnly) {
877
                                        $docSheet->getRowDimension(intval($row["r"]))->setVisible(false);
878
                                    }
879
                                    if (self::boolean($row["collapsed"])) {
880
                                        $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true);
881
                                    }
882
                                    if ($row["outlineLevel"] > 0) {
883
                                        $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"]));
884
                                    }
885 View Code Duplication
                                    if ($row["s"] && !$this->readDataOnly) {
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...
886
                                        $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"]));
887
                                    }
888
889
                                    foreach ($row->c as $c) {
890
                                        $r                     = (string) $c["r"];
891
                                        $cellDataType         = (string) $c["t"];
892
                                        $value                = null;
893
                                        $calculatedValue     = null;
894
895
                                        // Read cell?
896
                                        if ($this->getReadFilter() !== null) {
897
                                            $coordinates = \PhpSpreadsheet\Cell::coordinateFromString($r);
898
899
                                            if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) {
900
                                                continue;
901
                                            }
902
                                        }
903
904
    //                                    echo 'Reading cell ', $coordinates[0], $coordinates[1], PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
905
    //                                    print_r($c);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
906
    //                                    echo PHP_EOL;
907
    //                                    echo 'Cell Data Type is ', $cellDataType, ': ';
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
908
    //
909
                                        // Read cell!
910
                                        switch ($cellDataType) {
911
                                            case "s":
912
    //                                            echo 'String', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
913
                                                if ((string)$c->v != '') {
914
                                                    $value = $sharedStrings[intval($c->v)];
915
916
                                                    if ($value instanceof \PhpSpreadsheet\RichText) {
917
                                                        $value = clone $value;
918
                                                    }
919
                                                } else {
920
                                                    $value = '';
921
                                                }
922
                                                break;
923
                                            case "b":
924
    //                                            echo 'Boolean', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
925
                                                if (!isset($c->f)) {
926
                                                    $value = self::castToBoolean($c);
927
                                                } else {
928
                                                    // Formula
929
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean');
930
                                                    if (isset($c->f['t'])) {
931
                                                        $att = array();
0 ignored issues
show
Unused Code introduced by
$att is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
932
                                                        $att = $c->f;
933
                                                        $docSheet->getCell($r)->setFormulaAttributes($att);
934
                                                    }
935
    //                                                echo '$calculatedValue = ', $calculatedValue, PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
936
                                                }
937
                                                break;
938 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...
939
//                                                echo 'Inline String', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
940
                                                if (isset($c->f)) {
941
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
942
                                                } else {
943
                                                    $value = $this->parseRichText($c->is);
944
                                                }
945
                                                break;
946 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...
947
    //                                            echo 'Error', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
948
                                                if (!isset($c->f)) {
949
                                                    $value = self::castToError($c);
950
                                                } else {
951
                                                    // Formula
952
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
953
    //                                                echo '$calculatedValue = ', $calculatedValue, PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
954
                                                }
955
                                                break;
956
                                            default:
957
//                                                echo 'Default', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
958
                                                if (!isset($c->f)) {
959
    //                                                echo 'Not a Formula', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
960
                                                    $value = self::castToString($c);
961
                                                } else {
962
    //                                                echo 'Treat as Formula', PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
963
                                                    // Formula
964
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToString');
965
    //                                                echo '$calculatedValue = ', $calculatedValue, PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
966
                                                }
967
                                                break;
968
                                        }
969
    //                                    echo 'Value is ', $value, PHP_EOL;
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
970
971
                                        // Check for numeric values
972
                                        if (is_numeric($value) && $cellDataType != 's') {
973
                                            if ($value == (int)$value) {
974
                                                $value = (int)$value;
975
                                            } elseif ($value == (float)$value) {
976
                                                $value = (float)$value;
977
                                            } elseif ($value == (double)$value) {
978
                                                $value = (double)$value;
979
                                            }
980
                                        }
981
982
                                        // Rich text?
983
                                        if ($value instanceof \PhpSpreadsheet\RichText && $this->readDataOnly) {
984
                                            $value = $value->getPlainText();
985
                                        }
986
987
                                        $cell = $docSheet->getCell($r);
988
                                        // Assign value
989
                                        if ($cellDataType != '') {
990
                                            $cell->setValueExplicit($value, $cellDataType);
991
                                        } else {
992
                                            $cell->setValue($value);
993
                                        }
994
                                        if ($calculatedValue !== null) {
995
                                            $cell->setCalculatedValue($calculatedValue);
996
                                        }
997
998
                                        // Style information?
999 View Code Duplication
                                        if ($c["s"] && !$this->readDataOnly) {
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...
1000
                                            // no style index means 0, it seems
1001
                                            $cell->setXfIndex(isset($styles[intval($c["s"])]) ?
1002
                                                intval($c["s"]) : 0);
1003
                                        }
1004
                                    }
1005
                                }
1006
                            }
1007
1008
                            $conditionals = array();
1009
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
1010
                                foreach ($xmlSheet->conditionalFormatting as $conditional) {
1011
                                    foreach ($conditional->cfRule as $cfRule) {
1012
                                        if (((string)$cfRule["type"] == \PhpSpreadsheet\Style\Conditional::CONDITION_NONE || (string)$cfRule["type"] == \PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS || (string)$cfRule["type"] == \PhpSpreadsheet\Style\Conditional::CONDITION_CONTAINSTEXT || (string)$cfRule["type"] == \PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION) && isset($dxfs[intval($cfRule["dxfId"])])) {
1013
                                            $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule;
1014
                                        }
1015
                                    }
1016
                                }
1017
1018
                                foreach ($conditionals as $ref => $cfRules) {
1019
                                    ksort($cfRules);
1020
                                    $conditionalStyles = array();
1021
                                    foreach ($cfRules as $cfRule) {
1022
                                        $objConditional = new \PhpSpreadsheet\Style\Conditional();
1023
                                        $objConditional->setConditionType((string)$cfRule["type"]);
1024
                                        $objConditional->setOperatorType((string)$cfRule["operator"]);
1025
1026
                                        if ((string)$cfRule["text"] != '') {
1027
                                            $objConditional->setText((string)$cfRule["text"]);
1028
                                        }
1029
1030
                                        if (count($cfRule->formula) > 1) {
1031
                                            foreach ($cfRule->formula as $formula) {
1032
                                                $objConditional->addCondition((string)$formula);
1033
                                            }
1034
                                        } else {
1035
                                            $objConditional->addCondition((string)$cfRule->formula);
1036
                                        }
1037
                                        $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]);
1038
                                        $conditionalStyles[] = $objConditional;
1039
                                    }
1040
1041
                                    // Extract all cell references in $ref
1042
                                    $cellBlocks = explode(' ', str_replace('$', '', strtoupper($ref)));
1043
                                    foreach ($cellBlocks as $cellBlock) {
1044
                                        $docSheet->getStyle($cellBlock)->setConditionalStyles($conditionalStyles);
1045
                                    }
1046
                                }
1047
                            }
1048
1049
                            $aKeys = ["sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"];
1050
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
1051
                                foreach ($aKeys as $key) {
1052
                                    $method = "set" . ucfirst($key);
1053
                                    $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key]));
1054
                                }
1055
                            }
1056
1057
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
1058
                                $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true);
1059
                                if ($xmlSheet->protectedRanges->protectedRange) {
1060
                                    foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
1061
                                        $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true);
1062
                                    }
1063
                                }
1064
                            }
1065
1066
                            if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
1067
                                $autoFilterRange = (string) $xmlSheet->autoFilter["ref"];
1068
                                if (strpos($autoFilterRange, ':') !== false) {
1069
                                    $autoFilter = $docSheet->getAutoFilter();
1070
                                    $autoFilter->setRange($autoFilterRange);
1071
1072
                                    foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) {
1073
                                        $column = $autoFilter->getColumnByOffset((integer) $filterColumn["colId"]);
1074
                                        //    Check for standard filters
1075
                                        if ($filterColumn->filters) {
1076
                                            $column->setFilterType(\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER);
1077
                                            $filters = $filterColumn->filters;
1078
                                            if ((isset($filters["blank"])) && ($filters["blank"] == 1)) {
1079
                                                //    Operator is undefined, but always treated as EQUAL
1080
                                                $column->createRule()->setRule(null, '')->setRuleType(\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_FILTER);
1081
                                            }
1082
                                            //    Standard filters are always an OR join, so no join rule needs to be set
1083
                                            //    Entries can be either filter elements
1084 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...
1085
                                                //    Operator is undefined, but always treated as EQUAL
1086
                                                $column->createRule()->setRule(null, (string) $filterRule["val"])->setRuleType(\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_FILTER);
1087
                                            }
1088
                                            //    Or Date Group elements
1089
                                            foreach ($filters->dateGroupItem as $dateGroupItem) {
1090
                                                $column->createRule()->setRule(
1091
                                                    //    Operator is undefined, but always treated as EQUAL
1092
                                                    null,
1093
                                                    array(
1094
                                                        'year' => (string) $dateGroupItem["year"],
1095
                                                        'month' => (string) $dateGroupItem["month"],
1096
                                                        'day' => (string) $dateGroupItem["day"],
1097
                                                        'hour' => (string) $dateGroupItem["hour"],
1098
                                                        'minute' => (string) $dateGroupItem["minute"],
1099
                                                        'second' => (string) $dateGroupItem["second"],
1100
                                                    ),
1101
                                                    (string) $dateGroupItem["dateTimeGrouping"]
1102
                                                )
1103
                                                ->setRuleType(\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP);
1104
                                            }
1105
                                        }
1106
                                        //    Check for custom filters
1107
                                        if ($filterColumn->customFilters) {
1108
                                            $column->setFilterType(\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
1109
                                            $customFilters = $filterColumn->customFilters;
1110
                                            //    Custom filters can an AND or an OR join;
1111
                                            //        and there should only ever be one or two entries
1112
                                            if ((isset($customFilters["and"])) && ($customFilters["and"] == 1)) {
1113
                                                $column->setJoin(\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND);
1114
                                            }
1115 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...
1116
                                                $column->createRule()->setRule(
1117
                                                    (string) $filterRule["operator"],
1118
                                                    (string) $filterRule["val"]
1119
                                                )
1120
                                                ->setRuleType(\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
1121
                                            }
1122
                                        }
1123
                                        //    Check for dynamic filters
1124
                                        if ($filterColumn->dynamicFilter) {
1125
                                            $column->setFilterType(\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
1126
                                            //    We should only ever have one dynamic filter
1127
                                            foreach ($filterColumn->dynamicFilter as $filterRule) {
1128
                                                $column->createRule()->setRule(
1129
                                                    //    Operator is undefined, but always treated as EQUAL
1130
                                                    null,
1131
                                                    (string) $filterRule["val"],
1132
                                                    (string) $filterRule["type"]
1133
                                                )
1134
                                                ->setRuleType(\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
1135
                                                if (isset($filterRule["val"])) {
1136
                                                    $column->setAttribute('val', (string) $filterRule["val"]);
1137
                                                }
1138
                                                if (isset($filterRule["maxVal"])) {
1139
                                                    $column->setAttribute('maxVal', (string) $filterRule["maxVal"]);
1140
                                                }
1141
                                            }
1142
                                        }
1143
                                        //    Check for dynamic filters
1144
                                        if ($filterColumn->top10) {
1145
                                            $column->setFilterType(\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER);
1146
                                            //    We should only ever have one top10 filter
1147
                                            foreach ($filterColumn->top10 as $filterRule) {
1148
                                                $column->createRule()->setRule(
1149
                                                    (((isset($filterRule["percent"])) && ($filterRule["percent"] == 1))
1150
                                                        ? \PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT
1151
                                                        : \PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE
1152
                                                    ),
1153
                                                    (string) $filterRule["val"],
1154
                                                    (((isset($filterRule["top"])) && ($filterRule["top"] == 1))
1155
                                                        ? \PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP
1156
                                                        : \PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM
1157
                                                    )
1158
                                                )
1159
                                                ->setRuleType(\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_TOPTENFILTER);
1160
                                            }
1161
                                        }
1162
                                    }
1163
                                }
1164
                            }
1165
1166
                            if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
1167
                                foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) {
1168
                                    $mergeRef = (string) $mergeCell["ref"];
1169
                                    if (strpos($mergeRef, ':') !== false) {
1170
                                        $docSheet->mergeCells((string) $mergeCell["ref"]);
1171
                                    }
1172
                                }
1173
                            }
1174
1175
                            if ($xmlSheet && $xmlSheet->pageMargins && !$this->readDataOnly) {
1176
                                $docPageMargins = $docSheet->getPageMargins();
1177
                                $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"]));
1178
                                $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"]));
1179
                                $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"]));
1180
                                $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"]));
1181
                                $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"]));
1182
                                $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"]));
1183
                            }
1184
1185
                            if ($xmlSheet && $xmlSheet->pageSetup && !$this->readDataOnly) {
1186
                                $docPageSetup = $docSheet->getPageSetup();
1187
1188
                                if (isset($xmlSheet->pageSetup["orientation"])) {
1189
                                    $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]);
1190
                                }
1191
                                if (isset($xmlSheet->pageSetup["paperSize"])) {
1192
                                    $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"]));
1193
                                }
1194
                                if (isset($xmlSheet->pageSetup["scale"])) {
1195
                                    $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), false);
1196
                                }
1197 View Code Duplication
                                if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($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...
1198
                                    $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), false);
1199
                                }
1200 View Code Duplication
                                if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($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...
1201
                                    $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), false);
1202
                                }
1203
                                if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) &&
1204
                                    self::boolean((string) $xmlSheet->pageSetup["useFirstPageNumber"])) {
1205
                                    $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"]));
1206
                                }
1207
                            }
1208
1209
                            if ($xmlSheet && $xmlSheet->headerFooter && !$this->readDataOnly) {
1210
                                $docHeaderFooter = $docSheet->getHeaderFooter();
1211
1212 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...
1213
                                    self::boolean((string)$xmlSheet->headerFooter["differentOddEven"])) {
1214
                                    $docHeaderFooter->setDifferentOddEven(true);
1215
                                } else {
1216
                                    $docHeaderFooter->setDifferentOddEven(false);
1217
                                }
1218 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...
1219
                                    self::boolean((string)$xmlSheet->headerFooter["differentFirst"])) {
1220
                                    $docHeaderFooter->setDifferentFirst(true);
1221
                                } else {
1222
                                    $docHeaderFooter->setDifferentFirst(false);
1223
                                }
1224 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...
1225
                                    !self::boolean((string)$xmlSheet->headerFooter["scaleWithDoc"])) {
1226
                                    $docHeaderFooter->setScaleWithDocument(false);
1227
                                } else {
1228
                                    $docHeaderFooter->setScaleWithDocument(true);
1229
                                }
1230 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...
1231
                                    !self::boolean((string)$xmlSheet->headerFooter["alignWithMargins"])) {
1232
                                    $docHeaderFooter->setAlignWithMargins(false);
1233
                                } else {
1234
                                    $docHeaderFooter->setAlignWithMargins(true);
1235
                                }
1236
1237
                                $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader);
1238
                                $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter);
1239
                                $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader);
1240
                                $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter);
1241
                                $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader);
1242
                                $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter);
1243
                            }
1244
1245
                            if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->readDataOnly) {
1246
                                foreach ($xmlSheet->rowBreaks->brk as $brk) {
1247
                                    if ($brk["man"]) {
1248
                                        $docSheet->setBreak("A$brk[id]", \PhpSpreadsheet\Worksheet::BREAK_ROW);
1249
                                    }
1250
                                }
1251
                            }
1252
                            if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->readDataOnly) {
1253
                                foreach ($xmlSheet->colBreaks->brk as $brk) {
1254
                                    if ($brk["man"]) {
1255
                                        $docSheet->setBreak(\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $brk["id"]) . "1", \PhpSpreadsheet\Worksheet::BREAK_COLUMN);
1256
                                    }
1257
                                }
1258
                            }
1259
1260
                            if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) {
1261
                                foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) {
1262
                                    // Uppercase coordinate
1263
                                    $range = strtoupper($dataValidation["sqref"]);
1264
                                    $rangeSet = explode(' ', $range);
1265
                                    foreach ($rangeSet as $range) {
1266
                                        $stRange = $docSheet->shrinkRangeToFit($range);
1267
1268
                                        // Extract all cell references in $range
1269
                                        foreach (\PhpSpreadsheet\Cell::extractAllCellReferencesInRange($stRange) as $reference) {
1270
                                            // Create validation
1271
                                            $docValidation = $docSheet->getCell($reference)->getDataValidation();
1272
                                            $docValidation->setType((string) $dataValidation["type"]);
1273
                                            $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]);
1274
                                            $docValidation->setOperator((string) $dataValidation["operator"]);
1275
                                            $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0);
1276
                                            $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0);
1277
                                            $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0);
1278
                                            $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0);
1279
                                            $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]);
1280
                                            $docValidation->setError((string) $dataValidation["error"]);
1281
                                            $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]);
1282
                                            $docValidation->setPrompt((string) $dataValidation["prompt"]);
1283
                                            $docValidation->setFormula1((string) $dataValidation->formula1);
1284
                                            $docValidation->setFormula2((string) $dataValidation->formula2);
1285
                                        }
1286
                                    }
1287
                                }
1288
                            }
1289
1290
                            // Add hyperlinks
1291
                            $hyperlinks = array();
1292
                            if (!$this->readDataOnly) {
1293
                                // Locate hyperlink relations
1294
                                if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1295
                                    $relsWorksheet = simplexml_load_string(
1296
                                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
1297
                                        $this->securityScan(
1298
                                            $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")
1299
                                        ),
1300
                                        'SimpleXMLElement',
1301
                                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1302
                                    );
1303
                                    foreach ($relsWorksheet->Relationship as $ele) {
1304
                                        if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") {
1305
                                            $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"];
1306
                                        }
1307
                                    }
1308
                                }
1309
1310
                                // Loop through hyperlinks
1311
                                if ($xmlSheet && $xmlSheet->hyperlinks) {
1312
                                    foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) {
1313
                                        // Link url
1314
                                        $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1315
1316
                                        foreach (\PhpSpreadsheet\Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
1317
                                            $cell = $docSheet->getCell($cellReference);
1318
                                            if (isset($linkRel['id'])) {
1319
                                                $hyperlinkUrl = $hyperlinks[ (string)$linkRel['id'] ];
1320
                                                if (isset($hyperlink['location'])) {
1321
                                                    $hyperlinkUrl .= '#' . (string) $hyperlink['location'];
1322
                                                }
1323
                                                $cell->getHyperlink()->setUrl($hyperlinkUrl);
1324
                                            } elseif (isset($hyperlink['location'])) {
1325
                                                $cell->getHyperlink()->setUrl('sheet://' . (string)$hyperlink['location']);
1326
                                            }
1327
1328
                                            // Tooltip
1329
                                            if (isset($hyperlink['tooltip'])) {
1330
                                                $cell->getHyperlink()->setTooltip((string)$hyperlink['tooltip']);
1331
                                            }
1332
                                        }
1333
                                    }
1334
                                }
1335
                            }
1336
1337
                            // Add comments
1338
                            $comments = array();
1339
                            $vmlComments = array();
1340
                            if (!$this->readDataOnly) {
1341
                                // Locate comment relations
1342
                                if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1343
                                    $relsWorksheet = simplexml_load_string(
1344
                                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
1345
                                        $this->securityScan(
1346
                                            $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")
1347
                                        ),
1348
                                        'SimpleXMLElement',
1349
                                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1350
                                    );
1351
                                    foreach ($relsWorksheet->Relationship as $ele) {
1352
                                        if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") {
1353
                                            $comments[(string)$ele["Id"]] = (string)$ele["Target"];
1354
                                        }
1355
                                        if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
1356
                                            $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"];
1357
                                        }
1358
                                    }
1359
                                }
1360
1361
                                // Loop through comments
1362
                                foreach ($comments as $relName => $relPath) {
1363
                                    // Load comments file
1364
                                    $relPath = \PhpSpreadsheet\Shared\File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath);
1365
                                    $commentsFile = simplexml_load_string(
1366
                                        $this->securityScan($this->getFromZipArchive($zip, $relPath)),
1367
                                        'SimpleXMLElement',
1368
                                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1369
                                    );
1370
1371
                                    // Utility variables
1372
                                    $authors = array();
1373
1374
                                    // Loop through authors
1375
                                    foreach ($commentsFile->authors->author as $author) {
1376
                                        $authors[] = (string)$author;
1377
                                    }
1378
1379
                                    // Loop through contents
1380
                                    foreach ($commentsFile->commentList->comment as $comment) {
1381
                                        if (!empty($comment['authorId'])) {
1382
                                            $docSheet->getComment((string)$comment['ref'])->setAuthor($authors[(string)$comment['authorId']]);
1383
                                        }
1384
                                        $docSheet->getComment((string)$comment['ref'])->setText($this->parseRichText($comment->text));
1385
                                    }
1386
                                }
1387
1388
                                // Loop through VML comments
1389
                                foreach ($vmlComments as $relName => $relPath) {
1390
                                    // Load VML comments file
1391
                                    $relPath = \PhpSpreadsheet\Shared\File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath);
1392
                                    $vmlCommentsFile = simplexml_load_string(
1393
                                        $this->securityScan($this->getFromZipArchive($zip, $relPath)),
1394
                                        'SimpleXMLElement',
1395
                                        \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1396
                                    );
1397
                                    $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1398
1399
                                    $shapes = $vmlCommentsFile->xpath('//v:shape');
1400
                                    foreach ($shapes as $shape) {
1401
                                        $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1402
1403
                                        if (isset($shape['style'])) {
1404
                                            $style        = (string)$shape['style'];
1405
                                            $fillColor    = strtoupper(substr((string)$shape['fillcolor'], 1));
1406
                                            $column       = null;
1407
                                            $row          = null;
1408
1409
                                            $clientData   = $shape->xpath('.//x:ClientData');
1410
                                            if (is_array($clientData) && !empty($clientData)) {
1411
                                                $clientData   = $clientData[0];
1412
1413
                                                if (isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note') {
1414
                                                    $temp = $clientData->xpath('.//x:Row');
1415
                                                    if (is_array($temp)) {
1416
                                                        $row = $temp[0];
1417
                                                    }
1418
1419
                                                    $temp = $clientData->xpath('.//x:Column');
1420
                                                    if (is_array($temp)) {
1421
                                                        $column = $temp[0];
1422
                                                    }
1423
                                                }
1424
                                            }
1425
1426
                                            if (($column !== null) && ($row !== null)) {
1427
                                                // Set comment properties
1428
                                                $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1);
1429
                                                $comment->getFillColor()->setRGB($fillColor);
1430
1431
                                                // Parse style
1432
                                                $styleArray = explode(';', str_replace(' ', '', $style));
1433
                                                foreach ($styleArray as $stylePair) {
1434
                                                    $stylePair = explode(':', $stylePair);
1435
1436
                                                    if ($stylePair[0] == 'margin-left') {
1437
                                                        $comment->setMarginLeft($stylePair[1]);
1438
                                                    }
1439
                                                    if ($stylePair[0] == 'margin-top') {
1440
                                                        $comment->setMarginTop($stylePair[1]);
1441
                                                    }
1442
                                                    if ($stylePair[0] == 'width') {
1443
                                                        $comment->setWidth($stylePair[1]);
1444
                                                    }
1445
                                                    if ($stylePair[0] == 'height') {
1446
                                                        $comment->setHeight($stylePair[1]);
1447
                                                    }
1448
                                                    if ($stylePair[0] == 'visibility') {
1449
                                                        $comment->setVisible($stylePair[1] == 'visible');
1450
                                                    }
1451
                                                }
1452
                                            }
1453
                                        }
1454
                                    }
1455
                                }
1456
1457
                                // Header/footer images
1458
                                if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->readDataOnly) {
1459
                                    if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1460
                                        $relsWorksheet = simplexml_load_string(
1461
                                            //~ http://schemas.openxmlformats.org/package/2006/relationships"
1462
                                            $this->securityScan(
1463
                                                $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")
1464
                                            ),
1465
                                            'SimpleXMLElement',
1466
                                            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1467
                                        );
1468
                                        $vmlRelationship = '';
1469
1470
                                        foreach ($relsWorksheet->Relationship as $ele) {
1471
                                            if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") {
1472
                                                $vmlRelationship = self::dirAdd("$dir/$fileWorksheet", $ele["Target"]);
1473
                                            }
1474
                                        }
1475
1476
                                        if ($vmlRelationship != '') {
1477
                                            // Fetch linked images
1478
                                            $relsVML = simplexml_load_string(
1479
                                                //~ http://schemas.openxmlformats.org/package/2006/relationships"
1480
                                                $this->securityScan(
1481
                                                    $this->getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels')
1482
                                                ),
1483
                                                'SimpleXMLElement',
1484
                                                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1485
                                            );
1486
                                            $drawings = array();
1487 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...
1488
                                                if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") {
1489
                                                    $drawings[(string) $ele["Id"]] = self::dirAdd($vmlRelationship, $ele["Target"]);
1490
                                                }
1491
                                            }
1492
1493
                                            // Fetch VML document
1494
                                            $vmlDrawing = simplexml_load_string(
1495
                                                $this->securityScan($this->getFromZipArchive($zip, $vmlRelationship)),
1496
                                                'SimpleXMLElement',
1497
                                                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1498
                                            );
1499
                                            $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1500
1501
                                            $hfImages = array();
1502
1503
                                            $shapes = $vmlDrawing->xpath('//v:shape');
1504
                                            foreach ($shapes as $idx => $shape) {
1505
                                                $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1506
                                                $imageData = $shape->xpath('//v:imagedata');
1507
                                                $imageData = $imageData[$idx];
1508
1509
                                                $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office');
1510
                                                $style = self::toCSSArray((string)$shape['style']);
1511
1512
                                                $hfImages[(string) $shape['id']] = new \PhpSpreadsheet\Worksheet\HeaderFooterDrawing();
1513
                                                if (isset($imageData['title'])) {
1514
                                                    $hfImages[(string) $shape['id']]->setName((string)$imageData['title']);
1515
                                                }
1516
1517
                                                $hfImages[(string) $shape['id']]->setPath("zip://".\PhpSpreadsheet\Shared_File::realpath($pFilename)."#" . $drawings[(string)$imageData['relid']], false);
1518
                                                $hfImages[(string) $shape['id']]->setResizeProportional(false);
1519
                                                $hfImages[(string) $shape['id']]->setWidth($style['width']);
1520
                                                $hfImages[(string) $shape['id']]->setHeight($style['height']);
1521
                                                if (isset($style['margin-left'])) {
1522
                                                    $hfImages[(string) $shape['id']]->setOffsetX($style['margin-left']);
1523
                                                }
1524
                                                $hfImages[(string) $shape['id']]->setOffsetY($style['margin-top']);
1525
                                                $hfImages[(string) $shape['id']]->setResizeProportional(true);
1526
                                            }
1527
1528
                                            $docSheet->getHeaderFooter()->setImages($hfImages);
1529
                                        }
1530
                                    }
1531
                                }
1532
                            }
1533
1534
                            // TODO: Autoshapes from twoCellAnchors!
1535
                            if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) {
1536
                                $relsWorksheet = simplexml_load_string(
1537
                                    //~ http://schemas.openxmlformats.org/package/2006/relationships"
1538
                                    $this->securityScan(
1539
                                        $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")
1540
                                    ),
1541
                                    'SimpleXMLElement',
1542
                                    \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1543
                                );
1544
                                $drawings = array();
1545 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...
1546
                                    if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") {
1547
                                        $drawings[(string) $ele["Id"]] = self::dirAdd("$dir/$fileWorksheet", $ele["Target"]);
1548
                                    }
1549
                                }
1550
                                if ($xmlSheet->drawing && !$this->readDataOnly) {
1551
                                    foreach ($xmlSheet->drawing as $drawing) {
1552
                                        $fileDrawing = $drawings[(string) self::getArrayItem($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")];
1553
                                        $relsDrawing = simplexml_load_string(
1554
                                            //~ http://schemas.openxmlformats.org/package/2006/relationships"
1555
                                            $this->securityScan(
1556
                                                $this->getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels")
1557
                                            ),
1558
                                            'SimpleXMLElement',
1559
                                            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1560
                                        );
1561
                                        $images = array();
1562
1563
                                        if ($relsDrawing && $relsDrawing->Relationship) {
1564
                                            foreach ($relsDrawing->Relationship as $ele) {
1565
                                                if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") {
1566
                                                    $images[(string) $ele["Id"]] = self::dirAdd($fileDrawing, $ele["Target"]);
1567
                                                } elseif ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart") {
1568
                                                    if ($this->includeCharts) {
1569
                                                        $charts[self::dirAdd($fileDrawing, $ele["Target"])] = array(
1570
                                                            'id'        => (string) $ele["Id"],
1571
                                                            'sheet'    => $docSheet->getTitle()
1572
                                                        );
1573
                                                    }
1574
                                                }
1575
                                            }
1576
                                        }
1577
                                        $xmlDrawing = simplexml_load_string(
1578
                                            $this->securityScan($this->getFromZipArchive($zip, $fileDrawing)),
1579
                                            'SimpleXMLElement',
1580
                                            \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1581
                                        )->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing");
1582
1583
                                        if ($xmlDrawing->oneCellAnchor) {
1584
                                            foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) {
1585
                                                if ($oneCellAnchor->pic->blipFill) {
1586
                                                    $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip;
1587
                                                    $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm;
1588
                                                    $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw;
1589
                                                    $objDrawing = new \PhpSpreadsheet\Worksheet\Drawing;
1590
                                                    $objDrawing->setName((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name"));
1591
                                                    $objDrawing->setDescription((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr"));
1592
                                                    $objDrawing->setPath(
1593
                                                        "zip://".\PhpSpreadsheet\Shared\File::realpath($pFilename)."#" .
1594
                                                        $images[(string) self::getArrayItem(
1595
                                                            $blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"),
1596
                                                            "embed"
1597
                                                        )],
1598
                                                        false
1599
                                                    );
1600
                                                    $objDrawing->setCoordinates(\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1));
1601
                                                    $objDrawing->setOffsetX(\PhpSpreadsheet\Shared\Drawing::EMUToPixels($oneCellAnchor->from->colOff));
1602
                                                    $objDrawing->setOffsetY(\PhpSpreadsheet\Shared\Drawing::EMUToPixels($oneCellAnchor->from->rowOff));
1603
                                                    $objDrawing->setResizeProportional(false);
1604
                                                    $objDrawing->setWidth(\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cx")));
1605
                                                    $objDrawing->setHeight(\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), "cy")));
1606
                                                    if ($xfrm) {
1607
                                                        $objDrawing->setRotation(\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), "rot")));
1608
                                                    }
1609 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...
1610
                                                        $shadow = $objDrawing->getShadow();
1611
                                                        $shadow->setVisible(true);
1612
                                                        $shadow->setBlurRadius(\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "blurRad")));
1613
                                                        $shadow->setDistance(\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "dist")));
1614
                                                        $shadow->setDirection(\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), "dir")));
1615
                                                        $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), "algn"));
1616
                                                        $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), "val"));
1617
                                                        $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), "val") / 1000);
1618
                                                    }
1619
                                                    $objDrawing->setWorksheet($docSheet);
1620
                                                } else {
1621
                                                    //    ? Can charts be positioned with a oneCellAnchor ?
1622
                                                    $coordinates = \PhpSpreadsheet\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...
1623
                                                    $offsetX     = \PhpSpreadsheet\Shared\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...
1624
                                                    $offsetY     = \PhpSpreadsheet\Shared\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...
1625
                                                    $width       = \PhpSpreadsheet\Shared\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...
1626
                                                    $height      = \PhpSpreadsheet\Shared\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...
1627
                                                }
1628
                                            }
1629
                                        }
1630
                                        if ($xmlDrawing->twoCellAnchor) {
1631
                                            foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) {
1632
                                                if ($twoCellAnchor->pic->blipFill) {
1633
                                                    $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip;
1634
                                                    $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm;
1635
                                                    $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw;
1636
                                                    $objDrawing = new \PhpSpreadsheet\Worksheet\Drawing;
1637
                                                    $objDrawing->setName((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name"));
1638
                                                    $objDrawing->setDescription((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr"));
1639
                                                    $objDrawing->setPath(
1640
                                                        "zip://".\PhpSpreadsheet\Shared\File::realpath($pFilename)."#" .
1641
                                                        $images[(string) self::getArrayItem(
1642
                                                            $blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"),
1643
                                                            "embed"
1644
                                                        )],
1645
                                                        false
1646
                                                    );
1647
                                                    $objDrawing->setCoordinates(\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1));
1648
                                                    $objDrawing->setOffsetX(\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->colOff));
1649
                                                    $objDrawing->setOffsetY(\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->rowOff));
1650
                                                    $objDrawing->setResizeProportional(false);
1651
1652
                                                    if ($xfrm) {
1653
                                                        $objDrawing->setWidth(\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), "cx")));
1654
                                                        $objDrawing->setHeight(\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), "cy")));
1655
                                                        $objDrawing->setRotation(\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), "rot")));
1656
                                                    }
1657 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...
1658
                                                        $shadow = $objDrawing->getShadow();
1659
                                                        $shadow->setVisible(true);
1660
                                                        $shadow->setBlurRadius(\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "blurRad")));
1661
                                                        $shadow->setDistance(\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), "dist")));
1662
                                                        $shadow->setDirection(\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), "dir")));
1663
                                                        $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), "algn"));
1664
                                                        $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), "val"));
1665
                                                        $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), "val") / 1000);
1666
                                                    }
1667
                                                    $objDrawing->setWorksheet($docSheet);
1668
                                                } elseif (($this->includeCharts) && ($twoCellAnchor->graphicFrame)) {
1669
                                                    $fromCoordinate = \PhpSpreadsheet\Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1);
1670
                                                    $fromOffsetX    = \PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->colOff);
1671
                                                    $fromOffsetY    = \PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->rowOff);
1672
                                                    $toCoordinate   = \PhpSpreadsheet\Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1);
1673
                                                    $toOffsetX      = \PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->to->colOff);
1674
                                                    $toOffsetY      = \PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->to->rowOff);
1675
                                                    $graphic        = $twoCellAnchor->graphicFrame->children("http://schemas.openxmlformats.org/drawingml/2006/main")->graphic;
1676
                                                    $chartRef       = $graphic->graphicData->children("http://schemas.openxmlformats.org/drawingml/2006/chart")->chart;
1677
                                                    $thisChart      = (string) $chartRef->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
1678
1679
                                                    $chartDetails[$docSheet->getTitle().'!'.$thisChart] = array(
1680
                                                        'fromCoordinate'    => $fromCoordinate,
1681
                                                        'fromOffsetX'       => $fromOffsetX,
1682
                                                        'fromOffsetY'       => $fromOffsetY,
1683
                                                        'toCoordinate'      => $toCoordinate,
1684
                                                        'toOffsetX'         => $toOffsetX,
1685
                                                        'toOffsetY'         => $toOffsetY,
1686
                                                        'worksheetTitle'    => $docSheet->getTitle()
1687
                                                    );
1688
                                                }
1689
                                            }
1690
                                        }
1691
                                    }
1692
                                }
1693
                            }
1694
1695
                            // Loop through definedNames
1696
                            if ($xmlWorkbook->definedNames) {
1697
                                foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1698
                                    // Extract range
1699
                                    $extractedRange = (string)$definedName;
1700
                                    $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange);
1701 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...
1702
                                        $extractedRange = substr($extractedRange, 0, $spos).str_replace('$', '', substr($extractedRange, $spos));
1703
                                    } else {
1704
                                        $extractedRange = str_replace('$', '', $extractedRange);
1705
                                    }
1706
1707
                                    // Valid range?
1708
                                    if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') {
1709
                                        continue;
1710
                                    }
1711
1712
                                    // Some definedNames are only applicable if we are on the same sheet...
1713
                                    if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) {
1714
                                        // Switch on type
1715
                                        switch ((string)$definedName['name']) {
1716
                                            case '_xlnm._FilterDatabase':
1717
                                                if ((string)$definedName['hidden'] !== '1') {
1718
                                                    $extractedRange = explode(',', $extractedRange);
1719
                                                    foreach ($extractedRange as $range) {
1720
                                                        $autoFilterRange = $range;
1721
                                                        if (strpos($autoFilterRange, ':') !== false) {
1722
                                                            $docSheet->getAutoFilter()->setRange($autoFilterRange);
1723
                                                        }
1724
                                                    }
1725
                                                }
1726
                                                break;
1727
                                            case '_xlnm.Print_Titles':
1728
                                                // Split $extractedRange
1729
                                                $extractedRange = explode(',', $extractedRange);
1730
1731
                                                // Set print titles
1732
                                                foreach ($extractedRange as $range) {
1733
                                                    $matches = array();
1734
                                                    $range = str_replace('$', '', $range);
1735
1736
                                                    // check for repeating columns, e g. 'A:A' or 'A:D'
1737
                                                    if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) {
1738
                                                        $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2]));
1739
                                                    } elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) {
1740
                                                        // check for repeating rows, e.g. '1:1' or '1:5'
1741
                                                        $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2]));
1742
                                                    }
1743
                                                }
1744
                                                break;
1745
                                            case '_xlnm.Print_Area':
1746
                                                $rangeSets = explode(',', $extractedRange);        // FIXME: what if sheetname contains comma?
1747
                                                $newRangeSets = array();
1748
                                                foreach ($rangeSets as $rangeSet) {
1749
                                                    $range = explode('!', $rangeSet);    // FIXME: what if sheetname contains exclamation mark?
1750
                                                    $rangeSet = isset($range[1]) ? $range[1] : $range[0];
1751
                                                    if (strpos($rangeSet, ':') === false) {
1752
                                                        $rangeSet = $rangeSet . ':' . $rangeSet;
1753
                                                    }
1754
                                                    $newRangeSets[] = str_replace('$', '', $rangeSet);
1755
                                                }
1756
                                                $docSheet->getPageSetup()->setPrintArea(implode(',', $newRangeSets));
1757
                                                break;
1758
1759
                                            default:
1760
                                                break;
1761
                                        }
1762
                                    }
1763
                                }
1764
                            }
1765
1766
                            // Next sheet id
1767
                            ++$sheetId;
1768
                        }
1769
1770
                        // Loop through definedNames
1771
                        if ($xmlWorkbook->definedNames) {
1772
                            foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1773
                                // Extract range
1774
                                $extractedRange = (string)$definedName;
1775
                                $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange);
1776 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...
1777
                                    $extractedRange = substr($extractedRange, 0, $spos).str_replace('$', '', substr($extractedRange, $spos));
1778
                                } else {
1779
                                    $extractedRange = str_replace('$', '', $extractedRange);
1780
                                }
1781
1782
                                // Valid range?
1783
                                if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') {
1784
                                    continue;
1785
                                }
1786
1787
                                // Some definedNames are only applicable if we are on the same sheet...
1788
                                if ((string)$definedName['localSheetId'] != '') {
1789
                                    // Local defined name
1790
                                    // Switch on type
1791
                                    switch ((string)$definedName['name']) {
1792
                                        case '_xlnm._FilterDatabase':
1793
                                        case '_xlnm.Print_Titles':
1794
                                        case '_xlnm.Print_Area':
1795
                                            break;
1796
                                        default:
1797
                                            if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) {
1798
                                                $range = explode('!', (string)$definedName);
1799
                                                if (count($range) == 2) {
1800
                                                    $range[0] = str_replace("''", "'", $range[0]);
1801
                                                    $range[0] = str_replace("'", "", $range[0]);
1802
                                                    if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) {
1803
                                                        $extractedRange = str_replace('$', '', $range[1]);
1804
                                                        $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $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...
1805
                                                        $excel->addNamedRange(new \PhpSpreadsheet\NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope));
1806
                                                    }
1807
                                                }
1808
                                            }
1809
                                            break;
1810
                                    }
1811
                                } elseif (!isset($definedName['localSheetId'])) {
1812
                                    // "Global" definedNames
1813
                                    $locatedSheet = null;
1814
                                    $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...
1815
                                    if (strpos((string)$definedName, '!') !== false) {
1816
                                        // Extract sheet name
1817
                                        $extractedSheetName = \PhpSpreadsheet\Worksheet::extractSheetTitle((string)$definedName, true);
1818
                                        $extractedSheetName = $extractedSheetName[0];
1819
1820
                                        // Locate sheet
1821
                                        $locatedSheet = $excel->getSheetByName($extractedSheetName);
1822
1823
                                        // Modify range
1824
                                        $range = explode('!', $extractedRange);
1825
                                        $extractedRange = isset($range[1]) ? $range[1] : $range[0];
1826
                                    }
1827
1828
                                    if ($locatedSheet !== null) {
1829
                                        $excel->addNamedRange(new \PhpSpreadsheet\NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false));
1830
                                    }
1831
                                }
1832
                            }
1833
                        }
1834
                    }
1835
1836
                    if ((!$this->readDataOnly) || (!empty($this->loadSheetsOnly))) {
1837
                        // active sheet index
1838
                        $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index
1839
1840
                        // keep active sheet index if sheet is still loaded, else first sheet is set as the active
1841
                        if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
1842
                            $excel->setActiveSheetIndex($mapSheetId[$activeTab]);
1843
                        } else {
1844
                            if ($excel->getSheetCount() == 0) {
1845
                                $excel->createSheet();
1846
                            }
1847
                            $excel->setActiveSheetIndex(0);
1848
                        }
1849
                    }
1850
                    break;
1851
            }
1852
        }
1853
1854
        if (!$this->readDataOnly) {
1855
            $contentTypes = simplexml_load_string(
1856
                $this->securityScan(
1857
                    $this->getFromZipArchive($zip, "[Content_Types].xml")
1858
                ),
1859
                'SimpleXMLElement',
1860
                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1861
            );
1862
            foreach ($contentTypes->Override as $contentType) {
1863
                switch ($contentType["ContentType"]) {
1864
                    case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml":
1865
                        if ($this->includeCharts) {
1866
                            $chartEntryRef = ltrim($contentType['PartName'], '/');
1867
                            $chartElements = simplexml_load_string(
1868
                                $this->securityScan(
1869
                                    $this->getFromZipArchive($zip, $chartEntryRef)
1870
                                ),
1871
                                'SimpleXMLElement',
1872
                                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1873
                            );
1874
                            $objChart = \PhpSpreadsheet\Reader\Excel2007\Chart::readChart($chartElements, basename($chartEntryRef, '.xml'));
1875
1876
//                            echo 'Chart ', $chartEntryRef, '<br />';
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1877
//                            var_dump($charts[$chartEntryRef]);
1878
//
1879
                            if (isset($charts[$chartEntryRef])) {
1880
                                $chartPositionRef = $charts[$chartEntryRef]['sheet'].'!'.$charts[$chartEntryRef]['id'];
1881
//                                echo 'Position Ref ', $chartPositionRef, '<br />';
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1882
                                if (isset($chartDetails[$chartPositionRef])) {
1883
//                                    var_dump($chartDetails[$chartPositionRef]);
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1884
1885
                                    $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart);
1886
                                    $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet']));
1887
                                    $objChart->setTopLeftPosition($chartDetails[$chartPositionRef]['fromCoordinate'], $chartDetails[$chartPositionRef]['fromOffsetX'], $chartDetails[$chartPositionRef]['fromOffsetY']);
1888
                                    $objChart->setBottomRightPosition($chartDetails[$chartPositionRef]['toCoordinate'], $chartDetails[$chartPositionRef]['toOffsetX'], $chartDetails[$chartPositionRef]['toOffsetY']);
1889
                                }
1890
                            }
1891
                        }
1892
                }
1893
            }
1894
        }
1895
1896
        $zip->close();
1897
1898
        return $excel;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $excel; (PhpSpreadsheet\Spreadsheet) is incompatible with the return type declared by the interface PhpSpreadsheet\Reader\IReader::load of type PhpSpreadsheet\Reader\PhpSpreadsheet.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
1899
    }
1900
1901
    private static function readColor($color, $background = false)
1902
    {
1903
        if (isset($color["rgb"])) {
1904
            return (string)$color["rgb"];
1905
        } elseif (isset($color["indexed"])) {
1906
            return \PhpSpreadsheet\Style\Color::indexedColor($color["indexed"]-7, $background)->getARGB();
1907
        } elseif (isset($color["theme"])) {
1908
            if (self::$theme !== null) {
1909
                $returnColour = self::$theme->getColourByIndex((int)$color["theme"]);
1910
                if (isset($color["tint"])) {
1911
                    $tintAdjust = (float) $color["tint"];
1912
                    $returnColour = \PhpSpreadsheet\Style\Color::changeBrightness($returnColour, $tintAdjust);
1913
                }
1914
                return 'FF'.$returnColour;
1915
            }
1916
        }
1917
1918
        if ($background) {
1919
            return 'FFFFFFFF';
1920
        }
1921
        return 'FF000000';
1922
    }
1923
1924
    private static function readStyle($docStyle, $style)
1925
    {
1926
        // format code
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1927
//        if (isset($style->numFmt)) {
1928
//            if (isset($style->numFmt['formatCode'])) {
1929
//                $docStyle->getNumberFormat()->setFormatCode((string) $style->numFmt['formatCode']);
1930
//            } else {
1931
                $docStyle->getNumberFormat()->setFormatCode($style->numFmt);
1932
//            }
1933
//        }
1934
1935
        // font
1936
        if (isset($style->font)) {
1937
            $docStyle->getFont()->setName((string) $style->font->name["val"]);
1938
            $docStyle->getFont()->setSize((string) $style->font->sz["val"]);
1939 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...
1940
                $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || self::boolean((string) $style->font->b["val"]));
1941
            }
1942 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...
1943
                $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || self::boolean((string) $style->font->i["val"]));
1944
            }
1945 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...
1946
                $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || self::boolean((string) $style->font->strike["val"]));
1947
            }
1948
            $docStyle->getFont()->getColor()->setARGB(self::readColor($style->font->color));
1949
1950 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...
1951
                $docStyle->getFont()->setUnderline(\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE);
1952
            } elseif (isset($style->font->u) && isset($style->font->u["val"])) {
1953
                $docStyle->getFont()->setUnderline((string)$style->font->u["val"]);
1954
            }
1955
1956 View Code Duplication
            if (isset($style->font->vertAlign) && isset($style->font->vertAlign["val"])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1957
                $vertAlign = strtolower((string)$style->font->vertAlign["val"]);
1958
                if ($vertAlign == 'superscript') {
1959
                    $docStyle->getFont()->setSuperScript(true);
1960
                }
1961
                if ($vertAlign == 'subscript') {
1962
                    $docStyle->getFont()->setSubScript(true);
1963
                }
1964
            }
1965
        }
1966
1967
        // fill
1968
        if (isset($style->fill)) {
1969
            if ($style->fill->gradientFill) {
1970
                $gradientFill = $style->fill->gradientFill[0];
1971
                if (!empty($gradientFill["type"])) {
1972
                    $docStyle->getFill()->setFillType((string) $gradientFill["type"]);
1973
                }
1974
                $docStyle->getFill()->setRotation(floatval($gradientFill["degree"]));
1975
                $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
1976
                $docStyle->getFill()->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath("sml:stop[@position=0]"))->color));
1977
                $docStyle->getFill()->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath("sml:stop[@position=1]"))->color));
1978
            } elseif ($style->fill->patternFill) {
1979
                $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid';
1980
                $docStyle->getFill()->setFillType($patternType);
1981
                if ($style->fill->patternFill->fgColor) {
1982
                    $docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true));
1983
                } else {
1984
                    $docStyle->getFill()->getStartColor()->setARGB('FF000000');
1985
                }
1986
                if ($style->fill->patternFill->bgColor) {
1987
                    $docStyle->getFill()->getEndColor()->setARGB(self::readColor($style->fill->patternFill->bgColor, true));
1988
                }
1989
            }
1990
        }
1991
1992
        // border
1993
        if (isset($style->border)) {
1994
            $diagonalUp = self::boolean((string) $style->border["diagonalUp"]);
1995
            $diagonalDown = self::boolean((string) $style->border["diagonalDown"]);
1996
            if (!$diagonalUp && !$diagonalDown) {
1997
                $docStyle->getBorders()->setDiagonalDirection(\PhpSpreadsheet\Style\Borders::DIAGONAL_NONE);
1998
            } elseif ($diagonalUp && !$diagonalDown) {
1999
                $docStyle->getBorders()->setDiagonalDirection(\PhpSpreadsheet\Style\Borders::DIAGONAL_UP);
2000
            } elseif (!$diagonalUp && $diagonalDown) {
2001
                $docStyle->getBorders()->setDiagonalDirection(\PhpSpreadsheet\Style\Borders::DIAGONAL_DOWN);
2002
            } else {
2003
                $docStyle->getBorders()->setDiagonalDirection(\PhpSpreadsheet\Style\Borders::DIAGONAL_BOTH);
2004
            }
2005
            self::readBorder($docStyle->getBorders()->getLeft(), $style->border->left);
2006
            self::readBorder($docStyle->getBorders()->getRight(), $style->border->right);
2007
            self::readBorder($docStyle->getBorders()->getTop(), $style->border->top);
2008
            self::readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom);
2009
            self::readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal);
2010
        }
2011
2012
        // alignment
2013
        if (isset($style->alignment)) {
2014
            $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]);
2015
            $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]);
2016
2017
            $textRotation = 0;
2018
            if ((int)$style->alignment["textRotation"] <= 90) {
2019
                $textRotation = (int)$style->alignment["textRotation"];
2020
            } elseif ((int)$style->alignment["textRotation"] > 90) {
2021
                $textRotation = 90 - (int)$style->alignment["textRotation"];
2022
            }
2023
2024
            $docStyle->getAlignment()->setTextRotation(intval($textRotation));
2025
            $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment["wrapText"]));
2026
            $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment["shrinkToFit"]));
2027
            $docStyle->getAlignment()->setIndent(intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0);
2028
            $docStyle->getAlignment()->setReadorder(intval((string)$style->alignment["readingOrder"]) > 0 ? intval((string)$style->alignment["readingOrder"]) : 0);
2029
        }
2030
2031
        // protection
2032
        if (isset($style->protection)) {
2033 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...
2034
                if (self::boolean((string) $style->protection['locked'])) {
2035
                    $docStyle->getProtection()->setLocked(\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED);
2036
                } else {
2037
                    $docStyle->getProtection()->setLocked(\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED);
2038
                }
2039
            }
2040
2041 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...
2042
                if (self::boolean((string) $style->protection['hidden'])) {
2043
                    $docStyle->getProtection()->setHidden(\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED);
2044
                } else {
2045
                    $docStyle->getProtection()->setHidden(\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED);
2046
                }
2047
            }
2048
        }
2049
2050
        // top-level style settings
2051
        if (isset($style->quotePrefix)) {
2052
            $docStyle->setQuotePrefix($style->quotePrefix);
2053
        }
2054
    }
2055
2056
    private static function readBorder($docBorder, $eleBorder)
2057
    {
2058
        if (isset($eleBorder["style"])) {
2059
            $docBorder->setBorderStyle((string) $eleBorder["style"]);
2060
        }
2061
        if (isset($eleBorder->color)) {
2062
            $docBorder->getColor()->setARGB(self::readColor($eleBorder->color));
2063
        }
2064
    }
2065
2066
    private function parseRichText($is = null)
2067
    {
2068
        $value = new \PhpSpreadsheet\RichText();
2069
2070
        if (isset($is->t)) {
2071
            $value->createText(\PhpSpreadsheet\Shared\StringHelper::controlCharacterOOXML2PHP((string) $is->t));
2072
        } else {
2073
            if (is_object($is->r)) {
2074
                foreach ($is->r as $run) {
2075
                    if (!isset($run->rPr)) {
2076
                        $objText = $value->createText(\PhpSpreadsheet\Shared\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...
2077
                    } else {
2078
                        $objText = $value->createTextRun(\PhpSpreadsheet\Shared\StringHelper::controlCharacterOOXML2PHP((string) $run->t));
2079
2080 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...
2081
                            $objText->getFont()->setName((string) $run->rPr->rFont["val"]);
2082
                        }
2083
                        if (isset($run->rPr->sz["val"])) {
2084
                            $objText->getFont()->setSize((string) $run->rPr->sz["val"]);
2085
                        }
2086
                        if (isset($run->rPr->color)) {
2087
                            $objText->getFont()->setColor(new \PhpSpreadsheet\Style\Color(self::readColor($run->rPr->color)));
2088
                        }
2089 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...
2090
                            (isset($run->rPr->b) && !isset($run->rPr->b["val"]))) {
2091
                            $objText->getFont()->setBold(true);
2092
                        }
2093 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...
2094
                            (isset($run->rPr->i) && !isset($run->rPr->i["val"]))) {
2095
                            $objText->getFont()->setItalic(true);
2096
                        }
2097 View Code Duplication
                        if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2098
                            $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]);
2099
                            if ($vertAlign == 'superscript') {
2100
                                $objText->getFont()->setSuperScript(true);
2101
                            }
2102
                            if ($vertAlign == 'subscript') {
2103
                                $objText->getFont()->setSubScript(true);
2104
                            }
2105
                        }
2106 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...
2107
                            $objText->getFont()->setUnderline(\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE);
2108
                        } elseif (isset($run->rPr->u) && isset($run->rPr->u["val"])) {
2109
                            $objText->getFont()->setUnderline((string)$run->rPr->u["val"]);
2110
                        }
2111 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...
2112
                            (isset($run->rPr->strike) && !isset($run->rPr->strike["val"]))) {
2113
                            $objText->getFont()->setStrikethrough(true);
2114
                        }
2115
                    }
2116
                }
2117
            }
2118
        }
2119
2120
        return $value;
2121
    }
2122
2123
    private function readRibbon($excel, $customUITarget, $zip)
2124
    {
2125
        $baseDir = dirname($customUITarget);
2126
        $nameCustomUI = basename($customUITarget);
2127
        // get the xml file (ribbon)
2128
        $localRibbon = $this->getFromZipArchive($zip, $customUITarget);
2129
        $customUIImagesNames = array();
2130
        $customUIImagesBinaries = array();
2131
        // something like customUI/_rels/customUI.xml.rels
2132
        $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels';
2133
        $dataRels = $this->getFromZipArchive($zip, $pathRels);
2134
        if ($dataRels) {
2135
            // exists and not empty if the ribbon have some pictures (other than internal MSO)
2136
            $UIRels = simplexml_load_string(
2137
                $this->securityScan($dataRels),
2138
                'SimpleXMLElement',
2139
                \PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
2140
            );
2141
            if ($UIRels) {
2142
                // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image
2143
                foreach ($UIRels->Relationship as $ele) {
2144
                    if ($ele["Type"] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
2145
                        // an image ?
2146
                        $customUIImagesNames[(string) $ele['Id']] = (string)$ele['Target'];
2147
                        $customUIImagesBinaries[(string)$ele['Target']] = $this->getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']);
2148
                    }
2149
                }
2150
            }
2151
        }
2152
        if ($localRibbon) {
2153
            $excel->setRibbonXMLData($customUITarget, $localRibbon);
2154
            if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) {
2155
                $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries);
2156
            } else {
2157
                $excel->setRibbonBinObjects(null);
2158
            }
2159
        } else {
2160
            $excel->setRibbonXMLData(null);
2161
            $excel->setRibbonBinObjects(null);
2162
        }
2163
    }
2164
2165
    private static function getArrayItem($array, $key = 0)
2166
    {
2167
        return (isset($array[$key]) ? $array[$key] : null);
2168
    }
2169
2170
    private static function dirAdd($base, $add)
2171
    {
2172
        return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
2173
    }
2174
2175
    private static function toCSSArray($style)
2176
    {
2177
        $style = str_replace(array("\r","\n"), "", $style);
2178
2179
        $temp = explode(';', $style);
2180
        $style = array();
2181
        foreach ($temp as $item) {
2182
            $item = explode(':', $item);
2183
2184
            if (strpos($item[1], 'px') !== false) {
2185
                $item[1] = str_replace('px', '', $item[1]);
2186
            }
2187 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...
2188
                $item[1] = str_replace('pt', '', $item[1]);
2189
                $item[1] = \PhpSpreadsheet\Shared\Font::fontSizeToPixels($item[1]);
2190
            }
2191 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...
2192
                $item[1] = str_replace('in', '', $item[1]);
2193
                $item[1] = \PhpSpreadsheet\Shared\Font::inchSizeToPixels($item[1]);
2194
            }
2195 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...
2196
                $item[1] = str_replace('cm', '', $item[1]);
2197
                $item[1] = \PhpSpreadsheet\Shared\Font::centimeterSizeToPixels($item[1]);
2198
            }
2199
2200
            $style[$item[0]] = $item[1];
2201
        }
2202
2203
        return $style;
2204
    }
2205
2206
    private static function boolean($value = null)
2207
    {
2208
        if (is_object($value)) {
2209
            $value = (string) $value;
2210
        }
2211
        if (is_numeric($value)) {
2212
            return (bool) $value;
2213
        }
2214
        return ($value === 'true' || $value === 'TRUE');
2215
    }
2216
}
2217