Completed
Push — develop ( 2b41bd...39b55d )
by Adrien
22:48
created

Xlsx::getFromZipArchive()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 23
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.243

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 4
nop 2
dl 0
loc 23
ccs 7
cts 10
cp 0.7
crap 3.243
rs 9.0856
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\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 Xlsx extends BaseReader implements IReader
28
{
29
    /**
30
     * ReferenceHelper instance
31
     *
32
     * @var \PhpOffice\PhpSpreadsheet\ReferenceHelper
33
     */
34
    private $referenceHelper = null;
35
36
    /**
37
     * Xlsx\Theme instance
38
     *
39
     * @var Xlsx\Theme
40
     */
41
    private static $theme = null;
42
43
    /**
44
     * Create a new Xlsx Reader instance
45
     */
46 9
    public function __construct()
47
    {
48 9
        $this->readFilter = new DefaultReadFilter();
49 9
        $this->referenceHelper = \PhpOffice\PhpSpreadsheet\ReferenceHelper::getInstance();
50 9
    }
51
52
    /**
53
     * Can the current IReader read the file?
54
     *
55
     * @param    string         $pFilename
56
     * @throws   Exception
57
     * @return   bool
58
     */
59 4
    public function canRead($pFilename)
60
    {
61
        // Check if file exists
62 4
        if (!file_exists($pFilename)) {
63
            throw new Exception('Could not open ' . $pFilename . ' for reading! File does not exist.');
64
        }
65
66 4
        $zipClass = \PhpOffice\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 4
        $xl = false;
74
        // Load file
75 4
        $zip = new $zipClass();
76 4
        if ($zip->open($pFilename) === true) {
77
            // check if it is an OOXML archive
78 4
            $rels = simplexml_load_string(
79 4
                $this->securityScan(
80 4
                    $this->getFromZipArchive($zip, '_rels/.rels')
81
                ),
82 4
                'SimpleXMLElement',
83 4
                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
84
            );
85 4
            if ($rels !== false) {
86 4
                foreach ($rels->Relationship as $rel) {
87 4
                    switch ($rel['Type']) {
88 4
                        case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
89 4
                            if (basename($rel['Target']) == 'workbook.xml') {
90 4
                                $xl = true;
91
                            }
92 4
                            break;
93
                    }
94
                }
95
            }
96 4
            $zip->close();
97
        }
98
99 4
        return $xl;
100
    }
101
102
    /**
103
     * Reads names of the worksheets from a file, without parsing the whole file to a Spreadsheet object
104
     *
105
     * @param    string         $pFilename
106
     * @throws   Exception
107
     */
108 1
    public function listWorksheetNames($pFilename)
109
    {
110
        // Check if file exists
111 1
        if (!file_exists($pFilename)) {
112
            throw new Exception('Could not open ' . $pFilename . ' for reading! File does not exist.');
113
        }
114
115 1
        $worksheetNames = [];
116
117 1
        $zipClass = \PhpOffice\PhpSpreadsheet\Settings::getZipClass();
118
119 1
        $zip = new $zipClass();
120 1
        $zip->open($pFilename);
121
122
        //    The files we're looking at here are small enough that simpleXML is more efficient than XMLReader
123 1
        $rels = simplexml_load_string(
124 1
            $this->securityScan(
125 1
                $this->getFromZipArchive($zip, '_rels/.rels'),
126 1
                'SimpleXMLElement',
0 ignored issues
show
Unused Code introduced by
The call to Xlsx::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...
127 1
                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
128
            )
129
        ); //~ http://schemas.openxmlformats.org/package/2006/relationships");
130 1
        foreach ($rels->Relationship as $rel) {
131 1
            switch ($rel['Type']) {
132 1
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
133 1
                    $xmlWorkbook = simplexml_load_string(
134 1
                        $this->securityScan(
135 1
                            $this->getFromZipArchive($zip, "{$rel['Target']}"),
136 1
                            'SimpleXMLElement',
0 ignored issues
show
Unused Code introduced by
The call to Xlsx::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...
137 1
                            \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
138
                        )
139
                    ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
140
141 1
                    if ($xmlWorkbook->sheets) {
142 1
                        foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
143
                            // Check if sheet should be skipped
144 1
                            $worksheetNames[] = (string) $eleSheet['name'];
145
                        }
146
                    }
147
            }
148
        }
149
150 1
        $zip->close();
151
152 1
        return $worksheetNames;
153
    }
154
155
    /**
156
     * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
157
     *
158
     * @param   string     $pFilename
159
     * @throws  Exception
160
     */
161 1
    public function listWorksheetInfo($pFilename)
162
    {
163
        // Check if file exists
164 1
        if (!file_exists($pFilename)) {
165
            throw new Exception('Could not open ' . $pFilename . ' for reading! File does not exist.');
166
        }
167
168 1
        $worksheetInfo = [];
169
170 1
        $zipClass = \PhpOffice\PhpSpreadsheet\Settings::getZipClass();
171
172 1
        $zip = new $zipClass();
173 1
        $zip->open($pFilename);
174
175 1
        $rels = simplexml_load_string(
176
            //~ http://schemas.openxmlformats.org/package/2006/relationships"
177 1
            $this->securityScan($this->getFromZipArchive($zip, '_rels/.rels')),
178 1
            'SimpleXMLElement',
179 1
            \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
180
        );
181 1
        foreach ($rels->Relationship as $rel) {
182 1
            if ($rel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument') {
183 1
                $dir = dirname($rel['Target']);
184 1
                $relsWorkbook = simplexml_load_string(
185
                    //~ http://schemas.openxmlformats.org/package/2006/relationships"
186 1
                    $this->securityScan(
187 1
                        $this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel['Target']) . '.rels')
188
                    ),
189 1
                    'SimpleXMLElement',
190 1
                    \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
191
                );
192 1
                $relsWorkbook->registerXPathNamespace('rel', 'http://schemas.openxmlformats.org/package/2006/relationships');
193
194 1
                $worksheets = [];
195 1
                foreach ($relsWorkbook->Relationship as $ele) {
196 1
                    if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet') {
197 1
                        $worksheets[(string) $ele['Id']] = $ele['Target'];
198
                    }
199
                }
200
201 1
                $xmlWorkbook = simplexml_load_string(
202
                    //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
203 1
                    $this->securityScan(
204 1
                        $this->getFromZipArchive($zip, "{$rel['Target']}")
205
                    ),
206 1
                    'SimpleXMLElement',
207 1
                    \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
208
                );
209 1
                if ($xmlWorkbook->sheets) {
210 1
                    $dir = dirname($rel['Target']);
211 1
                    foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
212
                        $tmpInfo = [
213 1
                            'worksheetName' => (string) $eleSheet['name'],
214 1
                            'lastColumnLetter' => 'A',
215 1
                            'lastColumnIndex' => 0,
216 1
                            'totalRows' => 0,
217 1
                            'totalColumns' => 0,
218
                        ];
219
220 1
                        $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id')];
221
222 1
                        $xml = new \XMLReader();
223 1
                        $res = $xml->xml(
0 ignored issues
show
Unused Code introduced by
$res is not used, you could remove the assignment.

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

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

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

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

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

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
429 8
                        $docProps->setModified(strtotime(self::getArrayItem($xmlCore->xpath('dcterms:modified')))); //! respect xsi:type
0 ignored issues
show
Documentation introduced by
strtotime(self::getArray...h('dcterms:modified'))) is of type integer, but the function expects a object<PhpOffice\PhpSpre...Document\datetime>|null.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
430 8
                        $docProps->setTitle((string) self::getArrayItem($xmlCore->xpath('dc:title')));
431 8
                        $docProps->setDescription((string) self::getArrayItem($xmlCore->xpath('dc:description')));
432 8
                        $docProps->setSubject((string) self::getArrayItem($xmlCore->xpath('dc:subject')));
433 8
                        $docProps->setKeywords((string) self::getArrayItem($xmlCore->xpath('cp:keywords')));
434 8
                        $docProps->setCategory((string) self::getArrayItem($xmlCore->xpath('cp:category')));
435
                    }
436 8
                    break;
437 8
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties':
438 8
                    $xmlCore = simplexml_load_string(
439 8
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
440 8
                        'SimpleXMLElement',
441 8
                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
442
                    );
443 8
                    if (is_object($xmlCore)) {
444 8
                        $docProps = $excel->getProperties();
445 8
                        if (isset($xmlCore->Company)) {
446 7
                            $docProps->setCompany((string) $xmlCore->Company);
447
                        }
448 8
                        if (isset($xmlCore->Manager)) {
449 5
                            $docProps->setManager((string) $xmlCore->Manager);
450
                        }
451
                    }
452 8
                    break;
453 8
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties':
454 1
                    $xmlCore = simplexml_load_string(
455 1
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
456 1
                        'SimpleXMLElement',
457 1
                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
458
                    );
459 1
                    if (is_object($xmlCore)) {
460 1
                        $docProps = $excel->getProperties();
461 1
                        foreach ($xmlCore as $xmlProperty) {
462 1
                            $cellDataOfficeAttributes = $xmlProperty->attributes();
463 1
                            if (isset($cellDataOfficeAttributes['name'])) {
464 1
                                $propertyName = (string) $cellDataOfficeAttributes['name'];
465 1
                                $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes');
466 1
                                $attributeType = $cellDataOfficeChildren->getName();
467 1
                                $attributeValue = (string) $cellDataOfficeChildren->{$attributeType};
468 1
                                $attributeValue = \PhpOffice\PhpSpreadsheet\Document\Properties::convertProperty($attributeValue, $attributeType);
469 1
                                $attributeType = \PhpOffice\PhpSpreadsheet\Document\Properties::convertPropertyType($attributeType);
470 1
                                $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType);
471
                            }
472
                        }
473
                    }
474 1
                    break;
475
                //Ribbon
476 8
                case 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility':
477
                    $customUI = $rel['Target'];
478
                    if (!is_null($customUI)) {
479
                        $this->readRibbon($excel, $customUI, $zip);
480
                    }
481
                    break;
482 8
                case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
483 8
                    $dir = dirname($rel['Target']);
484 8
                    $relsWorkbook = simplexml_load_string(
485
                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
486 8
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/_rels/" . basename($rel['Target']) . '.rels')),
487 8
                        'SimpleXMLElement',
488 8
                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
489
                    );
490 8
                    $relsWorkbook->registerXPathNamespace('rel', 'http://schemas.openxmlformats.org/package/2006/relationships');
491
492 8
                    $sharedStrings = [];
493 8
                    $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']"));
494 8
                    $xmlStrings = simplexml_load_string(
495
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
496 8
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
497 8
                        'SimpleXMLElement',
498 8
                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
499
                    );
500 8
                    if (isset($xmlStrings) && isset($xmlStrings->si)) {
501 8
                        foreach ($xmlStrings->si as $val) {
502 8
                            if (isset($val->t)) {
503 8
                                $sharedStrings[] = \PhpOffice\PhpSpreadsheet\Shared\StringHelper::controlCharacterOOXML2PHP((string) $val->t);
504
                            } elseif (isset($val->r)) {
505 8
                                $sharedStrings[] = $this->parseRichText($val);
506
                            }
507
                        }
508
                    }
509
510 8
                    $worksheets = [];
511 8
                    $macros = $customUI = null;
0 ignored issues
show
Unused Code introduced by
$customUI is not used, you could remove the assignment.

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

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

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

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

Loading history...
512 8
                    foreach ($relsWorkbook->Relationship as $ele) {
513 8
                        switch ($ele['Type']) {
514 8
                            case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet':
515 8
                                $worksheets[(string) $ele['Id']] = $ele['Target'];
516 8
                                break;
517
                            // a vbaProject ? (: some macros)
518 8
                            case 'http://schemas.microsoft.com/office/2006/relationships/vbaProject':
519
                                $macros = $ele['Target'];
520 8
                                break;
521
                        }
522
                    }
523
524 8
                    if (!is_null($macros)) {
525
                        $macrosCode = $this->getFromZipArchive($zip, 'xl/vbaProject.bin'); //vbaProject.bin always in 'xl' dir and always named vbaProject.bin
526
                        if ($macrosCode !== false) {
527
                            $excel->setMacrosCode($macrosCode);
528
                            $excel->setHasMacros(true);
529
                            //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir
530
                            $Certificate = $this->getFromZipArchive($zip, 'xl/vbaProjectSignature.bin');
531
                            if ($Certificate !== false) {
532
                                $excel->setMacrosCertificate($Certificate);
533
                            }
534
                        }
535
                    }
536 8
                    $styles = [];
537 8
                    $cellStyles = [];
538 8
                    $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
539 8
                    $xmlStyles = simplexml_load_string(
540
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
541 8
                        $this->securityScan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
542 8
                        'SimpleXMLElement',
543 8
                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
544
                    );
545 8
                    $numFmts = null;
546 8
                    if ($xmlStyles && $xmlStyles->numFmts[0]) {
547 5
                        $numFmts = $xmlStyles->numFmts[0];
548
                    }
549 8
                    if (isset($numFmts) && ($numFmts !== null)) {
550 5
                        $numFmts->registerXPathNamespace('sml', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
551
                    }
552 8
                    if (!$this->readDataOnly && $xmlStyles) {
553 8
                        foreach ($xmlStyles->cellXfs->xf as $xf) {
554 8
                            $numFmt = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL;
555
556 8
                            if ($xf['numFmtId']) {
557 8
                                if (isset($numFmts)) {
558 5
                                    $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
559
560 5
                                    if (isset($tmpNumFmt['formatCode'])) {
561 2
                                        $numFmt = (string) $tmpNumFmt['formatCode'];
562
                                    }
563
                                }
564
565
                                // We shouldn't override any of the built-in MS Excel values (values below id 164)
566
                                //  But there's a lot of naughty homebrew xlsx writers that do use "reserved" id values that aren't actually used
567
                                //  So we make allowance for them rather than lose formatting masks
568 8
                                if ((int) $xf['numFmtId'] < 164 &&
569 8
                                    \PhpOffice\PhpSpreadsheet\Style\NumberFormat::builtInFormatCode((int) $xf['numFmtId']) !== '') {
570 8
                                    $numFmt = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::builtInFormatCode((int) $xf['numFmtId']);
571
                                }
572
                            }
573 8
                            $quotePrefix = false;
574 8
                            if (isset($xf['quotePrefix'])) {
575
                                $quotePrefix = (boolean) $xf['quotePrefix'];
576
                            }
577
578
                            $style = (object) [
579 8
                                'numFmt' => $numFmt,
580 8
                                'font' => $xmlStyles->fonts->font[intval($xf['fontId'])],
581 8
                                'fill' => $xmlStyles->fills->fill[intval($xf['fillId'])],
582 8
                                'border' => $xmlStyles->borders->border[intval($xf['borderId'])],
583 8
                                'alignment' => $xf->alignment,
584 8
                                'protection' => $xf->protection,
585 8
                                'quotePrefix' => $quotePrefix,
586
                            ];
587 8
                            $styles[] = $style;
588
589
                            // add style to cellXf collection
590 8
                            $objStyle = new \PhpOffice\PhpSpreadsheet\Style();
591 8
                            self::readStyle($objStyle, $style);
592 8
                            $excel->addCellXf($objStyle);
593
                        }
594
595 8
                        foreach ($xmlStyles->cellStyleXfs->xf as $xf) {
596 8
                            $numFmt = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_GENERAL;
597 8
                            if ($numFmts && $xf['numFmtId']) {
598 5
                                $tmpNumFmt = self::getArrayItem($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]"));
599 5
                                if (isset($tmpNumFmt['formatCode'])) {
600
                                    $numFmt = (string) $tmpNumFmt['formatCode'];
601 5
                                } elseif ((int) $xf['numFmtId'] < 165) {
602 5
                                    $numFmt = \PhpOffice\PhpSpreadsheet\Style\NumberFormat::builtInFormatCode((int) $xf['numFmtId']);
603
                                }
604
                            }
605
606
                            $cellStyle = (object) [
607 8
                                'numFmt' => $numFmt,
608 8
                                'font' => $xmlStyles->fonts->font[intval($xf['fontId'])],
609 8
                                'fill' => $xmlStyles->fills->fill[intval($xf['fillId'])],
610 8
                                'border' => $xmlStyles->borders->border[intval($xf['borderId'])],
611 8
                                'alignment' => $xf->alignment,
612 8
                                'protection' => $xf->protection,
613 8
                                'quotePrefix' => $quotePrefix,
0 ignored issues
show
Bug introduced by
The variable $quotePrefix does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
614
                            ];
615 8
                            $cellStyles[] = $cellStyle;
616
617
                            // add style to cellStyleXf collection
618 8
                            $objStyle = new \PhpOffice\PhpSpreadsheet\Style();
619 8
                            self::readStyle($objStyle, $cellStyle);
620 8
                            $excel->addCellStyleXf($objStyle);
621
                        }
622
                    }
623
624 8
                    $dxfs = [];
625 8
                    if (!$this->readDataOnly && $xmlStyles) {
626
                        //    Conditional Styles
627 8
                        if ($xmlStyles->dxfs) {
628 8
                            foreach ($xmlStyles->dxfs->dxf as $dxf) {
629
                                $style = new \PhpOffice\PhpSpreadsheet\Style(false, true);
630
                                self::readStyle($style, $dxf);
631
                                $dxfs[] = $style;
632
                            }
633
                        }
634
                        //    Cell Styles
635 8
                        if ($xmlStyles->cellStyles) {
636 8
                            foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) {
637 8
                                if (intval($cellStyle['builtinId']) == 0) {
638 8
                                    if (isset($cellStyles[intval($cellStyle['xfId'])])) {
639
                                        // Set default style
640 8
                                        $style = new \PhpOffice\PhpSpreadsheet\Style();
641 8
                                        self::readStyle($style, $cellStyles[intval($cellStyle['xfId'])]);
642
643
                                        // normal style, currently not using it for anything
644
                                    }
645
                                }
646
                            }
647
                        }
648
                    }
649
650 8
                    $xmlWorkbook = simplexml_load_string(
651
                        //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
652 8
                        $this->securityScan($this->getFromZipArchive($zip, "{$rel['Target']}")),
653 8
                        'SimpleXMLElement',
654 8
                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
655
                    );
656
657
                    // Set base date
658 8
                    if ($xmlWorkbook->workbookPr) {
659 8
                        \PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar(\PhpOffice\PhpSpreadsheet\Shared\Date::CALENDAR_WINDOWS_1900);
660 8
                        if (isset($xmlWorkbook->workbookPr['date1904'])) {
661
                            if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) {
662
                                \PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar(\PhpOffice\PhpSpreadsheet\Shared\Date::CALENDAR_MAC_1904);
663
                            }
664
                        }
665
                    }
666
667 8
                    $sheetId = 0; // keep track of new sheet id in final workbook
668 8
                    $oldSheetId = -1; // keep track of old sheet id in final workbook
669 8
                    $countSkippedSheets = 0; // keep track of number of skipped sheets
670 8
                    $mapSheetId = []; // mapping of sheet ids from old to new
671
672 8
                    $charts = $chartDetails = [];
673
674 8
                    if ($xmlWorkbook->sheets) {
675 8
                        foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
676 8
                            ++$oldSheetId;
677
678
                            // Check if sheet should be skipped
679 8
                            if (isset($this->loadSheetsOnly) && !in_array((string) $eleSheet['name'], $this->loadSheetsOnly)) {
680
                                ++$countSkippedSheets;
681
                                $mapSheetId[$oldSheetId] = null;
682
                                continue;
683
                            }
684
685
                            // Map old sheet id in original workbook to new sheet id.
686
                            // They will differ if loadSheetsOnly() is being used
687 8
                            $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets;
688
689
                            // Load sheet
690 8
                            $docSheet = $excel->createSheet();
691
                            //    Use false for $updateFormulaCellReferences to prevent adjustment of worksheet
692
                            //        references in formula cells... during the load, all formulae should be correct,
693
                            //        and we're simply bringing the worksheet name in line with the formula, not the
694
                            //        reverse
695 8
                            $docSheet->setTitle((string) $eleSheet['name'], false);
696 8
                            $fileWorksheet = $worksheets[(string) self::getArrayItem($eleSheet->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id')];
697 8
                            $xmlSheet = simplexml_load_string(
698
                                //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
699 8
                                $this->securityScan($this->getFromZipArchive($zip, "$dir/$fileWorksheet")),
700 8
                                'SimpleXMLElement',
701 8
                                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
702
                            );
703
704 8
                            $sharedFormulas = [];
705
706 8
                            if (isset($eleSheet['state']) && (string) $eleSheet['state'] != '') {
707
                                $docSheet->setSheetState((string) $eleSheet['state']);
708
                            }
709
710 8
                            if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) {
711 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
712
                                    $docSheet->getSheetView()->setZoomScale(intval($xmlSheet->sheetViews->sheetView['zoomScale']));
713
                                }
714 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
715
                                    $docSheet->getSheetView()->setZoomScaleNormal(intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']));
716
                                }
717 8
                                if (isset($xmlSheet->sheetViews->sheetView['view'])) {
718
                                    $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']);
719
                                }
720 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
721 5
                                    $docSheet->setShowGridLines(self::boolean((string) $xmlSheet->sheetViews->sheetView['showGridLines']));
722
                                }
723 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
724 5
                                    $docSheet->setShowRowColHeaders(self::boolean((string) $xmlSheet->sheetViews->sheetView['showRowColHeaders']));
725
                                }
726 8 View Code Duplication
                                if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
727
                                    $docSheet->setRightToLeft(self::boolean((string) $xmlSheet->sheetViews->sheetView['rightToLeft']));
728
                                }
729 8
                                if (isset($xmlSheet->sheetViews->sheetView->pane)) {
730 1
                                    if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
731 1
                                        $docSheet->freezePane((string) $xmlSheet->sheetViews->sheetView->pane['topLeftCell']);
732
                                    } else {
733
                                        $xSplit = 0;
734
                                        $ySplit = 0;
735
736 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...
737
                                            $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']);
738
                                        }
739
740 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...
741
                                            $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']);
742
                                        }
743
744
                                        $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit);
745
                                    }
746
                                }
747
748 8
                                if (isset($xmlSheet->sheetViews->sheetView->selection)) {
749 8
                                    if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) {
750 8
                                        $sqref = (string) $xmlSheet->sheetViews->sheetView->selection['sqref'];
751 8
                                        $sqref = explode(' ', $sqref);
752 8
                                        $sqref = $sqref[0];
753 8
                                        $docSheet->setSelectedCells($sqref);
754
                                    }
755
                                }
756
                            }
757
758 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) {
759 2
                                if (isset($xmlSheet->sheetPr->tabColor['rgb'])) {
760 2
                                    $docSheet->getTabColor()->setARGB((string) $xmlSheet->sheetPr->tabColor['rgb']);
761
                                }
762
                            }
763 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) {
764
                                $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']);
765
                            }
766 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) {
767 5 View Code Duplication
                                if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
768 5
                                    !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) {
769
                                    $docSheet->setShowSummaryRight(false);
770
                                } else {
771 5
                                    $docSheet->setShowSummaryRight(true);
772
                                }
773
774 5 View Code Duplication
                                if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
775 5
                                    !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) {
776
                                    $docSheet->setShowSummaryBelow(false);
777
                                } else {
778 5
                                    $docSheet->setShowSummaryBelow(true);
779
                                }
780
                            }
781
782 8
                            if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) {
783
                                if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) &&
784
                                    !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) {
785
                                    $docSheet->getPageSetup()->setFitToPage(false);
786
                                } else {
787
                                    $docSheet->getPageSetup()->setFitToPage(true);
788
                                }
789
                            }
790
791 8
                            if (isset($xmlSheet->sheetFormatPr)) {
792 8
                                if (isset($xmlSheet->sheetFormatPr['customHeight']) &&
793 8
                                    self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) &&
794 8
                                    isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) {
795
                                    $docSheet->getDefaultRowDimension()->setRowHeight((float) $xmlSheet->sheetFormatPr['defaultRowHeight']);
796
                                }
797 8
                                if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) {
798
                                    $docSheet->getDefaultColumnDimension()->setWidth((float) $xmlSheet->sheetFormatPr['defaultColWidth']);
799
                                }
800 8
                                if (isset($xmlSheet->sheetFormatPr['zeroHeight']) &&
801 8
                                    ((string) $xmlSheet->sheetFormatPr['zeroHeight'] == '1')) {
802
                                    $docSheet->getDefaultRowDimension()->setZeroHeight(true);
803
                                }
804
                            }
805
806 8
                            if (isset($xmlSheet->cols) && !$this->readDataOnly) {
807 5
                                foreach ($xmlSheet->cols->col as $col) {
808 5
                                    for ($i = intval($col['min']) - 1; $i < intval($col['max']); ++$i) {
809 5
                                        if ($col['style'] && !$this->readDataOnly) {
810 3
                                            $docSheet->getColumnDimension(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setXfIndex(intval($col['style']));
811
                                        }
812 5
                                        if (self::boolean($col['hidden'])) {
813 1
                                            $docSheet->getColumnDimension(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setVisible(false);
814
                                        }
815 5
                                        if (self::boolean($col['collapsed'])) {
816 1
                                            $docSheet->getColumnDimension(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setCollapsed(true);
817
                                        }
818 5
                                        if ($col['outlineLevel'] > 0) {
819 1
                                            $docSheet->getColumnDimension(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col['outlineLevel']));
820
                                        }
821 5
                                        $docSheet->getColumnDimension(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex($i))->setWidth(floatval($col['width']));
822
823 5
                                        if (intval($col['max']) == 16384) {
824
                                            break;
825
                                        }
826
                                    }
827
                                }
828
                            }
829
830 8
                            if (isset($xmlSheet->printOptions) && !$this->readDataOnly) {
831 5
                                if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) {
832 5
                                    $docSheet->setShowGridlines(true);
833
                                }
834 5
                                if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) {
835
                                    $docSheet->setPrintGridlines(true);
836
                                }
837 5
                                if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) {
838
                                    $docSheet->getPageSetup()->setHorizontalCentered(true);
839
                                }
840 5
                                if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) {
841
                                    $docSheet->getPageSetup()->setVerticalCentered(true);
842
                                }
843
                            }
844
845 8
                            if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) {
846 8
                                foreach ($xmlSheet->sheetData->row as $row) {
847 8
                                    if ($row['ht'] && !$this->readDataOnly) {
848 1
                                        $docSheet->getRowDimension(intval($row['r']))->setRowHeight(floatval($row['ht']));
849
                                    }
850 8
                                    if (self::boolean($row['hidden']) && !$this->readDataOnly) {
851
                                        $docSheet->getRowDimension(intval($row['r']))->setVisible(false);
852
                                    }
853 8
                                    if (self::boolean($row['collapsed'])) {
854
                                        $docSheet->getRowDimension(intval($row['r']))->setCollapsed(true);
855
                                    }
856 8
                                    if ($row['outlineLevel'] > 0) {
857
                                        $docSheet->getRowDimension(intval($row['r']))->setOutlineLevel(intval($row['outlineLevel']));
858
                                    }
859 8 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...
860
                                        $docSheet->getRowDimension(intval($row['r']))->setXfIndex(intval($row['s']));
861
                                    }
862
863 8
                                    foreach ($row->c as $c) {
864 8
                                        $r = (string) $c['r'];
865 8
                                        $cellDataType = (string) $c['t'];
866 8
                                        $value = null;
867 8
                                        $calculatedValue = null;
868
869
                                        // Read cell?
870 8
                                        if ($this->getReadFilter() !== null) {
871 8
                                            $coordinates = \PhpOffice\PhpSpreadsheet\Cell::coordinateFromString($r);
872
873 8
                                            if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) {
874 1
                                                continue;
875
                                            }
876
                                        }
877
878
                                        // Read cell!
879
                                        switch ($cellDataType) {
880 8
                                            case 's':
881 8
                                                if ((string) $c->v != '') {
882 8
                                                    $value = $sharedStrings[intval($c->v)];
883
884 8
                                                    if ($value instanceof \PhpOffice\PhpSpreadsheet\RichText) {
885 8
                                                        $value = clone $value;
886
                                                    }
887
                                                } else {
888
                                                    $value = '';
889
                                                }
890 8
                                                break;
891 6
                                            case 'b':
892 1
                                                if (!isset($c->f)) {
893 1
                                                    $value = self::castToBoolean($c);
894
                                                } else {
895
                                                    // Formula
896
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToBoolean');
897
                                                    if (isset($c->f['t'])) {
898
                                                        $att = [];
0 ignored issues
show
Unused Code introduced by
$att is not used, you could remove the assignment.

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

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

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

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

Loading history...
899
                                                        $att = $c->f;
900
                                                        $docSheet->getCell($r)->setFormulaAttributes($att);
901
                                                    }
902
                                                }
903 1
                                                break;
904 5 View Code Duplication
                                            case 'inlineStr':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
905 2
                                                if (isset($c->f)) {
906
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
907
                                                } else {
908 2
                                                    $value = $this->parseRichText($c->is);
909
                                                }
910 2
                                                break;
911 5 View Code Duplication
                                            case 'e':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
912
                                                if (!isset($c->f)) {
913
                                                    $value = self::castToError($c);
914
                                                } else {
915
                                                    // Formula
916
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToError');
917
                                                }
918
                                                break;
919
                                            default:
920 5
                                                if (!isset($c->f)) {
921 5
                                                    $value = self::castToString($c);
922
                                                } else {
923
                                                    // Formula
924 3
                                                    $this->castToFormula($c, $r, $cellDataType, $value, $calculatedValue, $sharedFormulas, 'castToString');
925
                                                }
926 5
                                                break;
927
                                        }
928
929
                                        // Check for numeric values
930 8
                                        if (is_numeric($value) && $cellDataType != 's') {
931 5
                                            if ($value == (int) $value) {
932 5
                                                $value = (int) $value;
933
                                            } elseif ($value == (float) $value) {
934
                                                $value = (float) $value;
935
                                            } elseif ($value == (double) $value) {
936
                                                $value = (double) $value;
937
                                            }
938
                                        }
939
940
                                        // Rich text?
941 8
                                        if ($value instanceof \PhpOffice\PhpSpreadsheet\RichText && $this->readDataOnly) {
942
                                            $value = $value->getPlainText();
943
                                        }
944
945 8
                                        $cell = $docSheet->getCell($r);
946
                                        // Assign value
947 8
                                        if ($cellDataType != '') {
948 8
                                            $cell->setValueExplicit($value, $cellDataType);
949
                                        } else {
950 5
                                            $cell->setValue($value);
951
                                        }
952 8
                                        if ($calculatedValue !== null) {
953 3
                                            $cell->setCalculatedValue($calculatedValue);
954
                                        }
955
956
                                        // Style information?
957 8 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...
958
                                            // no style index means 0, it seems
959 5
                                            $cell->setXfIndex(isset($styles[intval($c['s'])]) ?
960 8
                                                intval($c['s']) : 0);
961
                                        }
962
                                    }
963
                                }
964
                            }
965
966 8
                            $conditionals = [];
967 8
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) {
968
                                foreach ($xmlSheet->conditionalFormatting as $conditional) {
969
                                    foreach ($conditional->cfRule as $cfRule) {
970
                                        if (((string) $cfRule['type'] == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_NONE || (string) $cfRule['type'] == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS || (string) $cfRule['type'] == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CONTAINSTEXT || (string) $cfRule['type'] == \PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_EXPRESSION) && isset($dxfs[intval($cfRule['dxfId'])])) {
971
                                            $conditionals[(string) $conditional['sqref']][intval($cfRule['priority'])] = $cfRule;
972
                                        }
973
                                    }
974
                                }
975
976
                                foreach ($conditionals as $ref => $cfRules) {
977
                                    ksort($cfRules);
978
                                    $conditionalStyles = [];
979
                                    foreach ($cfRules as $cfRule) {
980
                                        $objConditional = new \PhpOffice\PhpSpreadsheet\Style\Conditional();
981
                                        $objConditional->setConditionType((string) $cfRule['type']);
982
                                        $objConditional->setOperatorType((string) $cfRule['operator']);
983
984
                                        if ((string) $cfRule['text'] != '') {
985
                                            $objConditional->setText((string) $cfRule['text']);
986
                                        }
987
988
                                        if (count($cfRule->formula) > 1) {
989
                                            foreach ($cfRule->formula as $formula) {
990
                                                $objConditional->addCondition((string) $formula);
991
                                            }
992
                                        } else {
993
                                            $objConditional->addCondition((string) $cfRule->formula);
994
                                        }
995
                                        $objConditional->setStyle(clone $dxfs[intval($cfRule['dxfId'])]);
996
                                        $conditionalStyles[] = $objConditional;
997
                                    }
998
999
                                    // Extract all cell references in $ref
1000
                                    $cellBlocks = explode(' ', str_replace('$', '', strtoupper($ref)));
1001
                                    foreach ($cellBlocks as $cellBlock) {
1002
                                        $docSheet->getStyle($cellBlock)->setConditionalStyles($conditionalStyles);
1003
                                    }
1004
                                }
1005
                            }
1006
1007 8
                            $aKeys = ['sheet', 'objects', 'scenarios', 'formatCells', 'formatColumns', 'formatRows', 'insertColumns', 'insertRows', 'insertHyperlinks', 'deleteColumns', 'deleteRows', 'selectLockedCells', 'sort', 'autoFilter', 'pivotTables', 'selectUnlockedCells'];
1008 8
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
1009 5
                                foreach ($aKeys as $key) {
1010 5
                                    $method = 'set' . ucfirst($key);
1011 5
                                    $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key]));
1012
                                }
1013
                            }
1014
1015 8
                            if (!$this->readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) {
1016 5
                                $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection['password'], true);
1017 5
                                if ($xmlSheet->protectedRanges->protectedRange) {
1018 2
                                    foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) {
1019 2
                                        $docSheet->protectCells((string) $protectedRange['sqref'], (string) $protectedRange['password'], true);
1020
                                    }
1021
                                }
1022
                            }
1023
1024 8
                            if ($xmlSheet && $xmlSheet->autoFilter && !$this->readDataOnly) {
1025
                                $autoFilterRange = (string) $xmlSheet->autoFilter['ref'];
1026
                                if (strpos($autoFilterRange, ':') !== false) {
1027
                                    $autoFilter = $docSheet->getAutoFilter();
1028
                                    $autoFilter->setRange($autoFilterRange);
1029
1030
                                    foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) {
1031
                                        $column = $autoFilter->getColumnByOffset((integer) $filterColumn['colId']);
1032
                                        //    Check for standard filters
1033
                                        if ($filterColumn->filters) {
1034
                                            $column->setFilterType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER);
1035
                                            $filters = $filterColumn->filters;
1036
                                            if ((isset($filters['blank'])) && ($filters['blank'] == 1)) {
1037
                                                //    Operator is undefined, but always treated as EQUAL
1038
                                                $column->createRule()->setRule(null, '')->setRuleType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_FILTER);
1039
                                            }
1040
                                            //    Standard filters are always an OR join, so no join rule needs to be set
1041
                                            //    Entries can be either filter elements
1042 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...
1043
                                                //    Operator is undefined, but always treated as EQUAL
1044
                                                $column->createRule()->setRule(null, (string) $filterRule['val'])->setRuleType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_FILTER);
1045
                                            }
1046
                                            //    Or Date Group elements
1047
                                            foreach ($filters->dateGroupItem as $dateGroupItem) {
1048
                                                $column->createRule()->setRule(
1049
                                                    //    Operator is undefined, but always treated as EQUAL
1050
                                                    null,
1051
                                                    [
1052
                                                        'year' => (string) $dateGroupItem['year'],
1053
                                                        'month' => (string) $dateGroupItem['month'],
1054
                                                        'day' => (string) $dateGroupItem['day'],
1055
                                                        'hour' => (string) $dateGroupItem['hour'],
1056
                                                        'minute' => (string) $dateGroupItem['minute'],
1057
                                                        'second' => (string) $dateGroupItem['second'],
1058
                                                    ],
1059
                                                    (string) $dateGroupItem['dateTimeGrouping']
1060
                                                )
1061
                                                ->setRuleType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP);
1062
                                            }
1063
                                        }
1064
                                        //    Check for custom filters
1065
                                        if ($filterColumn->customFilters) {
1066
                                            $column->setFilterType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
1067
                                            $customFilters = $filterColumn->customFilters;
1068
                                            //    Custom filters can an AND or an OR join;
1069
                                            //        and there should only ever be one or two entries
1070
                                            if ((isset($customFilters['and'])) && ($customFilters['and'] == 1)) {
1071
                                                $column->setJoin(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND);
1072
                                            }
1073 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...
1074
                                                $column->createRule()->setRule(
1075
                                                    (string) $filterRule['operator'],
1076
                                                    (string) $filterRule['val']
1077
                                                )
1078
                                                ->setRuleType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
1079
                                            }
1080
                                        }
1081
                                        //    Check for dynamic filters
1082
                                        if ($filterColumn->dynamicFilter) {
1083
                                            $column->setFilterType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
1084
                                            //    We should only ever have one dynamic filter
1085
                                            foreach ($filterColumn->dynamicFilter as $filterRule) {
1086
                                                $column->createRule()->setRule(
1087
                                                    //    Operator is undefined, but always treated as EQUAL
1088
                                                    null,
1089
                                                    (string) $filterRule['val'],
1090
                                                    (string) $filterRule['type']
1091
                                                )
1092
                                                ->setRuleType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
1093
                                                if (isset($filterRule['val'])) {
1094
                                                    $column->setAttribute('val', (string) $filterRule['val']);
1095
                                                }
1096
                                                if (isset($filterRule['maxVal'])) {
1097
                                                    $column->setAttribute('maxVal', (string) $filterRule['maxVal']);
1098
                                                }
1099
                                            }
1100
                                        }
1101
                                        //    Check for dynamic filters
1102
                                        if ($filterColumn->top10) {
1103
                                            $column->setFilterType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER);
1104
                                            //    We should only ever have one top10 filter
1105
                                            foreach ($filterColumn->top10 as $filterRule) {
1106
                                                $column->createRule()->setRule(
1107
                                                    (((isset($filterRule['percent'])) && ($filterRule['percent'] == 1))
1108
                                                        ? \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT
1109
                                                        : \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE
1110
                                                    ),
1111
                                                    (string) $filterRule['val'],
1112
                                                    (((isset($filterRule['top'])) && ($filterRule['top'] == 1))
1113
                                                        ? \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP
1114
                                                        : \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM
1115
                                                    )
1116
                                                )
1117
                                                ->setRuleType(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_TOPTENFILTER);
1118
                                            }
1119
                                        }
1120
                                    }
1121
                                }
1122
                            }
1123
1124 8
                            if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->readDataOnly) {
1125 4
                                foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) {
1126 4
                                    $mergeRef = (string) $mergeCell['ref'];
1127 4
                                    if (strpos($mergeRef, ':') !== false) {
1128 4
                                        $docSheet->mergeCells((string) $mergeCell['ref']);
1129
                                    }
1130
                                }
1131
                            }
1132
1133 8
                            if ($xmlSheet && $xmlSheet->pageMargins && !$this->readDataOnly) {
1134 8
                                $docPageMargins = $docSheet->getPageMargins();
1135 8
                                $docPageMargins->setLeft(floatval($xmlSheet->pageMargins['left']));
1136 8
                                $docPageMargins->setRight(floatval($xmlSheet->pageMargins['right']));
1137 8
                                $docPageMargins->setTop(floatval($xmlSheet->pageMargins['top']));
1138 8
                                $docPageMargins->setBottom(floatval($xmlSheet->pageMargins['bottom']));
1139 8
                                $docPageMargins->setHeader(floatval($xmlSheet->pageMargins['header']));
1140 8
                                $docPageMargins->setFooter(floatval($xmlSheet->pageMargins['footer']));
1141
                            }
1142
1143 8
                            if ($xmlSheet && $xmlSheet->pageSetup && !$this->readDataOnly) {
1144 8
                                $docPageSetup = $docSheet->getPageSetup();
1145
1146 8
                                if (isset($xmlSheet->pageSetup['orientation'])) {
1147 8
                                    $docPageSetup->setOrientation((string) $xmlSheet->pageSetup['orientation']);
1148
                                }
1149 8
                                if (isset($xmlSheet->pageSetup['paperSize'])) {
1150 8
                                    $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup['paperSize']));
1151
                                }
1152 8
                                if (isset($xmlSheet->pageSetup['scale'])) {
1153 5
                                    $docPageSetup->setScale(intval($xmlSheet->pageSetup['scale']), false);
1154
                                }
1155 8 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...
1156 5
                                    $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup['fitToHeight']), false);
1157
                                }
1158 8 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...
1159 5
                                    $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup['fitToWidth']), false);
1160
                                }
1161 8
                                if (isset($xmlSheet->pageSetup['firstPageNumber']) && isset($xmlSheet->pageSetup['useFirstPageNumber']) &&
1162 8
                                    self::boolean((string) $xmlSheet->pageSetup['useFirstPageNumber'])) {
1163
                                    $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup['firstPageNumber']));
1164
                                }
1165
                            }
1166
1167 8
                            if ($xmlSheet && $xmlSheet->headerFooter && !$this->readDataOnly) {
1168 5
                                $docHeaderFooter = $docSheet->getHeaderFooter();
1169
1170 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['differentOddEven']) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1171 5
                                    self::boolean((string) $xmlSheet->headerFooter['differentOddEven'])) {
1172
                                    $docHeaderFooter->setDifferentOddEven(true);
1173
                                } else {
1174 5
                                    $docHeaderFooter->setDifferentOddEven(false);
1175
                                }
1176 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['differentFirst']) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1177 5
                                    self::boolean((string) $xmlSheet->headerFooter['differentFirst'])) {
1178
                                    $docHeaderFooter->setDifferentFirst(true);
1179
                                } else {
1180 5
                                    $docHeaderFooter->setDifferentFirst(false);
1181
                                }
1182 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['scaleWithDoc']) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1183 5
                                    !self::boolean((string) $xmlSheet->headerFooter['scaleWithDoc'])) {
1184
                                    $docHeaderFooter->setScaleWithDocument(false);
1185
                                } else {
1186 5
                                    $docHeaderFooter->setScaleWithDocument(true);
1187
                                }
1188 5 View Code Duplication
                                if (isset($xmlSheet->headerFooter['alignWithMargins']) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1189 5
                                    !self::boolean((string) $xmlSheet->headerFooter['alignWithMargins'])) {
1190 1
                                    $docHeaderFooter->setAlignWithMargins(false);
1191
                                } else {
1192 4
                                    $docHeaderFooter->setAlignWithMargins(true);
1193
                                }
1194
1195 5
                                $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader);
1196 5
                                $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter);
1197 5
                                $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader);
1198 5
                                $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter);
1199 5
                                $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader);
1200 5
                                $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter);
1201
                            }
1202
1203 8
                            if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->readDataOnly) {
1204
                                foreach ($xmlSheet->rowBreaks->brk as $brk) {
1205
                                    if ($brk['man']) {
1206
                                        $docSheet->setBreak("A$brk[id]", \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_ROW);
1207
                                    }
1208
                                }
1209
                            }
1210 8
                            if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->readDataOnly) {
1211
                                foreach ($xmlSheet->colBreaks->brk as $brk) {
1212
                                    if ($brk['man']) {
1213
                                        $docSheet->setBreak(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $brk['id']) . '1', \PhpOffice\PhpSpreadsheet\Worksheet::BREAK_COLUMN);
1214
                                    }
1215
                                }
1216
                            }
1217
1218 8
                            if ($xmlSheet && $xmlSheet->dataValidations && !$this->readDataOnly) {
1219
                                foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) {
1220
                                    // Uppercase coordinate
1221
                                    $range = strtoupper($dataValidation['sqref']);
1222
                                    $rangeSet = explode(' ', $range);
1223
                                    foreach ($rangeSet as $range) {
1224
                                        $stRange = $docSheet->shrinkRangeToFit($range);
1225
1226
                                        // Extract all cell references in $range
1227
                                        foreach (\PhpOffice\PhpSpreadsheet\Cell::extractAllCellReferencesInRange($stRange) as $reference) {
1228
                                            // Create validation
1229
                                            $docValidation = $docSheet->getCell($reference)->getDataValidation();
1230
                                            $docValidation->setType((string) $dataValidation['type']);
1231
                                            $docValidation->setErrorStyle((string) $dataValidation['errorStyle']);
1232
                                            $docValidation->setOperator((string) $dataValidation['operator']);
1233
                                            $docValidation->setAllowBlank($dataValidation['allowBlank'] != 0);
1234
                                            $docValidation->setShowDropDown($dataValidation['showDropDown'] == 0);
1235
                                            $docValidation->setShowInputMessage($dataValidation['showInputMessage'] != 0);
1236
                                            $docValidation->setShowErrorMessage($dataValidation['showErrorMessage'] != 0);
1237
                                            $docValidation->setErrorTitle((string) $dataValidation['errorTitle']);
1238
                                            $docValidation->setError((string) $dataValidation['error']);
1239
                                            $docValidation->setPromptTitle((string) $dataValidation['promptTitle']);
1240
                                            $docValidation->setPrompt((string) $dataValidation['prompt']);
1241
                                            $docValidation->setFormula1((string) $dataValidation->formula1);
1242
                                            $docValidation->setFormula2((string) $dataValidation->formula2);
1243
                                        }
1244
                                    }
1245
                                }
1246
                            }
1247
1248
                            // Add hyperlinks
1249 8
                            $hyperlinks = [];
1250 8
                            if (!$this->readDataOnly) {
1251
                                // Locate hyperlink relations
1252 8
                                if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1253 8
                                    $relsWorksheet = simplexml_load_string(
1254
                                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
1255 8
                                        $this->securityScan(
1256 8
                                            $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1257
                                        ),
1258 8
                                        'SimpleXMLElement',
1259 8
                                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1260
                                    );
1261 8
                                    foreach ($relsWorksheet->Relationship as $ele) {
1262 5
                                        if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink') {
1263 5
                                            $hyperlinks[(string) $ele['Id']] = (string) $ele['Target'];
1264
                                        }
1265
                                    }
1266
                                }
1267
1268
                                // Loop through hyperlinks
1269 8
                                if ($xmlSheet && $xmlSheet->hyperlinks) {
1270 2
                                    foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) {
1271
                                        // Link url
1272 2
                                        $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1273
1274 2
                                        foreach (\PhpOffice\PhpSpreadsheet\Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) {
1275 2
                                            $cell = $docSheet->getCell($cellReference);
1276 2
                                            if (isset($linkRel['id'])) {
1277 2
                                                $hyperlinkUrl = $hyperlinks[(string) $linkRel['id']];
1278 2
                                                if (isset($hyperlink['location'])) {
1279
                                                    $hyperlinkUrl .= '#' . (string) $hyperlink['location'];
1280
                                                }
1281 2
                                                $cell->getHyperlink()->setUrl($hyperlinkUrl);
1282 2
                                            } elseif (isset($hyperlink['location'])) {
1283 2
                                                $cell->getHyperlink()->setUrl('sheet://' . (string) $hyperlink['location']);
1284
                                            }
1285
1286
                                            // Tooltip
1287 2
                                            if (isset($hyperlink['tooltip'])) {
1288 2
                                                $cell->getHyperlink()->setTooltip((string) $hyperlink['tooltip']);
1289
                                            }
1290
                                        }
1291
                                    }
1292
                                }
1293
                            }
1294
1295
                            // Add comments
1296 8
                            $comments = [];
1297 8
                            $vmlComments = [];
1298 8
                            if (!$this->readDataOnly) {
1299
                                // Locate comment relations
1300 8
                                if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1301 8
                                    $relsWorksheet = simplexml_load_string(
1302
                                        //~ http://schemas.openxmlformats.org/package/2006/relationships"
1303 8
                                        $this->securityScan(
1304 8
                                            $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1305
                                        ),
1306 8
                                        'SimpleXMLElement',
1307 8
                                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1308
                                    );
1309 8
                                    foreach ($relsWorksheet->Relationship as $ele) {
1310 5
                                        if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments') {
1311 2
                                            $comments[(string) $ele['Id']] = (string) $ele['Target'];
1312
                                        }
1313 5
                                        if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing') {
1314 5
                                            $vmlComments[(string) $ele['Id']] = (string) $ele['Target'];
1315
                                        }
1316
                                    }
1317
                                }
1318
1319
                                // Loop through comments
1320 8
                                foreach ($comments as $relName => $relPath) {
1321
                                    // Load comments file
1322 2
                                    $relPath = \PhpOffice\PhpSpreadsheet\Shared\File::realpath(dirname("$dir/$fileWorksheet") . '/' . $relPath);
1323 2
                                    $commentsFile = simplexml_load_string(
1324 2
                                        $this->securityScan($this->getFromZipArchive($zip, $relPath)),
1325 2
                                        'SimpleXMLElement',
1326 2
                                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1327
                                    );
1328
1329
                                    // Utility variables
1330 2
                                    $authors = [];
1331
1332
                                    // Loop through authors
1333 2
                                    foreach ($commentsFile->authors->author as $author) {
1334 2
                                        $authors[] = (string) $author;
1335
                                    }
1336
1337
                                    // Loop through contents
1338 2
                                    foreach ($commentsFile->commentList->comment as $comment) {
1339 2
                                        if (!empty($comment['authorId'])) {
1340
                                            $docSheet->getComment((string) $comment['ref'])->setAuthor($authors[(string) $comment['authorId']]);
1341
                                        }
1342 2
                                        $docSheet->getComment((string) $comment['ref'])->setText($this->parseRichText($comment->text));
1343
                                    }
1344
                                }
1345
1346
                                // Loop through VML comments
1347 8
                                foreach ($vmlComments as $relName => $relPath) {
1348
                                    // Load VML comments file
1349 2
                                    $relPath = \PhpOffice\PhpSpreadsheet\Shared\File::realpath(dirname("$dir/$fileWorksheet") . '/' . $relPath);
1350 2
                                    $vmlCommentsFile = simplexml_load_string(
1351 2
                                        $this->securityScan($this->getFromZipArchive($zip, $relPath)),
1352 2
                                        'SimpleXMLElement',
1353 2
                                        \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1354
                                    );
1355 2
                                    $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1356
1357 2
                                    $shapes = $vmlCommentsFile->xpath('//v:shape');
1358 2
                                    foreach ($shapes as $shape) {
1359 2
                                        $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1360
1361 2
                                        if (isset($shape['style'])) {
1362 2
                                            $style = (string) $shape['style'];
1363 2
                                            $fillColor = strtoupper(substr((string) $shape['fillcolor'], 1));
1364 2
                                            $column = null;
1365 2
                                            $row = null;
1366
1367 2
                                            $clientData = $shape->xpath('.//x:ClientData');
1368 2
                                            if (is_array($clientData) && !empty($clientData)) {
1369 2
                                                $clientData = $clientData[0];
1370
1371 2
                                                if (isset($clientData['ObjectType']) && (string) $clientData['ObjectType'] == 'Note') {
1372 2
                                                    $temp = $clientData->xpath('.//x:Row');
1373 2
                                                    if (is_array($temp)) {
1374 2
                                                        $row = $temp[0];
1375
                                                    }
1376
1377 2
                                                    $temp = $clientData->xpath('.//x:Column');
1378 2
                                                    if (is_array($temp)) {
1379 2
                                                        $column = $temp[0];
1380
                                                    }
1381
                                                }
1382
                                            }
1383
1384 2
                                            if (($column !== null) && ($row !== null)) {
1385
                                                // Set comment properties
1386 2
                                                $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1);
1387 2
                                                $comment->getFillColor()->setRGB($fillColor);
1388
1389
                                                // Parse style
1390 2
                                                $styleArray = explode(';', str_replace(' ', '', $style));
1391 2
                                                foreach ($styleArray as $stylePair) {
1392 2
                                                    $stylePair = explode(':', $stylePair);
1393
1394 2
                                                    if ($stylePair[0] == 'margin-left') {
1395 2
                                                        $comment->setMarginLeft($stylePair[1]);
1396
                                                    }
1397 2
                                                    if ($stylePair[0] == 'margin-top') {
1398 2
                                                        $comment->setMarginTop($stylePair[1]);
1399
                                                    }
1400 2
                                                    if ($stylePair[0] == 'width') {
1401 2
                                                        $comment->setWidth($stylePair[1]);
1402
                                                    }
1403 2
                                                    if ($stylePair[0] == 'height') {
1404 2
                                                        $comment->setHeight($stylePair[1]);
1405
                                                    }
1406 2
                                                    if ($stylePair[0] == 'visibility') {
1407 2
                                                        $comment->setVisible($stylePair[1] == 'visible');
1408
                                                    }
1409
                                                }
1410
                                            }
1411
                                        }
1412
                                    }
1413
                                }
1414
1415
                                // Header/footer images
1416 8
                                if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->readDataOnly) {
1417
                                    if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1418
                                        $relsWorksheet = simplexml_load_string(
1419
                                            //~ http://schemas.openxmlformats.org/package/2006/relationships"
1420
                                            $this->securityScan(
1421
                                                $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1422
                                            ),
1423
                                            'SimpleXMLElement',
1424
                                            \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1425
                                        );
1426
                                        $vmlRelationship = '';
1427
1428
                                        foreach ($relsWorksheet->Relationship as $ele) {
1429
                                            if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing') {
1430
                                                $vmlRelationship = self::dirAdd("$dir/$fileWorksheet", $ele['Target']);
1431
                                            }
1432
                                        }
1433
1434
                                        if ($vmlRelationship != '') {
1435
                                            // Fetch linked images
1436
                                            $relsVML = simplexml_load_string(
1437
                                                //~ http://schemas.openxmlformats.org/package/2006/relationships"
1438
                                                $this->securityScan(
1439
                                                    $this->getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels')
1440
                                                ),
1441
                                                'SimpleXMLElement',
1442
                                                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1443
                                            );
1444
                                            $drawings = [];
1445 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...
1446
                                                if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1447
                                                    $drawings[(string) $ele['Id']] = self::dirAdd($vmlRelationship, $ele['Target']);
1448
                                                }
1449
                                            }
1450
1451
                                            // Fetch VML document
1452
                                            $vmlDrawing = simplexml_load_string(
1453
                                                $this->securityScan($this->getFromZipArchive($zip, $vmlRelationship)),
1454
                                                'SimpleXMLElement',
1455
                                                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1456
                                            );
1457
                                            $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1458
1459
                                            $hfImages = [];
1460
1461
                                            $shapes = $vmlDrawing->xpath('//v:shape');
1462
                                            foreach ($shapes as $idx => $shape) {
1463
                                                $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
1464
                                                $imageData = $shape->xpath('//v:imagedata');
1465
                                                $imageData = $imageData[$idx];
1466
1467
                                                $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office');
1468
                                                $style = self::toCSSArray((string) $shape['style']);
1469
1470
                                                $hfImages[(string) $shape['id']] = new \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing();
1471
                                                if (isset($imageData['title'])) {
1472
                                                    $hfImages[(string) $shape['id']]->setName((string) $imageData['title']);
1473
                                                }
1474
1475
                                                $hfImages[(string) $shape['id']]->setPath('zip://' . \PhpOffice\PhpSpreadsheet\Shared_File::realpath($pFilename) . '#' . $drawings[(string) $imageData['relid']], false);
1476
                                                $hfImages[(string) $shape['id']]->setResizeProportional(false);
1477
                                                $hfImages[(string) $shape['id']]->setWidth($style['width']);
1478
                                                $hfImages[(string) $shape['id']]->setHeight($style['height']);
1479
                                                if (isset($style['margin-left'])) {
1480
                                                    $hfImages[(string) $shape['id']]->setOffsetX($style['margin-left']);
1481
                                                }
1482
                                                $hfImages[(string) $shape['id']]->setOffsetY($style['margin-top']);
1483
                                                $hfImages[(string) $shape['id']]->setResizeProportional(true);
1484
                                            }
1485
1486
                                            $docSheet->getHeaderFooter()->setImages($hfImages);
1487
                                        }
1488
                                    }
1489
                                }
1490
                            }
1491
1492
                            // TODO: Autoshapes from twoCellAnchors!
1493 8
                            if ($zip->locateName(dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')) {
1494 8
                                $relsWorksheet = simplexml_load_string(
1495
                                    //~ http://schemas.openxmlformats.org/package/2006/relationships"
1496 8
                                    $this->securityScan(
1497 8
                                        $this->getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . '/_rels/' . basename($fileWorksheet) . '.rels')
1498
                                    ),
1499 8
                                    'SimpleXMLElement',
1500 8
                                    \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1501
                                );
1502 8
                                $drawings = [];
1503 8 View Code Duplication
                                foreach ($relsWorksheet->Relationship as $ele) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1504 5
                                    if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing') {
1505 5
                                        $drawings[(string) $ele['Id']] = self::dirAdd("$dir/$fileWorksheet", $ele['Target']);
1506
                                    }
1507
                                }
1508 8
                                if ($xmlSheet->drawing && !$this->readDataOnly) {
1509 3
                                    foreach ($xmlSheet->drawing as $drawing) {
1510 3
                                        $fileDrawing = $drawings[(string) self::getArrayItem($drawing->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'), 'id')];
1511 3
                                        $relsDrawing = simplexml_load_string(
1512
                                            //~ http://schemas.openxmlformats.org/package/2006/relationships"
1513 3
                                            $this->securityScan(
1514 3
                                                $this->getFromZipArchive($zip, dirname($fileDrawing) . '/_rels/' . basename($fileDrawing) . '.rels')
1515
                                            ),
1516 3
                                            'SimpleXMLElement',
1517 3
                                            \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1518
                                        );
1519 3
                                        $images = [];
1520
1521 3
                                        if ($relsDrawing && $relsDrawing->Relationship) {
1522 3
                                            foreach ($relsDrawing->Relationship as $ele) {
1523 3
                                                if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
1524 3
                                                    $images[(string) $ele['Id']] = self::dirAdd($fileDrawing, $ele['Target']);
1525 1
                                                } elseif ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart') {
1526 1
                                                    if ($this->includeCharts) {
1527 1
                                                        $charts[self::dirAdd($fileDrawing, $ele['Target'])] = [
1528 1
                                                            'id' => (string) $ele['Id'],
1529 3
                                                            'sheet' => $docSheet->getTitle(),
1530
                                                        ];
1531
                                                    }
1532
                                                }
1533
                                            }
1534
                                        }
1535 3
                                        $xmlDrawing = simplexml_load_string(
1536 3
                                            $this->securityScan($this->getFromZipArchive($zip, $fileDrawing)),
1537 3
                                            'SimpleXMLElement',
1538 3
                                            \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1539 3
                                        )->children('http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing');
1540
1541 3
                                        if ($xmlDrawing->oneCellAnchor) {
1542 2
                                            foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) {
1543 2
                                                if ($oneCellAnchor->pic->blipFill) {
1544 2
                                                    $blip = $oneCellAnchor->pic->blipFill->children('http://schemas.openxmlformats.org/drawingml/2006/main')->blip;
1545 2
                                                    $xfrm = $oneCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->xfrm;
1546 2
                                                    $outerShdw = $oneCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->effectLst->outerShdw;
1547 2
                                                    $objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
1548 2
                                                    $objDrawing->setName((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'name'));
1549 2
                                                    $objDrawing->setDescription((string) self::getArrayItem($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'descr'));
1550 2
                                                    $objDrawing->setPath(
1551 2
                                                        'zip://' . \PhpOffice\PhpSpreadsheet\Shared\File::realpath($pFilename) . '#' .
1552 2
                                                        $images[(string) self::getArrayItem(
1553 2
                                                            $blip->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
1554 2
                                                            'embed'
1555
                                                        )],
1556 2
                                                        false
1557
                                                    );
1558 2
                                                    $objDrawing->setCoordinates(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1));
1559 2
                                                    $objDrawing->setOffsetX(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($oneCellAnchor->from->colOff));
1560 2
                                                    $objDrawing->setOffsetY(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($oneCellAnchor->from->rowOff));
1561 2
                                                    $objDrawing->setResizeProportional(false);
1562 2
                                                    $objDrawing->setWidth(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), 'cx')));
1563 2
                                                    $objDrawing->setHeight(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), 'cy')));
1564 2
                                                    if ($xfrm) {
1565 2
                                                        $objDrawing->setRotation(\PhpOffice\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), 'rot')));
1566
                                                    }
1567 2 View Code Duplication
                                                    if ($outerShdw) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1568 2
                                                        $shadow = $objDrawing->getShadow();
1569 2
                                                        $shadow->setVisible(true);
1570 2
                                                        $shadow->setBlurRadius(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'blurRad')));
1571 2
                                                        $shadow->setDistance(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'dist')));
1572 2
                                                        $shadow->setDirection(\PhpOffice\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), 'dir')));
1573 2
                                                        $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), 'algn'));
1574 2
                                                        $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), 'val'));
1575 2
                                                        $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), 'val') / 1000);
1576
                                                    }
1577 2
                                                    $objDrawing->setWorksheet($docSheet);
1578
                                                } else {
1579
                                                    //    ? Can charts be positioned with a oneCellAnchor ?
1580
                                                    $coordinates = \PhpOffice\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...
1581
                                                    $offsetX = \PhpOffice\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...
1582
                                                    $offsetY = \PhpOffice\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...
1583
                                                    $width = \PhpOffice\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...
1584 2
                                                    $height = \PhpOffice\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...
1585
                                                }
1586
                                            }
1587
                                        }
1588 3
                                        if ($xmlDrawing->twoCellAnchor) {
1589 1
                                            foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) {
1590 1
                                                if ($twoCellAnchor->pic->blipFill) {
1591 1
                                                    $blip = $twoCellAnchor->pic->blipFill->children('http://schemas.openxmlformats.org/drawingml/2006/main')->blip;
1592 1
                                                    $xfrm = $twoCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->xfrm;
1593 1
                                                    $outerShdw = $twoCellAnchor->pic->spPr->children('http://schemas.openxmlformats.org/drawingml/2006/main')->effectLst->outerShdw;
1594 1
                                                    $objDrawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
1595 1
                                                    $objDrawing->setName((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'name'));
1596 1
                                                    $objDrawing->setDescription((string) self::getArrayItem($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), 'descr'));
1597 1
                                                    $objDrawing->setPath(
1598 1
                                                        'zip://' . \PhpOffice\PhpSpreadsheet\Shared\File::realpath($pFilename) . '#' .
1599 1
                                                        $images[(string) self::getArrayItem(
1600 1
                                                            $blip->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'),
1601 1
                                                            'embed'
1602
                                                        )],
1603 1
                                                        false
1604
                                                    );
1605 1
                                                    $objDrawing->setCoordinates(\PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1));
1606 1
                                                    $objDrawing->setOffsetX(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->colOff));
1607 1
                                                    $objDrawing->setOffsetY(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->rowOff));
1608 1
                                                    $objDrawing->setResizeProportional(false);
1609
1610 1
                                                    if ($xfrm) {
1611 1
                                                        $objDrawing->setWidth(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), 'cx')));
1612 1
                                                        $objDrawing->setHeight(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels(self::getArrayItem($xfrm->ext->attributes(), 'cy')));
1613 1
                                                        $objDrawing->setRotation(\PhpOffice\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($xfrm->attributes(), 'rot')));
1614
                                                    }
1615 1 View Code Duplication
                                                    if ($outerShdw) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1616
                                                        $shadow = $objDrawing->getShadow();
1617
                                                        $shadow->setVisible(true);
1618
                                                        $shadow->setBlurRadius(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'blurRad')));
1619
                                                        $shadow->setDistance(\PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUTopixels(self::getArrayItem($outerShdw->attributes(), 'dist')));
1620
                                                        $shadow->setDirection(\PhpOffice\PhpSpreadsheet\Shared\Drawing::angleToDegrees(self::getArrayItem($outerShdw->attributes(), 'dir')));
1621
                                                        $shadow->setAlignment((string) self::getArrayItem($outerShdw->attributes(), 'algn'));
1622
                                                        $shadow->getColor()->setRGB(self::getArrayItem($outerShdw->srgbClr->attributes(), 'val'));
1623
                                                        $shadow->setAlpha(self::getArrayItem($outerShdw->srgbClr->alpha->attributes(), 'val') / 1000);
1624
                                                    }
1625 1
                                                    $objDrawing->setWorksheet($docSheet);
1626 1
                                                } elseif (($this->includeCharts) && ($twoCellAnchor->graphicFrame)) {
1627 1
                                                    $fromCoordinate = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1);
1628 1
                                                    $fromOffsetX = \PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->colOff);
1629 1
                                                    $fromOffsetY = \PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->from->rowOff);
1630 1
                                                    $toCoordinate = \PhpOffice\PhpSpreadsheet\Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1);
1631 1
                                                    $toOffsetX = \PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->to->colOff);
1632 1
                                                    $toOffsetY = \PhpOffice\PhpSpreadsheet\Shared\Drawing::EMUToPixels($twoCellAnchor->to->rowOff);
1633 1
                                                    $graphic = $twoCellAnchor->graphicFrame->children('http://schemas.openxmlformats.org/drawingml/2006/main')->graphic;
1634 1
                                                    $chartRef = $graphic->graphicData->children('http://schemas.openxmlformats.org/drawingml/2006/chart')->chart;
1635 1
                                                    $thisChart = (string) $chartRef->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1636
1637 1
                                                    $chartDetails[$docSheet->getTitle() . '!' . $thisChart] = [
1638 1
                                                        'fromCoordinate' => $fromCoordinate,
1639 1
                                                        'fromOffsetX' => $fromOffsetX,
1640 1
                                                        'fromOffsetY' => $fromOffsetY,
1641 1
                                                        'toCoordinate' => $toCoordinate,
1642 1
                                                        'toOffsetX' => $toOffsetX,
1643 1
                                                        'toOffsetY' => $toOffsetY,
1644 3
                                                        'worksheetTitle' => $docSheet->getTitle(),
1645
                                                    ];
1646
                                                }
1647
                                            }
1648
                                        }
1649
                                    }
1650
                                }
1651
                            }
1652
1653
                            // Loop through definedNames
1654 8
                            if ($xmlWorkbook->definedNames) {
1655 5
                                foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1656
                                    // Extract range
1657 1
                                    $extractedRange = (string) $definedName;
1658 1 View Code Duplication
                                    if (($spos = strpos($extractedRange, '!')) !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1659 1
                                        $extractedRange = substr($extractedRange, 0, $spos) . str_replace('$', '', substr($extractedRange, $spos));
1660
                                    } else {
1661
                                        $extractedRange = str_replace('$', '', $extractedRange);
1662
                                    }
1663
1664
                                    // Valid range?
1665 1
                                    if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') {
1666
                                        continue;
1667
                                    }
1668
1669
                                    // Some definedNames are only applicable if we are on the same sheet...
1670 1
                                    if ((string) $definedName['localSheetId'] != '' && (string) $definedName['localSheetId'] == $sheetId) {
1671
                                        // Switch on type
1672 1
                                        switch ((string) $definedName['name']) {
1673 1
                                            case '_xlnm._FilterDatabase':
1674
                                                if ((string) $definedName['hidden'] !== '1') {
1675
                                                    $extractedRange = explode(',', $extractedRange);
1676
                                                    foreach ($extractedRange as $range) {
1677
                                                        $autoFilterRange = $range;
1678
                                                        if (strpos($autoFilterRange, ':') !== false) {
1679
                                                            $docSheet->getAutoFilter()->setRange($autoFilterRange);
1680
                                                        }
1681
                                                    }
1682
                                                }
1683
                                                break;
1684 1
                                            case '_xlnm.Print_Titles':
1685
                                                // Split $extractedRange
1686 1
                                                $extractedRange = explode(',', $extractedRange);
1687
1688
                                                // Set print titles
1689 1
                                                foreach ($extractedRange as $range) {
1690 1
                                                    $matches = [];
1691 1
                                                    $range = str_replace('$', '', $range);
1692
1693
                                                    // check for repeating columns, e g. 'A:A' or 'A:D'
1694 1
                                                    if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) {
1695
                                                        $docSheet->getPageSetup()->setColumnsToRepeatAtLeft([$matches[1], $matches[2]]);
1696 1
                                                    } elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) {
1697
                                                        // check for repeating rows, e.g. '1:1' or '1:5'
1698 1
                                                        $docSheet->getPageSetup()->setRowsToRepeatAtTop([$matches[1], $matches[2]]);
1699
                                                    }
1700
                                                }
1701 1
                                                break;
1702
                                            case '_xlnm.Print_Area':
1703
                                                $rangeSets = preg_split("/'(.*?)'(?:![A-Z0-9]+:[A-Z0-9]+,?)/", $extractedRange, PREG_SPLIT_NO_EMPTY);
1704
                                                $newRangeSets = [];
1705
                                                foreach ($rangeSets as $rangeSet) {
1706
                                                    $range = explode('!', $rangeSet); // FIXME: what if sheetname contains exclamation mark?
1707
                                                    $rangeSet = isset($range[1]) ? $range[1] : $range[0];
1708
                                                    if (strpos($rangeSet, ':') === false) {
1709
                                                        $rangeSet = $rangeSet . ':' . $rangeSet;
1710
                                                    }
1711
                                                    $newRangeSets[] = str_replace('$', '', $rangeSet);
1712
                                                }
1713
                                                $docSheet->getPageSetup()->setPrintArea(implode(',', $newRangeSets));
1714
                                                break;
1715
1716
                                            default:
1717 1
                                                break;
1718
                                        }
1719
                                    }
1720
                                }
1721
                            }
1722
1723
                            // Next sheet id
1724 8
                            ++$sheetId;
1725
                        }
1726
1727
                        // Loop through definedNames
1728 8
                        if ($xmlWorkbook->definedNames) {
1729 5
                            foreach ($xmlWorkbook->definedNames->definedName as $definedName) {
1730
                                // Extract range
1731 1
                                $extractedRange = (string) $definedName;
1732 1 View Code Duplication
                                if (($spos = strpos($extractedRange, '!')) !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1733 1
                                    $extractedRange = substr($extractedRange, 0, $spos) . str_replace('$', '', substr($extractedRange, $spos));
1734
                                } else {
1735
                                    $extractedRange = str_replace('$', '', $extractedRange);
1736
                                }
1737
1738
                                // Valid range?
1739 1
                                if (stripos((string) $definedName, '#REF!') !== false || $extractedRange == '') {
1740
                                    continue;
1741
                                }
1742
1743
                                // Some definedNames are only applicable if we are on the same sheet...
1744 1
                                if ((string) $definedName['localSheetId'] != '') {
1745
                                    // Local defined name
1746
                                    // Switch on type
1747 1
                                    switch ((string) $definedName['name']) {
1748 1
                                        case '_xlnm._FilterDatabase':
1749 1
                                        case '_xlnm.Print_Titles':
1750
                                        case '_xlnm.Print_Area':
1751 1
                                            break;
1752
                                        default:
1753
                                            if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) {
1754
                                                $range = explode('!', (string) $definedName);
1755
                                                if (count($range) == 2) {
1756
                                                    $range[0] = str_replace("''", "'", $range[0]);
1757
                                                    $range[0] = str_replace("'", '', $range[0]);
1758
                                                    if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) {
1759
                                                        $extractedRange = str_replace('$', '', $range[1]);
1760
                                                        $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...
1761
                                                        $excel->addNamedRange(new \PhpOffice\PhpSpreadsheet\NamedRange((string) $definedName['name'], $worksheet, $extractedRange, true, $scope));
1762
                                                    }
1763
                                                }
1764
                                            }
1765 1
                                            break;
1766
                                    }
1767
                                } elseif (!isset($definedName['localSheetId'])) {
1768
                                    // "Global" definedNames
1769
                                    $locatedSheet = null;
1770
                                    $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...
1771
                                    if (strpos((string) $definedName, '!') !== false) {
1772
                                        // Extract sheet name
1773
                                        $extractedSheetName = \PhpOffice\PhpSpreadsheet\Worksheet::extractSheetTitle((string) $definedName, true);
1774
                                        $extractedSheetName = $extractedSheetName[0];
1775
1776
                                        // Locate sheet
1777
                                        $locatedSheet = $excel->getSheetByName($extractedSheetName);
1778
1779
                                        // Modify range
1780
                                        $range = explode('!', $extractedRange);
1781
                                        $extractedRange = isset($range[1]) ? $range[1] : $range[0];
1782
                                    }
1783
1784
                                    if ($locatedSheet !== null) {
1785 1
                                        $excel->addNamedRange(new \PhpOffice\PhpSpreadsheet\NamedRange((string) $definedName['name'], $locatedSheet, $extractedRange, false));
1786
                                    }
1787
                                }
1788
                            }
1789
                        }
1790
                    }
1791
1792 8
                    if ((!$this->readDataOnly) || (!empty($this->loadSheetsOnly))) {
1793
                        // active sheet index
1794 8
                        $activeTab = intval($xmlWorkbook->bookViews->workbookView['activeTab']); // refers to old sheet index
1795
1796
                        // keep active sheet index if sheet is still loaded, else first sheet is set as the active
1797 8
                        if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) {
1798 8
                            $excel->setActiveSheetIndex($mapSheetId[$activeTab]);
1799
                        } else {
1800
                            if ($excel->getSheetCount() == 0) {
1801
                                $excel->createSheet();
1802
                            }
1803
                            $excel->setActiveSheetIndex(0);
1804
                        }
1805
                    }
1806 8
                    break;
1807
            }
1808
        }
1809
1810 8
        if (!$this->readDataOnly) {
1811 8
            $contentTypes = simplexml_load_string(
1812 8
                $this->securityScan(
1813 8
                    $this->getFromZipArchive($zip, '[Content_Types].xml')
1814
                ),
1815 8
                'SimpleXMLElement',
1816 8
                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1817
            );
1818 8
            foreach ($contentTypes->Override as $contentType) {
1819 8
                switch ($contentType['ContentType']) {
1820 8
                    case 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml':
1821 1
                        if ($this->includeCharts) {
1822 1
                            $chartEntryRef = ltrim($contentType['PartName'], '/');
1823 1
                            $chartElements = simplexml_load_string(
1824 1
                                $this->securityScan(
1825 1
                                    $this->getFromZipArchive($zip, $chartEntryRef)
1826
                                ),
1827 1
                                'SimpleXMLElement',
1828 1
                                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
1829
                            );
1830 1
                            $objChart = \PhpOffice\PhpSpreadsheet\Reader\Xlsx\Chart::readChart($chartElements, basename($chartEntryRef, '.xml'));
1831
1832 1
                            if (isset($charts[$chartEntryRef])) {
1833 1
                                $chartPositionRef = $charts[$chartEntryRef]['sheet'] . '!' . $charts[$chartEntryRef]['id'];
1834 1
                                if (isset($chartDetails[$chartPositionRef])) {
1835 1
                                    $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart);
1836 1
                                    $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet']));
1837 1
                                    $objChart->setTopLeftPosition($chartDetails[$chartPositionRef]['fromCoordinate'], $chartDetails[$chartPositionRef]['fromOffsetX'], $chartDetails[$chartPositionRef]['fromOffsetY']);
1838 8
                                    $objChart->setBottomRightPosition($chartDetails[$chartPositionRef]['toCoordinate'], $chartDetails[$chartPositionRef]['toOffsetX'], $chartDetails[$chartPositionRef]['toOffsetY']);
1839
                                }
1840
                            }
1841
                        }
1842
                }
1843
            }
1844
        }
1845
1846 8
        $zip->close();
1847
1848 8
        return $excel;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $excel; (PhpOffice\PhpSpreadsheet\Spreadsheet) is incompatible with the return type declared by the interface PhpOffice\PhpSpreadsheet\Reader\IReader::load of type PhpOffice\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...
1849
    }
1850
1851 8
    private static function readColor($color, $background = false)
1852
    {
1853 8
        if (isset($color['rgb'])) {
1854 7
            return (string) $color['rgb'];
1855 4
        } elseif (isset($color['indexed'])) {
1856 3
            return \PhpOffice\PhpSpreadsheet\Style\Color::indexedColor($color['indexed'] - 7, $background)->getARGB();
1857 3
        } elseif (isset($color['theme'])) {
1858 3
            if (self::$theme !== null) {
1859 3
                $returnColour = self::$theme->getColourByIndex((int) $color['theme']);
1860 3
                if (isset($color['tint'])) {
1861
                    $tintAdjust = (float) $color['tint'];
1862
                    $returnColour = \PhpOffice\PhpSpreadsheet\Style\Color::changeBrightness($returnColour, $tintAdjust);
1863
                }
1864
1865 3
                return 'FF' . $returnColour;
1866
            }
1867
        }
1868
1869
        if ($background) {
1870
            return 'FFFFFFFF';
1871
        }
1872
1873
        return 'FF000000';
1874
    }
1875
1876
    /**
1877
     * @param \PhpOffice\PhpSpreadsheet\Style $docStyle
1878
     * @param \stdClass|\SimpleXMLElement $style
1879
     */
1880 8
    private static function readStyle(\PhpOffice\PhpSpreadsheet\Style $docStyle, $style)
1881
    {
1882 8
        $docStyle->getNumberFormat()->setFormatCode($style->numFmt);
1883
1884
        // font
1885 8
        if (isset($style->font)) {
1886 8
            $docStyle->getFont()->setName((string) $style->font->name['val']);
1887 8
            $docStyle->getFont()->setSize((string) $style->font->sz['val']);
1888 8 View Code Duplication
            if (isset($style->font->b)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1889 7
                $docStyle->getFont()->setBold(!isset($style->font->b['val']) || self::boolean((string) $style->font->b['val']));
1890
            }
1891 8 View Code Duplication
            if (isset($style->font->i)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1892 5
                $docStyle->getFont()->setItalic(!isset($style->font->i['val']) || self::boolean((string) $style->font->i['val']));
1893
            }
1894 8 View Code Duplication
            if (isset($style->font->strike)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1895 5
                $docStyle->getFont()->setStrikethrough(!isset($style->font->strike['val']) || self::boolean((string) $style->font->strike['val']));
1896
            }
1897 8
            $docStyle->getFont()->getColor()->setARGB(self::readColor($style->font->color));
1898
1899 8 View Code Duplication
            if (isset($style->font->u) && !isset($style->font->u['val'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1900
                $docStyle->getFont()->setUnderline(\PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE);
1901 8
            } elseif (isset($style->font->u) && isset($style->font->u['val'])) {
1902 5
                $docStyle->getFont()->setUnderline((string) $style->font->u['val']);
1903
            }
1904
1905 8 View Code Duplication
            if (isset($style->font->vertAlign) && isset($style->font->vertAlign['val'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1906
                $vertAlign = strtolower((string) $style->font->vertAlign['val']);
1907
                if ($vertAlign == 'superscript') {
1908
                    $docStyle->getFont()->setSuperScript(true);
1909
                }
1910
                if ($vertAlign == 'subscript') {
1911
                    $docStyle->getFont()->setSubScript(true);
1912
                }
1913
            }
1914
        }
1915
1916
        // fill
1917 8
        if (isset($style->fill)) {
1918 8
            if ($style->fill->gradientFill) {
1919 2
                $gradientFill = $style->fill->gradientFill[0];
1920 2
                if (!empty($gradientFill['type'])) {
1921 2
                    $docStyle->getFill()->setFillType((string) $gradientFill['type']);
1922
                }
1923 2
                $docStyle->getFill()->setRotation(floatval($gradientFill['degree']));
1924 2
                $gradientFill->registerXPathNamespace('sml', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
1925 2
                $docStyle->getFill()->getStartColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=0]'))->color));
1926 2
                $docStyle->getFill()->getEndColor()->setARGB(self::readColor(self::getArrayItem($gradientFill->xpath('sml:stop[@position=1]'))->color));
1927 8
            } elseif ($style->fill->patternFill) {
1928 8
                $patternType = (string) $style->fill->patternFill['patternType'] != '' ? (string) $style->fill->patternFill['patternType'] : 'solid';
1929 8
                $docStyle->getFill()->setFillType($patternType);
1930 8
                if ($style->fill->patternFill->fgColor) {
1931 3
                    $docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true));
1932
                } else {
1933 8
                    $docStyle->getFill()->getStartColor()->setARGB('FF000000');
1934
                }
1935 8
                if ($style->fill->patternFill->bgColor) {
1936 3
                    $docStyle->getFill()->getEndColor()->setARGB(self::readColor($style->fill->patternFill->bgColor, true));
1937
                }
1938
            }
1939
        }
1940
1941
        // border
1942 8
        if (isset($style->border)) {
1943 8
            $diagonalUp = self::boolean((string) $style->border['diagonalUp']);
1944 8
            $diagonalDown = self::boolean((string) $style->border['diagonalDown']);
1945 8
            if (!$diagonalUp && !$diagonalDown) {
1946 8
                $docStyle->getBorders()->setDiagonalDirection(\PhpOffice\PhpSpreadsheet\Style\Borders::DIAGONAL_NONE);
1947
            } elseif ($diagonalUp && !$diagonalDown) {
1948
                $docStyle->getBorders()->setDiagonalDirection(\PhpOffice\PhpSpreadsheet\Style\Borders::DIAGONAL_UP);
1949
            } elseif (!$diagonalUp && $diagonalDown) {
1950
                $docStyle->getBorders()->setDiagonalDirection(\PhpOffice\PhpSpreadsheet\Style\Borders::DIAGONAL_DOWN);
1951
            } else {
1952
                $docStyle->getBorders()->setDiagonalDirection(\PhpOffice\PhpSpreadsheet\Style\Borders::DIAGONAL_BOTH);
1953
            }
1954 8
            self::readBorder($docStyle->getBorders()->getLeft(), $style->border->left);
1955 8
            self::readBorder($docStyle->getBorders()->getRight(), $style->border->right);
1956 8
            self::readBorder($docStyle->getBorders()->getTop(), $style->border->top);
1957 8
            self::readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom);
1958 8
            self::readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal);
1959
        }
1960
1961
        // alignment
1962 8
        if (isset($style->alignment)) {
1963 8
            $docStyle->getAlignment()->setHorizontal((string) $style->alignment['horizontal']);
1964 8
            $docStyle->getAlignment()->setVertical((string) $style->alignment['vertical']);
1965
1966 8
            $textRotation = 0;
1967 8
            if ((int) $style->alignment['textRotation'] <= 90) {
1968 8
                $textRotation = (int) $style->alignment['textRotation'];
1969
            } elseif ((int) $style->alignment['textRotation'] > 90) {
1970
                $textRotation = 90 - (int) $style->alignment['textRotation'];
1971
            }
1972
1973 8
            $docStyle->getAlignment()->setTextRotation(intval($textRotation));
1974 8
            $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment['wrapText']));
1975 8
            $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment['shrinkToFit']));
1976 8
            $docStyle->getAlignment()->setIndent(intval((string) $style->alignment['indent']) > 0 ? intval((string) $style->alignment['indent']) : 0);
1977 8
            $docStyle->getAlignment()->setReadorder(intval((string) $style->alignment['readingOrder']) > 0 ? intval((string) $style->alignment['readingOrder']) : 0);
1978
        }
1979
1980
        // protection
1981 8
        if (isset($style->protection)) {
1982 8 View Code Duplication
            if (isset($style->protection['locked'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1983 2
                if (self::boolean((string) $style->protection['locked'])) {
1984
                    $docStyle->getProtection()->setLocked(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED);
1985
                } else {
1986 2
                    $docStyle->getProtection()->setLocked(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED);
1987
                }
1988
            }
1989
1990 8 View Code Duplication
            if (isset($style->protection['hidden'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1991
                if (self::boolean((string) $style->protection['hidden'])) {
1992
                    $docStyle->getProtection()->setHidden(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED);
1993
                } else {
1994
                    $docStyle->getProtection()->setHidden(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED);
1995
                }
1996
            }
1997
        }
1998
1999
        // top-level style settings
2000 8
        if (isset($style->quotePrefix)) {
2001 8
            $docStyle->setQuotePrefix($style->quotePrefix);
2002
        }
2003 8
    }
2004
2005 8
    private static function readBorder($docBorder, $eleBorder)
2006
    {
2007 8
        if (isset($eleBorder['style'])) {
2008 2
            $docBorder->setBorderStyle((string) $eleBorder['style']);
2009
        }
2010 8
        if (isset($eleBorder->color)) {
2011 2
            $docBorder->getColor()->setARGB(self::readColor($eleBorder->color));
2012
        }
2013 8
    }
2014
2015 3
    private function parseRichText($is = null)
2016
    {
2017 3
        $value = new \PhpOffice\PhpSpreadsheet\RichText();
2018
2019 3
        if (isset($is->t)) {
2020
            $value->createText(\PhpOffice\PhpSpreadsheet\Shared\StringHelper::controlCharacterOOXML2PHP((string) $is->t));
2021
        } else {
2022 3
            if (is_object($is->r)) {
2023 3
                foreach ($is->r as $run) {
2024 3
                    if (!isset($run->rPr)) {
2025 3
                        $objText = $value->createText(\PhpOffice\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...
2026
                    } else {
2027 3
                        $objText = $value->createTextRun(\PhpOffice\PhpSpreadsheet\Shared\StringHelper::controlCharacterOOXML2PHP((string) $run->t));
2028
2029 3 View Code Duplication
                        if (isset($run->rPr->rFont['val'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2030 3
                            $objText->getFont()->setName((string) $run->rPr->rFont['val']);
2031
                        }
2032 3
                        if (isset($run->rPr->sz['val'])) {
2033 3
                            $objText->getFont()->setSize((string) $run->rPr->sz['val']);
2034
                        }
2035 3
                        if (isset($run->rPr->color)) {
2036 3
                            $objText->getFont()->setColor(new \PhpOffice\PhpSpreadsheet\Style\Color(self::readColor($run->rPr->color)));
2037
                        }
2038 3 View Code Duplication
                        if ((isset($run->rPr->b['val']) && self::boolean((string) $run->rPr->b['val'])) ||
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2039 3
                            (isset($run->rPr->b) && !isset($run->rPr->b['val']))) {
2040 3
                            $objText->getFont()->setBold(true);
2041
                        }
2042 3 View Code Duplication
                        if ((isset($run->rPr->i['val']) && self::boolean((string) $run->rPr->i['val'])) ||
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2043 3
                            (isset($run->rPr->i) && !isset($run->rPr->i['val']))) {
2044 2
                            $objText->getFont()->setItalic(true);
2045
                        }
2046 3 View Code Duplication
                        if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign['val'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2047
                            $vertAlign = strtolower((string) $run->rPr->vertAlign['val']);
2048
                            if ($vertAlign == 'superscript') {
2049
                                $objText->getFont()->setSuperScript(true);
2050
                            }
2051
                            if ($vertAlign == 'subscript') {
2052
                                $objText->getFont()->setSubScript(true);
2053
                            }
2054
                        }
2055 3 View Code Duplication
                        if (isset($run->rPr->u) && !isset($run->rPr->u['val'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2056
                            $objText->getFont()->setUnderline(\PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE);
2057 3
                        } elseif (isset($run->rPr->u) && isset($run->rPr->u['val'])) {
2058 2
                            $objText->getFont()->setUnderline((string) $run->rPr->u['val']);
2059
                        }
2060 3 View Code Duplication
                        if ((isset($run->rPr->strike['val']) && self::boolean((string) $run->rPr->strike['val'])) ||
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
2061 3
                            (isset($run->rPr->strike) && !isset($run->rPr->strike['val']))) {
2062 3
                            $objText->getFont()->setStrikethrough(true);
2063
                        }
2064
                    }
2065
                }
2066
            }
2067
        }
2068
2069 3
        return $value;
2070
    }
2071
2072
    /**
2073
     * @param \PhpOffice\PhpSpreadsheet\Spreadsheet $excel
2074
     */
2075
    private function readRibbon(\PhpOffice\PhpSpreadsheet\Spreadsheet $excel, $customUITarget, $zip)
2076
    {
2077
        $baseDir = dirname($customUITarget);
2078
        $nameCustomUI = basename($customUITarget);
2079
        // get the xml file (ribbon)
2080
        $localRibbon = $this->getFromZipArchive($zip, $customUITarget);
2081
        $customUIImagesNames = [];
2082
        $customUIImagesBinaries = [];
2083
        // something like customUI/_rels/customUI.xml.rels
2084
        $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels';
2085
        $dataRels = $this->getFromZipArchive($zip, $pathRels);
2086
        if ($dataRels) {
2087
            // exists and not empty if the ribbon have some pictures (other than internal MSO)
2088
            $UIRels = simplexml_load_string(
2089
                $this->securityScan($dataRels),
2090
                'SimpleXMLElement',
2091
                \PhpOffice\PhpSpreadsheet\Settings::getLibXmlLoaderOptions()
2092
            );
2093
            if ($UIRels) {
2094
                // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image
2095
                foreach ($UIRels->Relationship as $ele) {
2096
                    if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
2097
                        // an image ?
2098
                        $customUIImagesNames[(string) $ele['Id']] = (string) $ele['Target'];
2099
                        $customUIImagesBinaries[(string) $ele['Target']] = $this->getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']);
2100
                    }
2101
                }
2102
            }
2103
        }
2104
        if ($localRibbon) {
2105
            $excel->setRibbonXMLData($customUITarget, $localRibbon);
2106
            if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) {
2107
                $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries);
2108
            } else {
2109
                $excel->setRibbonBinObjects(null);
2110
            }
2111
        } else {
2112
            $excel->setRibbonXMLData(null);
2113
            $excel->setRibbonBinObjects(null);
2114
        }
2115
    }
2116
2117 9
    private static function getArrayItem($array, $key = 0)
2118
    {
2119 9
        return isset($array[$key]) ? $array[$key] : null;
2120
    }
2121
2122 3
    private static function dirAdd($base, $add)
2123
    {
2124 3
        return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add");
2125
    }
2126
2127
    private static function toCSSArray($style)
2128
    {
2129
        $style = str_replace(["\r", "\n"], '', $style);
2130
2131
        $temp = explode(';', $style);
2132
        $style = [];
2133
        foreach ($temp as $item) {
2134
            $item = explode(':', $item);
2135
2136
            if (strpos($item[1], 'px') !== false) {
2137
                $item[1] = str_replace('px', '', $item[1]);
2138
            }
2139 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...
2140
                $item[1] = str_replace('pt', '', $item[1]);
2141
                $item[1] = \PhpOffice\PhpSpreadsheet\Shared\Font::fontSizeToPixels($item[1]);
2142
            }
2143 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...
2144
                $item[1] = str_replace('in', '', $item[1]);
2145
                $item[1] = \PhpOffice\PhpSpreadsheet\Shared\Font::inchSizeToPixels($item[1]);
2146
            }
2147 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...
2148
                $item[1] = str_replace('cm', '', $item[1]);
2149
                $item[1] = \PhpOffice\PhpSpreadsheet\Shared\Font::centimeterSizeToPixels($item[1]);
2150
            }
2151
2152
            $style[$item[0]] = $item[1];
2153
        }
2154
2155
        return $style;
2156
    }
2157
2158 8
    private static function boolean($value = null)
2159
    {
2160 8
        if (is_object($value)) {
2161 1
            $value = (string) $value;
2162
        }
2163 8
        if (is_numeric($value)) {
2164 6
            return (bool) $value;
2165
        }
2166
2167 8
        return $value === 'true' || $value === 'TRUE';
2168
    }
2169
}
2170