Completed
Pull Request — develop (#335)
by Franck
08:25
created

PowerPoint2007::loadRels()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 15
ccs 10
cts 10
cp 1
rs 9.2
cc 4
eloc 9
nc 4
nop 1
crap 4
1
<?php
2
/**
3
 * This file is part of PHPPresentation - A pure PHP library for reading and writing
4
 * presentations documents.
5
 *
6
 * PHPPresentation is free software distributed under the terms of the GNU Lesser
7
 * General Public License version 3 as published by the Free Software Foundation.
8
 *
9
 * For the full copyright and license information, please read the LICENSE
10
 * file that was distributed with this source code. For the full list of
11
 * contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors.
12
 *
13
 * @link        https://github.com/PHPOffice/PHPPresentation
14
 * @copyright   2009-2015 PHPPresentation contributors
15
 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16
 */
17
18
namespace PhpOffice\PhpPresentation\Reader;
19
20
use PhpOffice\PhpPresentation\DocumentLayout;
21
use PhpOffice\PhpPresentation\Shape\RichText;
22
use PhpOffice\PhpPresentation\Shape\RichText\Paragraph;
23
use PhpOffice\PhpPresentation\Shape\Table\Cell;
24
use PhpOffice\PhpPresentation\Slide;
25
use PhpOffice\PhpPresentation\Slide\AbstractSlide;
26
use PhpOffice\PhpPresentation\Shape\Placeholder;
27
use PhpOffice\PhpPresentation\Slide\Background\Image;
28
use PhpOffice\PhpPresentation\Slide\SlideLayout;
29
use PhpOffice\PhpPresentation\Slide\SlideMaster;
30
use PhpOffice\PhpPresentation\Shape\Drawing\Gd;
31
use PhpOffice\PhpPresentation\Style\Fill;
32
use PhpOffice\PhpPresentation\Style\SchemeColor;
33
use PhpOffice\PhpPresentation\Style\TextStyle;
34
use PhpOffice\Common\XMLReader;
35
use PhpOffice\Common\Drawing as CommonDrawing;
36
use PhpOffice\PhpPresentation\PhpPresentation;
37
use PhpOffice\PhpPresentation\Style\Bullet;
38
use PhpOffice\PhpPresentation\Style\Color;
39
use ZipArchive;
40
41
/**
42
 * Serialized format reader
43
 */
44
class PowerPoint2007 implements ReaderInterface
45
{
46
    /**
47
     * Output Object
48
     * @var PhpPresentation
49
     */
50
    protected $oPhpPresentation;
51
    /**
52
     * Output Object
53
     * @var \ZipArchive
54
     */
55
    protected $oZip;
56
    /**
57
     * @var array[]
58
     */
59
    protected $arrayRels = array();
60
    /**
61
     * @var SlideLayout[]
62
     */
63
    protected $arraySlideLayouts = array();
64
    /*
65
     * @var string
66
     */
67
    protected $filename;
68
    /*
69
     * @var string
70
     */
71
    protected $fileRels;
72
73
    /**
74
     * Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file?
75
     *
76
     * @param  string $pFilename
77
     * @throws \Exception
78
     * @return boolean
79
     */
80 2
    public function canRead($pFilename)
81
    {
82 2
        return $this->fileSupportsUnserializePhpPresentation($pFilename);
83
    }
84
85
    /**
86
     * Does a file support UnserializePhpPresentation ?
87
     *
88
     * @param  string $pFilename
89
     * @throws \Exception
90
     * @return boolean
91
     */
92 9
    public function fileSupportsUnserializePhpPresentation($pFilename = '')
93
    {
94
        // Check if file exists
95 9
        if (!file_exists($pFilename)) {
96 2
            throw new \Exception("Could not open " . $pFilename . " for reading! File does not exist.");
97
        }
98
99 7
        $oZip = new ZipArchive();
100
        // Is it a zip ?
101 7
        if ($oZip->open($pFilename) === true) {
102
            // Is it an OpenXML Document ?
103
            // Is it a Presentation ?
104 5
            if (is_array($oZip->statName('[Content_Types].xml')) && is_array($oZip->statName('ppt/presentation.xml'))) {
105 5
                return true;
106
            }
107
        }
108 3
        return false;
109
    }
110
111
    /**
112
     * Loads PhpPresentation Serialized file
113
     *
114
     * @param  string $pFilename
115
     * @return \PhpOffice\PhpPresentation\PhpPresentation
116
     * @throws \Exception
117
     */
118 6
    public function load($pFilename)
119
    {
120
        // Unserialize... First make sure the file supports it!
121 6
        if (!$this->fileSupportsUnserializePhpPresentation($pFilename)) {
122 1
            throw new \Exception("Invalid file format for PhpOffice\PhpPresentation\Reader\PowerPoint2007: " . $pFilename . ".");
123
        }
124
125 4
        return $this->loadFile($pFilename);
126
    }
127
128
    /**
129
     * Load PhpPresentation Serialized file
130
     *
131
     * @param  string $pFilename
132
     * @return \PhpOffice\PhpPresentation\PhpPresentation
133
     */
134 4
    protected function loadFile($pFilename)
135
    {
136 4
        $this->oPhpPresentation = new PhpPresentation();
137 4
        $this->oPhpPresentation->removeSlideByIndex();
138 4
        $this->oPhpPresentation->setAllMasterSlides(array());
139 4
        $this->filename = $pFilename;
140
141 4
        $this->oZip = new ZipArchive();
142 4
        $this->oZip->open($this->filename);
143 4
        $docPropsCore = $this->oZip->getFromName('docProps/core.xml');
144 4
        if ($docPropsCore !== false) {
145 4
            $this->loadDocumentProperties($docPropsCore);
146
        }
147
148 4
        $docPropsCustom = $this->oZip->getFromName('docProps/custom.xml');
149 4
        if ($docPropsCustom !== false) {
150 1
            $this->loadCustomProperties($docPropsCustom);
151
        }
152
153 4
        $pptViewProps = $this->oZip->getFromName('ppt/viewProps.xml');
154 4
        if ($pptViewProps !== false) {
155 4
            $this->loadViewProperties($pptViewProps);
156
        }
157
158 4
        $pptPresentation = $this->oZip->getFromName('ppt/presentation.xml');
159 4
        if ($pptPresentation !== false) {
160 4
            $this->loadDocumentLayout($pptPresentation);
161 4
            $this->loadSlides($pptPresentation);
162
        }
163
164 4
        return $this->oPhpPresentation;
165
    }
166
167
    /**
168
     * Read Document Layout
169
     * @param $sPart
170
     */
171 4
    protected function loadDocumentLayout($sPart)
172
    {
173 4
        $xmlReader = new XMLReader();
174 4
        if ($xmlReader->getDomFromString($sPart)) {
175 4
            foreach ($xmlReader->getElements('/p:presentation/p:sldSz') as $oElement) {
176 4
                $type = $oElement->getAttribute('type');
177 4
                $oLayout = $this->oPhpPresentation->getLayout();
178 4
                if ($type == DocumentLayout::LAYOUT_CUSTOM) {
179
                    $oLayout->setCX($oElement->getAttribute('cx'));
180
                    $oLayout->setCY($oElement->getAttribute('cy'));
181
                } else {
182 4
                    $oLayout->setDocumentLayout($type, true);
183 4
                    if ($oElement->getAttribute('cx') < $oElement->getAttribute('cy')) {
184 4
                        $oLayout->setDocumentLayout($type, false);
185
                    }
186
                }
187
            }
188
        }
189 4
    }
190
191
    /**
192
     * Read Document Properties
193
     * @param string $sPart
194
     */
195 4
    protected function loadDocumentProperties($sPart)
196
    {
197 4
        $xmlReader = new XMLReader();
198 4
        if ($xmlReader->getDomFromString($sPart)) {
199
            $arrayProperties = array(
200 4
                '/cp:coreProperties/dc:creator' => 'setCreator',
201
                '/cp:coreProperties/cp:lastModifiedBy' => 'setLastModifiedBy',
202
                '/cp:coreProperties/dc:title' => 'setTitle',
203
                '/cp:coreProperties/dc:description' => 'setDescription',
204
                '/cp:coreProperties/dc:subject' => 'setSubject',
205
                '/cp:coreProperties/cp:keywords' => 'setKeywords',
206
                '/cp:coreProperties/cp:category' => 'setCategory',
207
                '/cp:coreProperties/dcterms:created' => 'setCreated',
208
                '/cp:coreProperties/dcterms:modified' => 'setModified',
209
            );
210 4
            $oProperties = $this->oPhpPresentation->getDocumentProperties();
211 4
            foreach ($arrayProperties as $path => $property) {
212 4
                $oElement = $xmlReader->getElement($path);
213 4
                if ($oElement instanceof \DOMElement) {
214 4
                    if ($oElement->hasAttribute('xsi:type') && $oElement->getAttribute('xsi:type') == 'dcterms:W3CDTF') {
215 4
                        $oDateTime = new \DateTime();
216 4
                        $oDateTime->createFromFormat(\DateTime::W3C, $oElement->nodeValue);
217 4
                        $oProperties->{$property}($oDateTime->getTimestamp());
218
                    } else {
219 4
                        $oProperties->{$property}($oElement->nodeValue);
220
                    }
221
                }
222
            }
223
        }
224 4
    }
225
226
    /**
227
     * Read Custom Properties
228
     * @param string $sPart
229
     */
230 1
    protected function loadCustomProperties($sPart)
231
    {
232 1
        $xmlReader = new XMLReader();
233 1
        $sPart = str_replace(' xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"', '', $sPart);
234 1
        if ($xmlReader->getDomFromString($sPart)) {
235 1
            $pathMarkAsFinal = '/Properties/property[@pid="2"][@fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"][@name="_MarkAsFinal"]/vt:bool';
236 1
            if (is_object($oElement = $xmlReader->getElement($pathMarkAsFinal))) {
237 1
                if ($oElement->nodeValue == 'true') {
238 1
                    $this->oPhpPresentation->getPresentationProperties()->markAsFinal(true);
239
                }
240
            }
241
        }
242 1
    }
243
244
    /**
245
     * Read View Properties
246
     * @param string $sPart
247
     */
248 4
    protected function loadViewProperties($sPart)
249
    {
250 4
        $xmlReader = new XMLReader();
251 4
        if ($xmlReader->getDomFromString($sPart)) {
252 4
            $pathZoom = '/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx';
253 4
            $oElement = $xmlReader->getElement($pathZoom);
254 4
            if ($oElement instanceof \DOMElement) {
255 3
                if ($oElement->hasAttribute('d') && $oElement->hasAttribute('n')) {
256 3
                    $this->oPhpPresentation->getPresentationProperties()->setZoom($oElement->getAttribute('n') / $oElement->getAttribute('d'));
257
                }
258
            }
259
        }
260 4
    }
261
262
    /**
263
     * Extract all slides
264
     */
265 4
    protected function loadSlides($sPart)
266
    {
267 4
        $xmlReader = new XMLReader();
268 4
        if ($xmlReader->getDomFromString($sPart)) {
269 4
            $fileRels = 'ppt/_rels/presentation.xml.rels';
270 4
            $this->loadRels($fileRels);
271
            // Load the Masterslides
272 4
            $this->loadMasterSlides($xmlReader, $fileRels);
273
            // Continue with loading the slides
274 4
            foreach ($xmlReader->getElements('/p:presentation/p:sldIdLst/p:sldId') as $oElement) {
275 4
                $rId = $oElement->getAttribute('r:id');
276 4
                $pathSlide = isset($this->arrayRels[$fileRels][$rId]) ? $this->arrayRels[$fileRels][$rId]['Target'] : '';
277 4
                if (!empty($pathSlide)) {
278 4
                    $pptSlide = $this->oZip->getFromName('ppt/' . $pathSlide);
279 4
                    if ($pptSlide !== false) {
280 4
                        $this->loadRels('ppt/slides/_rels/' . basename($pathSlide) . '.rels');
281 4
                        $this->loadSlide($pptSlide, basename($pathSlide));
282
                    }
283
                }
284
            }
285
        }
286 4
    }
287
288
    /**
289
     * Extract all MasterSlides
290
     * @param XMLReader $xmlReader
291
     * @param string $fileRels
292
     */
293 4
    protected function loadMasterSlides(XMLReader $xmlReader, $fileRels)
294
    {
295
        // Get all the MasterSlide Id's from the presentation.xml file
296 4
        foreach ($xmlReader->getElements('/p:presentation/p:sldMasterIdLst/p:sldMasterId') as $oElement) {
297 4
            $rId = $oElement->getAttribute('r:id');
298
            // Get the path to the masterslide from the array with _rels files
299 4
            $pathMasterSlide = isset($this->arrayRels[$fileRels][$rId]) ?
300 4
                $this->arrayRels[$fileRels][$rId]['Target'] : '';
301 4
            if (!empty($pathMasterSlide)) {
302 4
                $pptMasterSlide = $this->oZip->getFromName('ppt/' . $pathMasterSlide);
303 4
                if ($pptMasterSlide !== false) {
304 4
                    $this->loadRels('ppt/slideMasters/_rels/' . basename($pathMasterSlide) . '.rels');
305 4
                    $this->loadMasterSlide($pptMasterSlide, basename($pathMasterSlide));
306
                }
307
            }
308
        }
309 4
    }
310
311
    /**
312
     * Extract data from slide
313
     * @param string $sPart
314
     * @param string $baseFile
315
     */
316 4
    protected function loadSlide($sPart, $baseFile)
317
    {
318 4
        $xmlReader = new XMLReader();
319 4
        if ($xmlReader->getDomFromString($sPart)) {
320
            // Core
321 4
            $oSlide = $this->oPhpPresentation->createSlide();
322 4
            $this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1);
323 4
            $oSlide->setRelsIndex('ppt/slides/_rels/' . $baseFile . '.rels');
324
325
            // Background
326 4
            $oElement = $xmlReader->getElement('/p:sld/p:cSld/p:bg/p:bgPr');
327 4
            if ($oElement instanceof \DOMElement) {
328
                $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
329
                if ($oElementColor instanceof \DOMElement) {
330
                    // Color
331
                    $oColor = new Color();
332
                    $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
333
                    // Background
334
                    $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Color();
335
                    $oBackground->setColor($oColor);
336
                    // Slide Background
337
                    $oSlide = $this->oPhpPresentation->getActiveSlide();
338
                    $oSlide->setBackground($oBackground);
339
                }
340
                $oElementImage = $xmlReader->getElement('a:blipFill/a:blip', $oElement);
341
                if ($oElementImage instanceof \DOMElement) {
342
                    $relImg = $this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'][$oElementImage->getAttribute('r:embed')];
343
                    if (is_array($relImg)) {
344
                        // File
345
                        $pathImage = 'ppt/slides/' . $relImg['Target'];
346
                        $pathImage = explode('/', $pathImage);
347
                        foreach ($pathImage as $key => $partPath) {
348
                            if ($partPath == '..') {
349
                                unset($pathImage[$key - 1]);
350
                                unset($pathImage[$key]);
351
                            }
352
                        }
353
                        $pathImage = implode('/', $pathImage);
354
                        $contentImg = $this->oZip->getFromName($pathImage);
355
356
                        $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
357
                        file_put_contents($tmpBkgImg, $contentImg);
358
                        // Background
359
                        $oBackground = new Image();
360
                        $oBackground->setPath($tmpBkgImg);
361
                        // Slide Background
362
                        $oSlide = $this->oPhpPresentation->getActiveSlide();
363
                        $oSlide->setBackground($oBackground);
364
                    }
365
                }
366
            }
367
368
            // Shapes
369 4
            $arrayElements = $xmlReader->getElements('/p:sld/p:cSld/p:spTree/*');
370 4
            if ($arrayElements) {
371 4
                $this->loadSlideShapes($oSlide, $arrayElements, $xmlReader);
372
            }
373
374
            // Layout
375 4
            $oSlide = $this->oPhpPresentation->getActiveSlide();
376 4
            foreach ($this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'] as $valueRel) {
377 4
                if ($valueRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout') {
378 4
                    $layoutBasename = basename($valueRel['Target']);
379 4
                    if (array_key_exists($layoutBasename, $this->arraySlideLayouts)) {
380 4
                        $oSlide->setSlideLayout($this->arraySlideLayouts[$layoutBasename]);
381
                    }
382 4
                    break;
383
                }
384
            }
385
        }
386 4
    }
387
388
    /**
389
     * @param string $baseFile
390
     */
391 4
    private function loadMasterSlide($sPart, $baseFile)
392
    {
393 4
        $xmlReader = new XMLReader();
394 4
        if ($xmlReader->getDomFromString($sPart)) {
395
            // Core
396 4
            $oSlideMaster = $this->oPhpPresentation->createMasterSlide();
397 4
            $oSlideMaster->setTextStyles(new TextStyle(false));
398 4
            $oSlideMaster->setRelsIndex('ppt/slideMasters/_rels/' . $baseFile . '.rels');
399
400
            // Background
401 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:cSld/p:bg');
402 4
            if ($oElement instanceof \DOMElement) {
403 4
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideMaster);
404
            }
405
406
            // Shapes
407 4
            $arrayElements = $xmlReader->getElements('/p:sldMaster/p:cSld/p:spTree/*');
408 4
            if ($arrayElements) {
409 4
                $this->loadSlideShapes($oSlideMaster, $arrayElements, $xmlReader);
410
            }
411
            // Header & Footer
412
413
            // ColorMapping
414 4
            $colorMap = array();
415 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:clrMap');
416 4
            if ($oElement->hasAttributes()) {
417 4
                foreach ($oElement->attributes as $attr) {
418 4
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
419
                }
420 4
                $oSlideMaster->colorMap->setMapping($colorMap);
421
            }
422
423
            // TextStyles
424 4
            $arrayElementTxStyles = $xmlReader->getElements('/p:sldMaster/p:txStyles/*');
425 4
            if ($arrayElementTxStyles) {
426 4
                foreach ($arrayElementTxStyles as $oElementTxStyle) {
427 4
                    $arrayElementsLvl = $xmlReader->getElements('/p:sldMaster/p:txStyles/' . $oElementTxStyle->nodeName . '/*');
428 4
                    foreach ($arrayElementsLvl as $oElementLvl) {
429 4
                        if ($oElementLvl->nodeName == 'a:extLst') {
430 1
                            continue;
431
                        }
432 4
                        $oRTParagraph = new Paragraph();
433
434 4
                        if ($oElementLvl->nodeName == 'a:defPPr') {
435 3
                            $level = 0;
436
                        } else {
437 4
                            $level = str_replace('a:lvl', '', $oElementLvl->nodeName);
438 4
                            $level = str_replace('pPr', '', $level);
439
                        }
440
441 4
                        if ($oElementLvl->hasAttribute('algn')) {
442 4
                            $oRTParagraph->getAlignment()->setHorizontal($oElementLvl->getAttribute('algn'));
443
                        }
444 4
                        if ($oElementLvl->hasAttribute('marL')) {
445 4
                            $val = $oElementLvl->getAttribute('marL');
446 4
                            $val = CommonDrawing::emuToPixels($val);
447 4
                            $oRTParagraph->getAlignment()->setMarginLeft($val);
448
                        }
449 4
                        if ($oElementLvl->hasAttribute('marR')) {
450
                            $val = $oElementLvl->getAttribute('marR');
451
                            $val = CommonDrawing::emuToPixels($val);
452
                            $oRTParagraph->getAlignment()->setMarginRight($val);
453
                        }
454 4
                        if ($oElementLvl->hasAttribute('indent')) {
455 4
                            $val = $oElementLvl->getAttribute('indent');
456 4
                            $val = CommonDrawing::emuToPixels($val);
457 4
                            $oRTParagraph->getAlignment()->setIndent($val);
458
                        }
459 4
                        $oElementLvlDefRPR = $xmlReader->getElement('a:defRPr', $oElementLvl);
460 4
                        if ($oElementLvlDefRPR instanceof \DOMElement) {
461 4
                            if ($oElementLvlDefRPR->hasAttribute('sz')) {
462 4
                                $oRTParagraph->getFont()->setSize($oElementLvlDefRPR->getAttribute('sz') / 100);
463
                            }
464 4
                            if ($oElementLvlDefRPR->hasAttribute('b') && $oElementLvlDefRPR->getAttribute('b') == 1) {
465 1
                                $oRTParagraph->getFont()->setBold(true);
466
                            }
467 4
                            if ($oElementLvlDefRPR->hasAttribute('i') && $oElementLvlDefRPR->getAttribute('i') == 1) {
468
                                $oRTParagraph->getFont()->setItalic(true);
469
                            }
470
                        }
471 4
                        $oElementSchemeColor = $xmlReader->getElement('a:defRPr/a:solidFill/a:schemeClr', $oElementLvl);
472 4
                        if ($oElementSchemeColor instanceof \DOMElement) {
473 4
                            if ($oElementSchemeColor->hasAttribute('val')) {
474 4
                                $oSchemeColor = new SchemeColor();
475 4
                                $oSchemeColor->setValue($oElementSchemeColor->getAttribute('val'));
476 4
                                $oRTParagraph->getFont()->setColor($oSchemeColor);
477
                            }
478
                        }
479
480 4
                        switch ($oElementTxStyle->nodeName) {
481 4
                            case 'p:bodyStyle':
482 4
                                $oSlideMaster->getTextStyles()->setBodyStyleAtLvl($oRTParagraph, $level);
483 4
                                break;
484 4
                            case 'p:otherStyle':
485 4
                                $oSlideMaster->getTextStyles()->setOtherStyleAtLvl($oRTParagraph, $level);
486 4
                                break;
487 4
                            case 'p:titleStyle':
488 4
                                $oSlideMaster->getTextStyles()->setTitleStyleAtLvl($oRTParagraph, $level);
489 4
                                break;
490
                        }
491
                    }
492
                }
493
            }
494
495
            // Load the theme
496 4
            foreach ($this->arrayRels[$oSlideMaster->getRelsIndex()] as $arrayRel) {
497 4
                if ($arrayRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') {
498 4
                    $pptTheme = $this->oZip->getFromName('ppt/' . substr($arrayRel['Target'], strrpos($arrayRel['Target'], '../') + 3));
499 4
                    if ($pptTheme !== false) {
500 4
                        $this->loadTheme($pptTheme, $oSlideMaster);
501
                    }
502 4
                    break;
503
                }
504
            }
505
506
            // Load the Layoutslide
507 4
            foreach ($xmlReader->getElements('/p:sldMaster/p:sldLayoutIdLst/p:sldLayoutId') as $oElement) {
508 4
                $rId = $oElement->getAttribute('r:id');
509
                // Get the path to the masterslide from the array with _rels files
510 4
                $pathLayoutSlide = isset($this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]) ?
511 4
                    $this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]['Target'] : '';
512 4
                if (!empty($pathLayoutSlide)) {
513 4
                    $pptLayoutSlide = $this->oZip->getFromName('ppt/' . substr($pathLayoutSlide, strrpos($pathLayoutSlide, '../') + 3));
514 4
                    if ($pptLayoutSlide !== false) {
515 4
                        $this->loadRels('ppt/slideLayouts/_rels/' . basename($pathLayoutSlide) . '.rels');
516 4
                        $oSlideMaster->addSlideLayout(
517 4
                            $this->loadLayoutSlide($pptLayoutSlide, basename($pathLayoutSlide), $oSlideMaster)
518
                        );
519
                    }
520
                }
521
            }
522
        }
523 4
    }
524
525
    /**
526
     * @param string $sPart
527
     * @param string $baseFile
528
     * @param SlideMaster $oSlideMaster
529
     */
530 4
    private function loadLayoutSlide($sPart, $baseFile, SlideMaster $oSlideMaster)
531
    {
532 4
        $xmlReader = new XMLReader();
533 4
        if ($xmlReader->getDomFromString($sPart)) {
534
            // Core
535 4
            $oSlideLayout = new SlideLayout($oSlideMaster);
536 4
            $oSlideLayout->setRelsIndex('ppt/slideLayouts/_rels/' . $baseFile . '.rels');
537
538
            // Name
539 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld');
540 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttribute('name')) {
541 4
                $oSlideLayout->setLayoutName($oElement->getAttribute('name'));
542
            }
543
544
            // Background
545 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld/p:bg');
546 4
            if ($oElement instanceof \DOMElement) {
547 1
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideLayout);
548
            }
549
550
            // ColorMapping
551 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:clrMapOvr/a:overrideClrMapping');
552 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttributes()) {
553 1
                $colorMap = array();
554 1
                foreach ($oElement->attributes as $attr) {
555 1
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
556
                }
557 1
                $oSlideLayout->colorMap->setMapping($colorMap);
558
            }
559
560
            // Shapes
561 4
            $oElements = $xmlReader->getElements('/p:sldLayout/p:cSld/p:spTree/*');
562 4
            if ($oElements) {
563 4
                $this->loadSlideShapes($oSlideLayout, $oElements, $xmlReader);
564
            }
565 4
            $this->arraySlideLayouts[$baseFile] = &$oSlideLayout;
566 4
            return $oSlideLayout;
567
        }
568
        return null;
569
    }
570
571
    /**
572
     * @param string $sPart
573
     * @param SlideMaster $oSlideMaster
574
     */
575 4
    private function loadTheme($sPart, SlideMaster $oSlideMaster)
576
    {
577 4
        $xmlReader = new XMLReader();
578 4
        if ($xmlReader->getDomFromString($sPart)) {
579 4
            $oElements = $xmlReader->getElements('/a:theme/a:themeElements/a:clrScheme/*');
580 4
            if ($oElements) {
581 4
                foreach ($oElements as $oElement) {
582 4
                    $oSchemeColor = new SchemeColor();
583 4
                    $oSchemeColor->setValue(str_replace('a:', '', $oElement->tagName));
584 4
                    $colorElement = $xmlReader->getElement('*', $oElement);
585 4
                    if ($colorElement instanceof \DOMElement) {
586 4
                        if ($colorElement->hasAttribute('lastClr')) {
587 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('lastClr'));
588 4
                        } elseif ($colorElement->hasAttribute('val')) {
589 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('val'));
590
                        }
591
                    }
592 4
                    $oSlideMaster->addSchemeColor($oSchemeColor);
593
                }
594
            }
595
        }
596 4
    }
597
598
    /**
599
     * @param XMLReader $xmlReader
600
     * @param \DOMElement $oElement
601
     * @param AbstractSlide $oSlide
602
     */
603 4
    private function loadSlideBackground(XMLReader $xmlReader, \DOMElement $oElement, AbstractSlide $oSlide)
604
    {
605
        // Background color
606 4
        $oElementColor = $xmlReader->getElement('p:bgPr/a:solidFill/a:srgbClr', $oElement);
607 4
        if ($oElementColor instanceof \DOMElement) {
608
            // Color
609
            $oColor = new Color();
610
            $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
611
            // Background
612
            $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Color();
613
            $oBackground->setColor($oColor);
614
            // Slide Background
615
            $oSlide->setBackground($oBackground);
616
        }
617
618
        // Background scheme color
619 4
        $oElementSchemeColor = $xmlReader->getElement('p:bgRef/a:schemeClr', $oElement);
620 4
        if ($oElementSchemeColor instanceof \DOMElement) {
621
            // Color
622 4
            $oColor = new SchemeColor();
623 4
            $oColor->setValue($oElementSchemeColor->hasAttribute('val') ? $oElementSchemeColor->getAttribute('val') : null);
624
            // Background
625 4
            $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\SchemeColor();
626 4
            $oBackground->setSchemeColor($oColor);
627
            // Slide Background
628 4
            $oSlide->setBackground($oBackground);
629
        }
630
631
        // Background image
632 4
        $oElementImage = $xmlReader->getElement('p:bgPr/a:blipFill/a:blip', $oElement);
633 4
        if ($oElementImage instanceof \DOMElement) {
634
            $relImg = $this->arrayRels[$oSlide->getRelsIndex()][$oElementImage->getAttribute('r:embed')];
635
            if (is_array($relImg)) {
636
                // File
637
                $pathImage = 'ppt/slides/' . $relImg['Target'];
638
                $pathImage = explode('/', $pathImage);
639
                foreach ($pathImage as $key => $partPath) {
640
                    if ($partPath == '..') {
641
                        unset($pathImage[$key - 1]);
642
                        unset($pathImage[$key]);
643
                    }
644
                }
645
                $pathImage = implode('/', $pathImage);
646
                $contentImg = $this->oZip->getFromName($pathImage);
647
648
                $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
649
                file_put_contents($tmpBkgImg, $contentImg);
650
                // Background
651
                $oBackground = new Image();
652
                $oBackground->setPath($tmpBkgImg);
653
                // Slide Background
654
                $oSlide->setBackground($oBackground);
655
            }
656
        }
657 4
    }
658
659
    /**
660
     * @param XMLReader $document
661
     * @param \DOMElement $node
662
     * @param AbstractSlide $oSlide
663
     */
664 3
    protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
665
    {
666
        // Core
667 3
        $oShape = new Gd();
668 3
        $oShape->getShadow()->setVisible(false);
669
        // Variables
670 3
        $fileRels = $oSlide->getRelsIndex();
671
672 3
        $oElement = $document->getElement('p:nvPicPr/p:cNvPr', $node);
673 3
        if ($oElement instanceof \DOMElement) {
674 3
            $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : '');
675 3
            $oShape->setDescription($oElement->hasAttribute('descr') ? $oElement->getAttribute('descr') : '');
676
        }
677
678 3
        $oElement = $document->getElement('p:blipFill/a:blip', $node);
679 3
        if ($oElement instanceof \DOMElement) {
680 3
            if ($oElement->hasAttribute('r:embed') && isset($this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'])) {
681 3
                $pathImage = 'ppt/slides/' . $this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'];
682 3
                $pathImage = explode('/', $pathImage);
683 3
                foreach ($pathImage as $key => $partPath) {
684 3
                    if ($partPath == '..') {
685 3
                        unset($pathImage[$key - 1]);
686 3
                        unset($pathImage[$key]);
687
                    }
688
                }
689 3
                $pathImage = implode('/', $pathImage);
690 3
                $imageFile = $this->oZip->getFromName($pathImage);
691 3
                if (!empty($imageFile)) {
692 3
                    $oShape->setImageResource(imagecreatefromstring($imageFile));
693
                }
694
            }
695
        }
696
697 3
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
698 3
        if ($oElement instanceof \DOMElement) {
699 3
            if ($oElement->hasAttribute('rot')) {
700 3
                $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
701
            }
702
        }
703
704 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
705 3
        if ($oElement instanceof \DOMElement) {
706 3
            if ($oElement->hasAttribute('x')) {
707 3
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
708
            }
709 3
            if ($oElement->hasAttribute('y')) {
710 3
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
711
            }
712
        }
713
714 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
715 3
        if ($oElement instanceof \DOMElement) {
716 3
            if ($oElement->hasAttribute('cx')) {
717 3
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
718
            }
719 3
            if ($oElement->hasAttribute('cy')) {
720 3
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
721
            }
722
        }
723
724 3
        $oElement = $document->getElement('p:spPr/a:effectLst', $node);
725 3
        if ($oElement instanceof \DOMElement) {
726 3
            $oShape->getShadow()->setVisible(true);
727
728 3
            $oSubElement = $document->getElement('a:outerShdw', $oElement);
729 3
            if ($oSubElement instanceof \DOMElement) {
730 3
                if ($oSubElement->hasAttribute('blurRad')) {
731 3
                    $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels($oSubElement->getAttribute('blurRad')));
732
                }
733 3
                if ($oSubElement->hasAttribute('dist')) {
734 3
                    $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels($oSubElement->getAttribute('dist')));
735
                }
736 3
                if ($oSubElement->hasAttribute('dir')) {
737 3
                    $oShape->getShadow()->setDirection(CommonDrawing::angleToDegrees($oSubElement->getAttribute('dir')));
738
                }
739 3
                if ($oSubElement->hasAttribute('algn')) {
740 3
                    $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn'));
741
                }
742
            }
743
744 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement);
745 3
            if ($oSubElement instanceof \DOMElement) {
746 3
                if ($oSubElement->hasAttribute('val')) {
747 3
                    $oColor = new Color();
748 3
                    $oColor->setRGB($oSubElement->getAttribute('val'));
749 3
                    $oShape->getShadow()->setColor($oColor);
750
                }
751
            }
752
753 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement);
754 3
            if ($oSubElement instanceof \DOMElement) {
755 3
                if ($oSubElement->hasAttribute('val')) {
756 3
                    $oShape->getShadow()->setAlpha((int)$oSubElement->getAttribute('val') / 1000);
757
                }
758
            }
759
        }
760
761 3
        $oSlide->addShape($oShape);
762 3
    }
763
764
    /**
765
     * @param XMLReader $document
766
     * @param \DOMElement $node
767
     * @param AbstractSlide $oSlide
768
     * @throws \Exception
769
     */
770 4
    protected function loadShapeRichText(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
771
    {
772
        // Core
773 4
        $oShape = $oSlide->createRichTextShape();
774 4
        $oShape->setParagraphs(array());
775
        // Variables
776 4
        $this->fileRels = $oSlide->getRelsIndex();
777
778 4
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
779 4
        if ($oElement instanceof \DOMElement && $oElement->hasAttribute('rot')) {
780 4
            $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
781
        }
782
783 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
784 4
        if ($oElement instanceof \DOMElement) {
785 4
            if ($oElement->hasAttribute('x')) {
786 4
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
787
            }
788 4
            if ($oElement->hasAttribute('y')) {
789 4
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
790
            }
791
        }
792
793 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
794 4
        if ($oElement instanceof \DOMElement) {
795 4
            if ($oElement->hasAttribute('cx')) {
796 4
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
797
            }
798 4
            if ($oElement->hasAttribute('cy')) {
799 4
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
800
            }
801
        }
802
803 4
        $oElement = $document->getElement('p:nvSpPr/p:nvPr/p:ph', $node);
804 4
        if ($oElement instanceof \DOMElement) {
805 4
            if ($oElement->hasAttribute('type')) {
806 4
                $placeholder = new Placeholder($oElement->getAttribute('type'));
807 4
                $oShape->setPlaceHolder($placeholder);
808
            }
809
        }
810
811 4
        $arrayElements = $document->getElements('p:txBody/a:p', $node);
812 4
        foreach ($arrayElements as $oElement) {
813 4
            $this->loadParagraph($document, $oElement, $oShape);
814
        }
815
816 4
        if (count($oShape->getParagraphs()) > 0) {
817 4
            $oShape->setActiveParagraph(0);
818
        }
819 4
    }
820
821
    /**
822
     * @param XMLReader $document
823
     * @param \DOMElement $oElement
824
     * @param Cell|RichText $oShape
825
     * @throws \Exception
826
     */
827 4
    protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oShape) {
828
        // Core
829 4
        $oParagraph = $oShape->createParagraph();
830 4
        $oParagraph->setRichTextElements(array());
831
832 4
        $oSubElement = $document->getElement('a:pPr', $oElement);
833 4
        if ($oSubElement instanceof \DOMElement) {
834 4
            if ($oSubElement->hasAttribute('algn')) {
835 4
                $oParagraph->getAlignment()->setHorizontal($oSubElement->getAttribute('algn'));
836
            }
837 4
            if ($oSubElement->hasAttribute('fontAlgn')) {
838 3
                $oParagraph->getAlignment()->setVertical($oSubElement->getAttribute('fontAlgn'));
839
            }
840 4
            if ($oSubElement->hasAttribute('marL')) {
841 4
                $oParagraph->getAlignment()->setMarginLeft(CommonDrawing::emuToPixels($oSubElement->getAttribute('marL')));
842
            }
843 4
            if ($oSubElement->hasAttribute('marR')) {
844 3
                $oParagraph->getAlignment()->setMarginRight(CommonDrawing::emuToPixels($oSubElement->getAttribute('marR')));
845
            }
846 4
            if ($oSubElement->hasAttribute('indent')) {
847 3
                $oParagraph->getAlignment()->setIndent(CommonDrawing::emuToPixels($oSubElement->getAttribute('indent')));
848
            }
849 4
            if ($oSubElement->hasAttribute('lvl')) {
850 4
                $oParagraph->getAlignment()->setLevel($oSubElement->getAttribute('lvl'));
851
            }
852
853 4
            $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NONE);
854
855 4
            $oElementBuFont = $document->getElement('a:buFont', $oSubElement);
856 4
            if ($oElementBuFont instanceof \DOMElement) {
857 3
                if ($oElementBuFont->hasAttribute('typeface')) {
858 3
                    $oParagraph->getBulletStyle()->setBulletFont($oElementBuFont->getAttribute('typeface'));
859
                }
860
            }
861 4
            $oElementBuChar = $document->getElement('a:buChar', $oSubElement);
862 4
            if ($oElementBuChar instanceof \DOMElement) {
863 3
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET);
864 3
                if ($oElementBuChar->hasAttribute('char')) {
865 3
                    $oParagraph->getBulletStyle()->setBulletChar($oElementBuChar->getAttribute('char'));
866
                }
867
            }
868 4
            $oElementBuAutoNum = $document->getElement('a:buAutoNum', $oSubElement);
869 4
            if ($oElementBuAutoNum instanceof \DOMElement) {
870
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NUMERIC);
871
                if ($oElementBuAutoNum->hasAttribute('type')) {
872
                    $oParagraph->getBulletStyle()->setBulletNumericStyle($oElementBuAutoNum->getAttribute('type'));
873
                }
874
                if ($oElementBuAutoNum->hasAttribute('startAt') && $oElementBuAutoNum->getAttribute('startAt') != 1) {
875
                    $oParagraph->getBulletStyle()->setBulletNumericStartAt($oElementBuAutoNum->getAttribute('startAt'));
876
                }
877
            }
878 4
            $oElementBuClr = $document->getElement('a:buClr', $oSubElement);
879 4
            if ($oElementBuClr instanceof \DOMElement) {
880
                $oColor = new Color();
881
                /**
882
                 * @todo Create protected for reading Color
883
                 */
884
                $oElementColor = $document->getElement('a:srgbClr', $oElementBuClr);
885
                if ($oElementColor instanceof \DOMElement) {
886
                    $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
887
                }
888
                $oParagraph->getBulletStyle()->setBulletColor($oColor);
889
            }
890
        }
891 4
        $arraySubElements = $document->getElements('(a:r|a:br)', $oElement);
892 4
        foreach ($arraySubElements as $oSubElement) {
893 4
            if ($oSubElement->tagName == 'a:br') {
894 3
                $oParagraph->createBreak();
895
            }
896 4
            if ($oSubElement->tagName == 'a:r') {
897 4
                $oElementrPr = $document->getElement('a:rPr', $oSubElement);
898 4
                if (is_object($oElementrPr)) {
899 4
                    $oText = $oParagraph->createTextRun();
900
901 4
                    if ($oElementrPr->hasAttribute('b')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
902 3
                        $oText->getFont()->setBold($oElementrPr->getAttribute('b') == 'true' ? true : false);
903
                    }
904 4
                    if ($oElementrPr->hasAttribute('i')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
905 3
                        $oText->getFont()->setItalic($oElementrPr->getAttribute('i') == 'true' ? true : false);
906
                    }
907 4
                    if ($oElementrPr->hasAttribute('strike')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
908 3
                        $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true);
909
                    }
910 4
                    if ($oElementrPr->hasAttribute('sz')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
911 3
                        $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100));
912
                    }
913 4
                    if ($oElementrPr->hasAttribute('u')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
914 3
                        $oText->getFont()->setUnderline($oElementrPr->getAttribute('u'));
915
                    }
916
                    // Color
917 4
                    $oElementSrgbClr = $document->getElement('a:solidFill/a:srgbClr', $oElementrPr);
0 ignored issues
show
Documentation introduced by
$oElementrPr is of type object<DOMNode>, but the function expects a null|object<DOMElement>.

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...
918 4
                    if (is_object($oElementSrgbClr) && $oElementSrgbClr->hasAttribute('val')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
919 3
                        $oColor = new Color();
920 3
                        $oColor->setRGB($oElementSrgbClr->getAttribute('val'));
921 3
                        $oText->getFont()->setColor($oColor);
922
                    }
923
                    // Hyperlink
924 4
                    $oElementHlinkClick = $document->getElement('a:hlinkClick', $oElementrPr);
0 ignored issues
show
Documentation introduced by
$oElementrPr is of type object<DOMNode>, but the function expects a null|object<DOMElement>.

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...
925 4
                    if (is_object($oElementHlinkClick)) {
926 3
                        if ($oElementHlinkClick->hasAttribute('tooltip')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
927 3
                            $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip'));
928
                        }
929 3
                        if ($oElementHlinkClick->hasAttribute('r:id') && isset($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target'])) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
930 3
                            $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']);
931
                        }
932
                    }
933
                    //} else {
934
                    // $oText = $oParagraph->createText();
935
936 4
                    $oSubSubElement = $document->getElement('a:t', $oSubElement);
937 4
                    $oText->setText($oSubSubElement->nodeValue);
938
                }
939
            }
940
        }
941 4
    }
942
943
    /**
944
     * @param XMLReader $document
945
     * @param \DOMElement $node
946
     * @param AbstractSlide $oSlide
947
     * @throws \Exception
948
     */
949
    protected function loadShapeTable(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
950
    {
951
        $this->fileRels = $oSlide->getRelsIndex();
952
953
        $oShape = $oSlide->createTableShape();
954
955
        $oElement = $document->getElement('p:cNvPr', $node);
956
        if ($oElement instanceof \DOMElement) {
957
            if ($oElement->hasAttribute('name')) {
958
                $oShape->setName($oElement->getAttribute('name'));
959
            }
960
            if ($oElement->hasAttribute('descr')) {
961
                $oShape->setDescription($oElement->getAttribute('descr'));
962
            }
963
        }
964
965
        $oElement = $document->getElement('p:xfrm/a:off', $node);
966
        if ($oElement instanceof \DOMElement) {
967
            if ($oElement->hasAttribute('x')) {
968
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
969
            }
970
            if ($oElement->hasAttribute('y')) {
971
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
972
            }
973
        }
974
975
        $oElement = $document->getElement('p:xfrm/a:ext', $node);
976
        if ($oElement instanceof \DOMElement) {
977
            if ($oElement->hasAttribute('cx')) {
978
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
979
            }
980
            if ($oElement->hasAttribute('cy')) {
981
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
982
            }
983
        }
984
985
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tblGrid/a:gridCol', $node);
986
        $oShape->setNumColumn($arrayElements->length);
987
        $oShape->createRow();
988
        foreach ($arrayElements as $key => $oElement) {
989
            if ($oElement instanceof \DOMElement && $oElement->getAttribute('w')) {
990
                $oShape->getRow(0)->getCell($key)->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('w')));
991
            }
992
        }
993
994
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tr', $node);
995
        foreach ($arrayElements as $keyRow => $oElementRow) {
996
            if (!($oElementRow instanceof \DOMElement)) {
997
                continue;
998
            }
999
            $oRow = $oShape->getRow($keyRow, true);
1000
            if (is_null($oRow)) {
1001
                $oRow = $oShape->createRow();
1002
            }
1003
            if ($oElementRow->hasAttribute('h')) {
1004
                $oRow->setHeight(CommonDrawing::emuToPixels($oElementRow->getAttribute('h')));
1005
            }
1006
            $arrayElementsCell = $document->getElements('a:tc', $oElementRow);
1007
            foreach ($arrayElementsCell as $keyCell => $oElementCell) {
1008
                if (!($oElementCell instanceof \DOMElement)) {
1009
                    continue;
1010
                }
1011
                $oCell = $oRow->getCell($keyCell);
1012
                if ($oElementCell->hasAttribute('gridSpan')) {
1013
                    $oCell->setColSpan($oElementCell->getAttribute('gridSpan'));
1014
                }
1015
                if ($oElementCell->hasAttribute('rowSpan')) {
1016
                    $oCell->setRowSpan($oElementCell->getAttribute('rowSpan'));
1017
                }
1018
1019
                foreach ($document->getElements('a:txBody/a:p', $oElementCell) as $oElementPara) {
1020
                    $this->loadParagraph($document, $oElementPara, $oCell);
0 ignored issues
show
Bug introduced by
It seems like $oCell defined by $oRow->getCell($keyCell) on line 1011 can be null; however, PhpOffice\PhpPresentatio...nt2007::loadParagraph() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
1021
                }
1022
1023
                $oElementTcPr = $document->getElement('a:tcPr', $oElementCell);
1024
                if ($oElementTcPr instanceof \DOMElement) {
1025
                    $oFill = $this->loadStyleFill($document, $oElementTcPr, $oSlide);
1026
                    if ($oFill instanceof Fill) {
1027
                        $oCell->setFill($oFill);
1028
                    }
1029
                }
1030
            }
1031
        }
1032
    }
1033
1034
    /**
1035
     * @param XMLReader $xmlReader
1036
     * @param \DOMElement $oElement
1037
     * @param AbstractSlide $oSlide
1038
     * @return null|Fill
1039
     */
1040
    protected function loadStyleFill(XMLReader $xmlReader, \DOMElement $oElement, AbstractSlide $oSlide)
0 ignored issues
show
Unused Code introduced by
The parameter $oSlide is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1041
    {
1042
        // Gradient fill
1043
        $oElementFill = $xmlReader->getElement('a:gradFill', $oElement);
1044
        if ($oElementFill instanceof \DOMElement) {
1045
            $oFill = new Fill();
1046
            $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR);
1047
1048
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill);
1049
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1050
                $oFill->getStartColor()->setRGB($oElementColor->getAttribute('val'));
1051
                $oElementAlpha = $xmlReader->getElement('a:alpha', $oElementColor);
1052
                if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1053
                    $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1054
                    $oFill->getStartColor()->setRGB($oElementColor->getAttribute('val'), $alpha);
1055
                }
1056
            }
1057
1058
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill);
1059
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1060
                $oFill->getEndColor()->setRGB($oElementColor->getAttribute('val'));
1061
                $oElementAlpha = $xmlReader->getElement('a:alpha', $oElementColor);
1062
                if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1063
                    $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1064
                    $oFill->getEndColor()->setRGB($oElementColor->getAttribute('val'), $alpha);
1065
                }
1066
            }
1067
1068
            $oRotation = $xmlReader->getElement('a:lin', $oElementFill);
1069
            if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) {
1070
                $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang')));
1071
            }
1072
            return $oFill;
1073
        }
1074
1075
        // Solid fill
1076
        $oElementFill = $xmlReader->getElement('a:solidFill', $oElement);
1077
        if ($oElementFill instanceof \DOMElement) {
1078
            $oFill = new Fill();
1079
            $oFill->setFillType(Fill::FILL_SOLID);
1080
1081
            $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill);
1082
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1083
                $oFill->getStartColor()->setRGB($oElementColor->getAttribute('val'));
1084
                $oElementAlpha = $xmlReader->getElement('a:alpha', $oElementColor);
1085
                if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1086
                    $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1087
                    $oFill->getStartColor()->setRGB($oElementColor->getAttribute('val'), $alpha);
1088
                }
1089
            }
1090
            return $oFill;
1091
        }
1092
        return null;
1093
    }
1094
1095
    /**
1096
     *
1097
     * @param string $fileRels
1098
     * @return string
1099
     */
1100 4
    protected function loadRels($fileRels)
1101
    {
1102 4
        $sPart = $this->oZip->getFromName($fileRels);
1103 4
        if ($sPart !== false) {
1104 4
            $xmlReader = new XMLReader();
1105 4
            if ($xmlReader->getDomFromString($sPart)) {
1106 4
                foreach ($xmlReader->getElements('*') as $oNode) {
1107 4
                    $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array(
1108 4
                        'Target' => $oNode->getAttribute('Target'),
1109 4
                        'Type' => $oNode->getAttribute('Type'),
1110
                    );
1111
                }
1112
            }
1113
        }
1114 4
    }
1115
1116
    /**
1117
     * @param $oSlide
1118
     * @param \DOMNodeList $oElements
1119
     * @param XMLReader $xmlReader
1120
     * @internal param $baseFile
1121
     */
1122 4
    private function loadSlideShapes($oSlide, $oElements, $xmlReader)
1123
    {
1124 4
        foreach ($oElements as $oNode) {
1125 4
            switch ($oNode->tagName) {
1126 4
                case 'p:graphicFrame':
1127
                    $this->loadShapeTable($xmlReader, $oNode, $oSlide);
1128
                    break;
1129 4
                case 'p:pic':
1130 3
                    $this->loadShapeDrawing($xmlReader, $oNode, $oSlide);
1131 3
                    break;
1132 4
                case 'p:sp':
1133 4
                    $this->loadShapeRichText($xmlReader, $oNode, $oSlide);
1134 4
                    break;
1135 4
                default:
1136
                    //var_export($oNode->tagName);
1137
            }
1138
        }
1139 4
    }
1140
}
1141