Completed
Pull Request — develop (#337)
by Franck
07:31
created

PowerPoint2007::loadRels()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5.0144

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
ccs 11
cts 12
cp 0.9167
rs 8.8571
cc 5
eloc 11
nc 5
nop 1
crap 5.0144
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\PhpPresentation;
22
use PhpOffice\PhpPresentation\Shape\Placeholder;
23
use PhpOffice\PhpPresentation\Shape\RichText;
24
use PhpOffice\PhpPresentation\Shape\RichText\Paragraph;
25
use PhpOffice\PhpPresentation\Shape\Table\Cell;
26
use PhpOffice\PhpPresentation\Slide;
27
use PhpOffice\PhpPresentation\Slide\AbstractSlide;
28
use PhpOffice\PhpPresentation\Slide\SlideLayout;
29
use PhpOffice\PhpPresentation\Slide\SlideMaster;
30
use PhpOffice\PhpPresentation\Shape\Drawing\Gd;
31
use PhpOffice\PhpPresentation\Style\Bullet;
32
use PhpOffice\PhpPresentation\Style\Border;
33
use PhpOffice\PhpPresentation\Style\Borders;
34
use PhpOffice\PhpPresentation\Style\Color;
35
use PhpOffice\PhpPresentation\Style\Fill;
36
use PhpOffice\PhpPresentation\Style\SchemeColor;
37
use PhpOffice\PhpPresentation\Style\TextStyle;
38
use PhpOffice\Common\XMLReader;
39
use PhpOffice\Common\Drawing as CommonDrawing;
40
use ZipArchive;
41
42
/**
43
 * Serialized format reader
44
 */
45
class PowerPoint2007 implements ReaderInterface
46
{
47
    /**
48
     * Output Object
49
     * @var PhpPresentation
50
     */
51
    protected $oPhpPresentation;
52
    /**
53
     * Output Object
54
     * @var \ZipArchive
55
     */
56
    protected $oZip;
57
    /**
58
     * @var array[]
59
     */
60
    protected $arrayRels = array();
61
    /**
62
     * @var SlideLayout[]
63
     */
64
    protected $arraySlideLayouts = array();
65
    /*
66
     * @var string
67
     */
68
    protected $filename;
69
    /*
70
     * @var string
71
     */
72
    protected $fileRels;
73
74
    /**
75
     * Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file?
76
     *
77
     * @param  string $pFilename
78
     * @throws \Exception
79
     * @return boolean
80
     */
81 2
    public function canRead($pFilename)
82
    {
83 2
        return $this->fileSupportsUnserializePhpPresentation($pFilename);
84
    }
85
86
    /**
87
     * Does a file support UnserializePhpPresentation ?
88
     *
89
     * @param  string $pFilename
90
     * @throws \Exception
91
     * @return boolean
92
     */
93 9
    public function fileSupportsUnserializePhpPresentation($pFilename = '')
94
    {
95
        // Check if file exists
96 9
        if (!file_exists($pFilename)) {
97 2
            throw new \Exception("Could not open " . $pFilename . " for reading! File does not exist.");
98
        }
99
100 7
        $oZip = new ZipArchive();
101
        // Is it a zip ?
102 7
        if ($oZip->open($pFilename) === true) {
103
            // Is it an OpenXML Document ?
104
            // Is it a Presentation ?
105 5
            if (is_array($oZip->statName('[Content_Types].xml')) && is_array($oZip->statName('ppt/presentation.xml'))) {
106 5
                return true;
107
            }
108
        }
109 3
        return false;
110
    }
111
112
    /**
113
     * Loads PhpPresentation Serialized file
114
     *
115
     * @param  string $pFilename
116
     * @return \PhpOffice\PhpPresentation\PhpPresentation
117
     * @throws \Exception
118
     */
119 6
    public function load($pFilename)
120
    {
121
        // Unserialize... First make sure the file supports it!
122 6
        if (!$this->fileSupportsUnserializePhpPresentation($pFilename)) {
123 1
            throw new \Exception("Invalid file format for PhpOffice\PhpPresentation\Reader\PowerPoint2007: " . $pFilename . ".");
124
        }
125
126 4
        return $this->loadFile($pFilename);
127
    }
128
129
    /**
130
     * Load PhpPresentation Serialized file
131
     *
132
     * @param  string $pFilename
133
     * @return \PhpOffice\PhpPresentation\PhpPresentation
134
     */
135 4
    protected function loadFile($pFilename)
136
    {
137 4
        $this->oPhpPresentation = new PhpPresentation();
138 4
        $this->oPhpPresentation->removeSlideByIndex();
139 4
        $this->oPhpPresentation->setAllMasterSlides(array());
140 4
        $this->filename = $pFilename;
141
142 4
        $this->oZip = new ZipArchive();
143 4
        $this->oZip->open($this->filename);
144 4
        $docPropsCore = $this->oZip->getFromName('docProps/core.xml');
145 4
        if ($docPropsCore !== false) {
146 4
            $this->loadDocumentProperties($docPropsCore);
147
        }
148
149 4
        $docPropsCustom = $this->oZip->getFromName('docProps/custom.xml');
150 4
        if ($docPropsCustom !== false) {
151 1
            $this->loadCustomProperties($docPropsCustom);
152
        }
153
154 4
        $pptViewProps = $this->oZip->getFromName('ppt/viewProps.xml');
155 4
        if ($pptViewProps !== false) {
156 4
            $this->loadViewProperties($pptViewProps);
157
        }
158
159 4
        $pptPresentation = $this->oZip->getFromName('ppt/presentation.xml');
160 4
        if ($pptPresentation !== false) {
161 4
            $this->loadDocumentLayout($pptPresentation);
162 4
            $this->loadSlides($pptPresentation);
163
        }
164
165 4
        return $this->oPhpPresentation;
166
    }
167
168
    /**
169
     * Read Document Layout
170
     * @param $sPart
171
     */
172 4
    protected function loadDocumentLayout($sPart)
173
    {
174 4
        $xmlReader = new XMLReader();
175 4
        if ($xmlReader->getDomFromString($sPart)) {
176 4
            foreach ($xmlReader->getElements('/p:presentation/p:sldSz') as $oElement) {
177 4
                if (!($oElement instanceof \DOMElement)) {
178
                    continue;
179
                }
180 4
                $type = $oElement->getAttribute('type');
181 4
                $oLayout = $this->oPhpPresentation->getLayout();
182 4
                if ($type == DocumentLayout::LAYOUT_CUSTOM) {
183
                    $oLayout->setCX($oElement->getAttribute('cx'));
184
                    $oLayout->setCY($oElement->getAttribute('cy'));
185
                } else {
186 4
                    $oLayout->setDocumentLayout($type, true);
187 4
                    if ($oElement->getAttribute('cx') < $oElement->getAttribute('cy')) {
188 4
                        $oLayout->setDocumentLayout($type, false);
189
                    }
190
                }
191
            }
192
        }
193 4
    }
194
195
    /**
196
     * Read Document Properties
197
     * @param string $sPart
198
     */
199 4
    protected function loadDocumentProperties($sPart)
200
    {
201 4
        $xmlReader = new XMLReader();
202 4
        if ($xmlReader->getDomFromString($sPart)) {
203
            $arrayProperties = array(
204 4
                '/cp:coreProperties/dc:creator' => 'setCreator',
205
                '/cp:coreProperties/cp:lastModifiedBy' => 'setLastModifiedBy',
206
                '/cp:coreProperties/dc:title' => 'setTitle',
207
                '/cp:coreProperties/dc:description' => 'setDescription',
208
                '/cp:coreProperties/dc:subject' => 'setSubject',
209
                '/cp:coreProperties/cp:keywords' => 'setKeywords',
210
                '/cp:coreProperties/cp:category' => 'setCategory',
211
                '/cp:coreProperties/dcterms:created' => 'setCreated',
212
                '/cp:coreProperties/dcterms:modified' => 'setModified',
213
            );
214 4
            $oProperties = $this->oPhpPresentation->getDocumentProperties();
215 4
            foreach ($arrayProperties as $path => $property) {
216 4
                $oElement = $xmlReader->getElement($path);
217 4
                if ($oElement instanceof \DOMElement) {
218 4
                    if ($oElement->hasAttribute('xsi:type') && $oElement->getAttribute('xsi:type') == 'dcterms:W3CDTF') {
219 4
                        $oDateTime = new \DateTime();
220 4
                        $oDateTime->createFromFormat(\DateTime::W3C, $oElement->nodeValue);
221 4
                        $oProperties->{$property}($oDateTime->getTimestamp());
222
                    } else {
223 4
                        $oProperties->{$property}($oElement->nodeValue);
224
                    }
225
                }
226
            }
227
        }
228 4
    }
229
230
    /**
231
     * Read Custom Properties
232
     * @param string $sPart
233
     */
234 1
    protected function loadCustomProperties($sPart)
235
    {
236 1
        $xmlReader = new XMLReader();
237 1
        $sPart = str_replace(' xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"', '', $sPart);
238 1
        if ($xmlReader->getDomFromString($sPart)) {
239 1
            $pathMarkAsFinal = '/Properties/property[@pid="2"][@fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"][@name="_MarkAsFinal"]/vt:bool';
240 1
            if (is_object($oElement = $xmlReader->getElement($pathMarkAsFinal))) {
241 1
                if ($oElement->nodeValue == 'true') {
242 1
                    $this->oPhpPresentation->getPresentationProperties()->markAsFinal(true);
243
                }
244
            }
245
        }
246 1
    }
247
248
    /**
249
     * Read View Properties
250
     * @param string $sPart
251
     */
252 4
    protected function loadViewProperties($sPart)
253
    {
254 4
        $xmlReader = new XMLReader();
255 4
        if ($xmlReader->getDomFromString($sPart)) {
256 4
            $pathZoom = '/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx';
257 4
            $oElement = $xmlReader->getElement($pathZoom);
258 4
            if ($oElement instanceof \DOMElement) {
259 3
                if ($oElement->hasAttribute('d') && $oElement->hasAttribute('n')) {
260 3
                    $this->oPhpPresentation->getPresentationProperties()->setZoom($oElement->getAttribute('n') / $oElement->getAttribute('d'));
261
                }
262
            }
263
        }
264 4
    }
265
266
    /**
267
     * Extract all slides
268
     */
269 4
    protected function loadSlides($sPart)
270
    {
271 4
        $xmlReader = new XMLReader();
272 4
        if ($xmlReader->getDomFromString($sPart)) {
273 4
            $fileRels = 'ppt/_rels/presentation.xml.rels';
274 4
            $this->loadRels($fileRels);
275
            // Load the Masterslides
276 4
            $this->loadMasterSlides($xmlReader, $fileRels);
277
            // Continue with loading the slides
278 4
            foreach ($xmlReader->getElements('/p:presentation/p:sldIdLst/p:sldId') as $oElement) {
279 4
                if (!($oElement instanceof \DOMElement)) {
280
                    continue;
281
                }
282 4
                $rId = $oElement->getAttribute('r:id');
283 4
                $pathSlide = isset($this->arrayRels[$fileRels][$rId]) ? $this->arrayRels[$fileRels][$rId]['Target'] : '';
284 4
                if (!empty($pathSlide)) {
285 4
                    $pptSlide = $this->oZip->getFromName('ppt/' . $pathSlide);
286 4
                    if ($pptSlide !== false) {
287 4
                        $slideRels = 'ppt/slides/_rels/' . basename($pathSlide) . '.rels';
288 4
                        $this->loadRels($slideRels);
289 4
                        $this->loadSlide($pptSlide, basename($pathSlide));
290 4
                        foreach ($this->arrayRels[$slideRels] as $key => $rel) {
291 4
                            if ($rel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide') {
292 4
                                $this->loadSlideNote(basename($rel['Target']), $this->oPhpPresentation->getActiveSlide());
293
                            }
294
                        }
295
                    }
296
                }
297
            }
298
        }
299 4
    }
300
301
    /**
302
     * Extract all MasterSlides
303
     * @param XMLReader $xmlReader
304
     * @param string $fileRels
305
     */
306 4
    protected function loadMasterSlides(XMLReader $xmlReader, $fileRels)
307
    {
308
        // Get all the MasterSlide Id's from the presentation.xml file
309 4
        foreach ($xmlReader->getElements('/p:presentation/p:sldMasterIdLst/p:sldMasterId') as $oElement) {
310 4
            if (!($oElement instanceof \DOMElement)) {
311
                continue;
312
            }
313 4
            $rId = $oElement->getAttribute('r:id');
314
            // Get the path to the masterslide from the array with _rels files
315 4
            $pathMasterSlide = isset($this->arrayRels[$fileRels][$rId]) ?
316 4
                $this->arrayRels[$fileRels][$rId]['Target'] : '';
317 4
            if (!empty($pathMasterSlide)) {
318 4
                $pptMasterSlide = $this->oZip->getFromName('ppt/' . $pathMasterSlide);
319 4
                if ($pptMasterSlide !== false) {
320 4
                    $this->loadRels('ppt/slideMasters/_rels/' . basename($pathMasterSlide) . '.rels');
321 4
                    $this->loadMasterSlide($pptMasterSlide, basename($pathMasterSlide));
322
                }
323
            }
324
        }
325 4
    }
326
327
    /**
328
     * Extract data from slide
329
     * @param string $sPart
330
     * @param string $baseFile
331
     */
332 4
    protected function loadSlide($sPart, $baseFile)
333
    {
334 4
        $xmlReader = new XMLReader();
335 4
        if ($xmlReader->getDomFromString($sPart)) {
336
            // Core
337 4
            $oSlide = $this->oPhpPresentation->createSlide();
338 4
            $this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1);
339 4
            $oSlide->setRelsIndex('ppt/slides/_rels/' . $baseFile . '.rels');
340
341
            // Background
342 4
            $oElement = $xmlReader->getElement('/p:sld/p:cSld/p:bg/p:bgPr');
343 4
            if ($oElement instanceof \DOMElement) {
344
                $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
345
                if ($oElementColor instanceof \DOMElement) {
346
                    // Color
347
                    $oColor = new Color();
348
                    $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
349
                    // Background
350
                    $oBackground = new Slide\Background\Color();
351
                    $oBackground->setColor($oColor);
352
                    // Slide Background
353
                    $oSlide = $this->oPhpPresentation->getActiveSlide();
354
                    $oSlide->setBackground($oBackground);
355
                }
356
                $oElementImage = $xmlReader->getElement('a:blipFill/a:blip', $oElement);
357
                if ($oElementImage instanceof \DOMElement) {
358
                    $relImg = $this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'][$oElementImage->getAttribute('r:embed')];
359
                    if (is_array($relImg)) {
360
                        // File
361
                        $pathImage = 'ppt/slides/' . $relImg['Target'];
362
                        $pathImage = explode('/', $pathImage);
363
                        foreach ($pathImage as $key => $partPath) {
364
                            if ($partPath == '..') {
365
                                unset($pathImage[$key - 1]);
366
                                unset($pathImage[$key]);
367
                            }
368
                        }
369
                        $pathImage = implode('/', $pathImage);
370
                        $contentImg = $this->oZip->getFromName($pathImage);
371
372
                        $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
373
                        file_put_contents($tmpBkgImg, $contentImg);
374
                        // Background
375
                        $oBackground = new Slide\Background\Image();
376
                        $oBackground->setPath($tmpBkgImg);
377
                        // Slide Background
378
                        $oSlide = $this->oPhpPresentation->getActiveSlide();
379
                        $oSlide->setBackground($oBackground);
380
                    }
381
                }
382
            }
383
384
            // Shapes
385 4
            $arrayElements = $xmlReader->getElements('/p:sld/p:cSld/p:spTree/*');
386 4
            if ($arrayElements) {
387 4
                $this->loadSlideShapes($oSlide, $arrayElements, $xmlReader);
388
            }
389
390
            // Layout
391 4
            $oSlide = $this->oPhpPresentation->getActiveSlide();
392 4
            foreach ($this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'] as $valueRel) {
393 4
                if ($valueRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout') {
394 4
                    $layoutBasename = basename($valueRel['Target']);
395 4
                    if (array_key_exists($layoutBasename, $this->arraySlideLayouts)) {
396 4
                        $oSlide->setSlideLayout($this->arraySlideLayouts[$layoutBasename]);
397
                    }
398 4
                    break;
399
                }
400
            }
401
        }
402 4
    }
403
404
    /**
405
     * @param string $sPart
406
     * @param string $baseFile
407
     */
408 4
    protected function loadMasterSlide($sPart, $baseFile)
409
    {
410 4
        $xmlReader = new XMLReader();
411 4
        if ($xmlReader->getDomFromString($sPart)) {
412
            // Core
413 4
            $oSlideMaster = $this->oPhpPresentation->createMasterSlide();
414 4
            $oSlideMaster->setTextStyles(new TextStyle(false));
415 4
            $oSlideMaster->setRelsIndex('ppt/slideMasters/_rels/' . $baseFile . '.rels');
416
417
            // Background
418 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:cSld/p:bg');
419 4
            if ($oElement instanceof \DOMElement) {
420 4
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideMaster);
421
            }
422
423
            // Shapes
424 4
            $arrayElements = $xmlReader->getElements('/p:sldMaster/p:cSld/p:spTree/*');
425 4
            if ($arrayElements) {
426 4
                $this->loadSlideShapes($oSlideMaster, $arrayElements, $xmlReader);
427
            }
428
            // Header & Footer
429
430
            // ColorMapping
431 4
            $colorMap = array();
432 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:clrMap');
433 4
            if ($oElement->hasAttributes()) {
434 4
                foreach ($oElement->attributes as $attr) {
435 4
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
436
                }
437 4
                $oSlideMaster->colorMap->setMapping($colorMap);
438
            }
439
440
            // TextStyles
441 4
            $arrayElementTxStyles = $xmlReader->getElements('/p:sldMaster/p:txStyles/*');
442 4
            if ($arrayElementTxStyles) {
443 4
                foreach ($arrayElementTxStyles as $oElementTxStyle) {
444 4
                    $arrayElementsLvl = $xmlReader->getElements('/p:sldMaster/p:txStyles/' . $oElementTxStyle->nodeName . '/*');
445 4
                    foreach ($arrayElementsLvl as $oElementLvl) {
446 4
                        if (!($oElementLvl instanceof \DOMElement) || $oElementLvl->nodeName == 'a:extLst') {
447 1
                            continue;
448
                        }
449 4
                        $oRTParagraph = new Paragraph();
450
451 4
                        if ($oElementLvl->nodeName == 'a:defPPr') {
452 3
                            $level = 0;
453
                        } else {
454 4
                            $level = str_replace('a:lvl', '', $oElementLvl->nodeName);
455 4
                            $level = str_replace('pPr', '', $level);
456
                        }
457
458 4
                        if ($oElementLvl->hasAttribute('algn')) {
459 4
                            $oRTParagraph->getAlignment()->setHorizontal($oElementLvl->getAttribute('algn'));
460
                        }
461 4
                        if ($oElementLvl->hasAttribute('marL')) {
462 4
                            $val = $oElementLvl->getAttribute('marL');
463 4
                            $val = CommonDrawing::emuToPixels($val);
464 4
                            $oRTParagraph->getAlignment()->setMarginLeft($val);
465
                        }
466 4
                        if ($oElementLvl->hasAttribute('marR')) {
467
                            $val = $oElementLvl->getAttribute('marR');
468
                            $val = CommonDrawing::emuToPixels($val);
469
                            $oRTParagraph->getAlignment()->setMarginRight($val);
470
                        }
471 4
                        if ($oElementLvl->hasAttribute('indent')) {
472 4
                            $val = $oElementLvl->getAttribute('indent');
473 4
                            $val = CommonDrawing::emuToPixels($val);
474 4
                            $oRTParagraph->getAlignment()->setIndent($val);
475
                        }
476 4
                        $oElementLvlDefRPR = $xmlReader->getElement('a:defRPr', $oElementLvl);
477 4
                        if ($oElementLvlDefRPR instanceof \DOMElement) {
478 4
                            if ($oElementLvlDefRPR->hasAttribute('sz')) {
479 4
                                $oRTParagraph->getFont()->setSize($oElementLvlDefRPR->getAttribute('sz') / 100);
480
                            }
481 4
                            if ($oElementLvlDefRPR->hasAttribute('b') && $oElementLvlDefRPR->getAttribute('b') == 1) {
482 1
                                $oRTParagraph->getFont()->setBold(true);
483
                            }
484 4
                            if ($oElementLvlDefRPR->hasAttribute('i') && $oElementLvlDefRPR->getAttribute('i') == 1) {
485
                                $oRTParagraph->getFont()->setItalic(true);
486
                            }
487
                        }
488 4
                        $oElementSchemeColor = $xmlReader->getElement('a:defRPr/a:solidFill/a:schemeClr', $oElementLvl);
489 4
                        if ($oElementSchemeColor instanceof \DOMElement) {
490 4
                            if ($oElementSchemeColor->hasAttribute('val')) {
491 4
                                $oSchemeColor = new SchemeColor();
492 4
                                $oSchemeColor->setValue($oElementSchemeColor->getAttribute('val'));
493 4
                                $oRTParagraph->getFont()->setColor($oSchemeColor);
494
                            }
495
                        }
496
497 4
                        switch ($oElementTxStyle->nodeName) {
498 4
                            case 'p:bodyStyle':
499 4
                                $oSlideMaster->getTextStyles()->setBodyStyleAtLvl($oRTParagraph, $level);
500 4
                                break;
501 4
                            case 'p:otherStyle':
502 4
                                $oSlideMaster->getTextStyles()->setOtherStyleAtLvl($oRTParagraph, $level);
503 4
                                break;
504 4
                            case 'p:titleStyle':
505 4
                                $oSlideMaster->getTextStyles()->setTitleStyleAtLvl($oRTParagraph, $level);
506 4
                                break;
507
                        }
508
                    }
509
                }
510
            }
511
512
            // Load the theme
513 4
            foreach ($this->arrayRels[$oSlideMaster->getRelsIndex()] as $arrayRel) {
514 4
                if ($arrayRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') {
515 4
                    $pptTheme = $this->oZip->getFromName('ppt/' . substr($arrayRel['Target'], strrpos($arrayRel['Target'], '../') + 3));
516 4
                    if ($pptTheme !== false) {
517 4
                        $this->loadTheme($pptTheme, $oSlideMaster);
518
                    }
519 4
                    break;
520
                }
521
            }
522
523
            // Load the Layoutslide
524 4
            foreach ($xmlReader->getElements('/p:sldMaster/p:sldLayoutIdLst/p:sldLayoutId') as $oElement) {
525 4
                if (!($oElement instanceof \DOMElement)) {
526
                    continue;
527
                }
528 4
                $rId = $oElement->getAttribute('r:id');
529
                // Get the path to the masterslide from the array with _rels files
530 4
                $pathLayoutSlide = isset($this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]) ?
531 4
                    $this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]['Target'] : '';
532 4
                if (!empty($pathLayoutSlide)) {
533 4
                    $pptLayoutSlide = $this->oZip->getFromName('ppt/' . substr($pathLayoutSlide, strrpos($pathLayoutSlide, '../') + 3));
534 4
                    if ($pptLayoutSlide !== false) {
535 4
                        $this->loadRels('ppt/slideLayouts/_rels/' . basename($pathLayoutSlide) . '.rels');
536 4
                        $oSlideMaster->addSlideLayout(
537 4
                            $this->loadLayoutSlide($pptLayoutSlide, basename($pathLayoutSlide), $oSlideMaster)
538
                        );
539
                    }
540
                }
541
            }
542
        }
543 4
    }
544
545
    /**
546
     * @param string $sPart
547
     * @param string $baseFile
548
     * @param SlideMaster $oSlideMaster
549
     * @return SlideLayout|null
550
     */
551 4
    protected function loadLayoutSlide($sPart, $baseFile, SlideMaster $oSlideMaster)
552
    {
553 4
        $xmlReader = new XMLReader();
554 4
        if ($xmlReader->getDomFromString($sPart)) {
555
            // Core
556 4
            $oSlideLayout = new SlideLayout($oSlideMaster);
557 4
            $oSlideLayout->setRelsIndex('ppt/slideLayouts/_rels/' . $baseFile . '.rels');
558
559
            // Name
560 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld');
561 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttribute('name')) {
562 4
                $oSlideLayout->setLayoutName($oElement->getAttribute('name'));
563
            }
564
565
            // Background
566 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld/p:bg');
567 4
            if ($oElement instanceof \DOMElement) {
568 1
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideLayout);
569
            }
570
571
            // ColorMapping
572 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:clrMapOvr/a:overrideClrMapping');
573 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttributes()) {
574 1
                $colorMap = array();
575 1
                foreach ($oElement->attributes as $attr) {
576 1
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
577
                }
578 1
                $oSlideLayout->colorMap->setMapping($colorMap);
579
            }
580
581
            // Shapes
582 4
            $oElements = $xmlReader->getElements('/p:sldLayout/p:cSld/p:spTree/*');
583 4
            if ($oElements) {
584 4
                $this->loadSlideShapes($oSlideLayout, $oElements, $xmlReader);
585
            }
586 4
            $this->arraySlideLayouts[$baseFile] = &$oSlideLayout;
587 4
            return $oSlideLayout;
588
        }
589
        return null;
590
    }
591
592
    /**
593
     * @param string $sPart
594
     * @param SlideMaster $oSlideMaster
595
     */
596 4
    protected function loadTheme($sPart, SlideMaster $oSlideMaster)
597
    {
598 4
        $xmlReader = new XMLReader();
599 4
        if ($xmlReader->getDomFromString($sPart)) {
600 4
            $oElements = $xmlReader->getElements('/a:theme/a:themeElements/a:clrScheme/*');
601 4
            if ($oElements) {
602 4
                foreach ($oElements as $oElement) {
603 4
                    $oSchemeColor = new SchemeColor();
604 4
                    $oSchemeColor->setValue(str_replace('a:', '', $oElement->tagName));
605 4
                    $colorElement = $xmlReader->getElement('*', $oElement);
606 4
                    if ($colorElement instanceof \DOMElement) {
607 4
                        if ($colorElement->hasAttribute('lastClr')) {
608 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('lastClr'));
609 4
                        } elseif ($colorElement->hasAttribute('val')) {
610 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('val'));
611
                        }
612
                    }
613 4
                    $oSlideMaster->addSchemeColor($oSchemeColor);
614
                }
615
            }
616
        }
617 4
    }
618
619
    /**
620
     * @param XMLReader $xmlReader
621
     * @param \DOMElement $oElement
622
     * @param AbstractSlide $oSlide
623
     */
624 4
    protected function loadSlideBackground(XMLReader $xmlReader, \DOMElement $oElement, AbstractSlide $oSlide)
625
    {
626
        // Background color
627 4
        $oElementColor = $xmlReader->getElement('p:bgPr/a:solidFill/a:srgbClr', $oElement);
628 4
        if ($oElementColor instanceof \DOMElement) {
629
            // Color
630
            $oColor = new Color();
631
            $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
632
            // Background
633
            $oBackground = new Slide\Background\Color();
634
            $oBackground->setColor($oColor);
635
            // Slide Background
636
            $oSlide->setBackground($oBackground);
637
        }
638
639
        // Background scheme color
640 4
        $oElementSchemeColor = $xmlReader->getElement('p:bgRef/a:schemeClr', $oElement);
641 4
        if ($oElementSchemeColor instanceof \DOMElement) {
642
            // Color
643 4
            $oColor = new SchemeColor();
644 4
            $oColor->setValue($oElementSchemeColor->hasAttribute('val') ? $oElementSchemeColor->getAttribute('val') : null);
645
            // Background
646 4
            $oBackground = new Slide\Background\SchemeColor();
647 4
            $oBackground->setSchemeColor($oColor);
648
            // Slide Background
649 4
            $oSlide->setBackground($oBackground);
650
        }
651
652
        // Background image
653 4
        $oElementImage = $xmlReader->getElement('p:bgPr/a:blipFill/a:blip', $oElement);
654 4
        if ($oElementImage instanceof \DOMElement) {
655
            $relImg = $this->arrayRels[$oSlide->getRelsIndex()][$oElementImage->getAttribute('r:embed')];
656
            if (is_array($relImg)) {
657
                // File
658
                $pathImage = 'ppt/slides/' . $relImg['Target'];
659
                $pathImage = explode('/', $pathImage);
660
                foreach ($pathImage as $key => $partPath) {
661
                    if ($partPath == '..') {
662
                        unset($pathImage[$key - 1]);
663
                        unset($pathImage[$key]);
664
                    }
665
                }
666
                $pathImage = implode('/', $pathImage);
667
                $contentImg = $this->oZip->getFromName($pathImage);
668
669
                $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
670
                file_put_contents($tmpBkgImg, $contentImg);
671
                // Background
672
                $oBackground = new Slide\Background\Image();
673
                $oBackground->setPath($tmpBkgImg);
674
                // Slide Background
675
                $oSlide->setBackground($oBackground);
676
            }
677
        }
678 4
    }
679
680
    /**
681
     * @param string $baseFile
682
     * @param Slide $oSlide
683
     */
684
    protected function loadSlideNote($baseFile, Slide $oSlide)
685
    {
686
        $sPart = $this->oZip->getFromName('ppt/notesSlides/' . $baseFile);
687
        $xmlReader = new XMLReader();
688
        if ($xmlReader->getDomFromString($sPart)) {
689
            $oNote = $oSlide->getNote();
690
691
            $arrayElements = $xmlReader->getElements('/p:notes/p:cSld/p:spTree/*');
692
            if ($arrayElements) {
693
                $this->loadSlideShapes($oNote, $arrayElements, $xmlReader);
694
            }
695
        }
696
    }
697
698
    /**
699
     * @param XMLReader $document
700
     * @param \DOMElement $node
701
     * @param AbstractSlide $oSlide
702
     */
703 3
    protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
704
    {
705
        // Core
706 3
        $oShape = new Gd();
707 3
        $oShape->getShadow()->setVisible(false);
708
        // Variables
709 3
        $fileRels = $oSlide->getRelsIndex();
710
711 3
        $oElement = $document->getElement('p:nvPicPr/p:cNvPr', $node);
712 3
        if ($oElement instanceof \DOMElement) {
713 3
            $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : '');
714 3
            $oShape->setDescription($oElement->hasAttribute('descr') ? $oElement->getAttribute('descr') : '');
715
        }
716
717 3
        $oElement = $document->getElement('p:blipFill/a:blip', $node);
718 3
        if ($oElement instanceof \DOMElement) {
719 3
            if ($oElement->hasAttribute('r:embed') && isset($this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'])) {
720 3
                $pathImage = 'ppt/slides/' . $this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'];
721 3
                $pathImage = explode('/', $pathImage);
722 3
                foreach ($pathImage as $key => $partPath) {
723 3
                    if ($partPath == '..') {
724 3
                        unset($pathImage[$key - 1]);
725 3
                        unset($pathImage[$key]);
726
                    }
727
                }
728 3
                $pathImage = implode('/', $pathImage);
729 3
                $imageFile = $this->oZip->getFromName($pathImage);
730 3
                if (!empty($imageFile)) {
731 3
                    $oShape->setImageResource(imagecreatefromstring($imageFile));
732
                }
733
            }
734
        }
735
736 3
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
737 3
        if ($oElement instanceof \DOMElement) {
738 3
            if ($oElement->hasAttribute('rot')) {
739 3
                $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
740
            }
741
        }
742
743 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
744 3
        if ($oElement instanceof \DOMElement) {
745 3
            if ($oElement->hasAttribute('x')) {
746 3
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
747
            }
748 3
            if ($oElement->hasAttribute('y')) {
749 3
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
750
            }
751
        }
752
753 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
754 3
        if ($oElement instanceof \DOMElement) {
755 3
            if ($oElement->hasAttribute('cx')) {
756 3
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
757
            }
758 3
            if ($oElement->hasAttribute('cy')) {
759 3
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
760
            }
761
        }
762
763 3
        $oElement = $document->getElement('p:spPr/a:effectLst', $node);
764 3
        if ($oElement instanceof \DOMElement) {
765 3
            $oShape->getShadow()->setVisible(true);
766
767 3
            $oSubElement = $document->getElement('a:outerShdw', $oElement);
768 3
            if ($oSubElement instanceof \DOMElement) {
769 3
                if ($oSubElement->hasAttribute('blurRad')) {
770 3
                    $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels($oSubElement->getAttribute('blurRad')));
771
                }
772 3
                if ($oSubElement->hasAttribute('dist')) {
773 3
                    $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels($oSubElement->getAttribute('dist')));
774
                }
775 3
                if ($oSubElement->hasAttribute('dir')) {
776 3
                    $oShape->getShadow()->setDirection(CommonDrawing::angleToDegrees($oSubElement->getAttribute('dir')));
777
                }
778 3
                if ($oSubElement->hasAttribute('algn')) {
779 3
                    $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn'));
780
                }
781
            }
782
783 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement);
784 3
            if ($oSubElement instanceof \DOMElement) {
785 3
                if ($oSubElement->hasAttribute('val')) {
786 3
                    $oColor = new Color();
787 3
                    $oColor->setRGB($oSubElement->getAttribute('val'));
788 3
                    $oShape->getShadow()->setColor($oColor);
789
                }
790
            }
791
792 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement);
793 3
            if ($oSubElement instanceof \DOMElement) {
794 3
                if ($oSubElement->hasAttribute('val')) {
795 3
                    $oShape->getShadow()->setAlpha((int)$oSubElement->getAttribute('val') / 1000);
796
                }
797
            }
798
        }
799
800 3
        $oSlide->addShape($oShape);
801 3
    }
802
803
    /**
804
     * @param XMLReader $document
805
     * @param \DOMElement $node
806
     * @param AbstractSlide $oSlide
807
     * @throws \Exception
808
     */
809 4
    protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oSlide)
810
    {
811 4
        if (!$document->elementExists('p:txBody/a:p/a:r', $node)) {
812 4
            return;
813
        }
814
        // Core
815 4
        $oShape = $oSlide->createRichTextShape();
816 4
        $oShape->setParagraphs(array());
817
        // Variables
818 4
        if ($oSlide instanceof AbstractSlide) {
819 4
            $this->fileRels = $oSlide->getRelsIndex();
820
        }
821
822 4
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
823 4
        if ($oElement instanceof \DOMElement && $oElement->hasAttribute('rot')) {
824 4
            $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
825
        }
826
827 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
828 4
        if ($oElement instanceof \DOMElement) {
829 4
            if ($oElement->hasAttribute('x')) {
830 4
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
831
            }
832 4
            if ($oElement->hasAttribute('y')) {
833 4
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
834
            }
835
        }
836
837 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
838 4
        if ($oElement instanceof \DOMElement) {
839 4
            if ($oElement->hasAttribute('cx')) {
840 4
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
841
            }
842 4
            if ($oElement->hasAttribute('cy')) {
843 4
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
844
            }
845
        }
846
847 4
        $oElement = $document->getElement('p:nvSpPr/p:nvPr/p:ph', $node);
848 4
        if ($oElement instanceof \DOMElement) {
849 4
            if ($oElement->hasAttribute('type')) {
850 4
                $placeholder = new Placeholder($oElement->getAttribute('type'));
851 4
                $oShape->setPlaceHolder($placeholder);
852
            }
853
        }
854
855 4
        $arrayElements = $document->getElements('p:txBody/a:p', $node);
856 4
        foreach ($arrayElements as $oElement) {
857 4
            $this->loadParagraph($document, $oElement, $oShape);
858
        }
859
860 4
        if (count($oShape->getParagraphs()) > 0) {
861 4
            $oShape->setActiveParagraph(0);
862
        }
863 4
    }
864
865
    /**
866
     * @param XMLReader $document
867
     * @param \DOMElement $node
868
     * @param AbstractSlide $oSlide
869
     * @throws \Exception
870
     */
871
    protected function loadShapeTable(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
872
    {
873
        $this->fileRels = $oSlide->getRelsIndex();
874
875
        $oShape = $oSlide->createTableShape();
876
877
        $oElement = $document->getElement('p:cNvPr', $node);
878
        if ($oElement instanceof \DOMElement) {
879
            if ($oElement->hasAttribute('name')) {
880
                $oShape->setName($oElement->getAttribute('name'));
881
            }
882
            if ($oElement->hasAttribute('descr')) {
883
                $oShape->setDescription($oElement->getAttribute('descr'));
884
            }
885
        }
886
887
        $oElement = $document->getElement('p:xfrm/a:off', $node);
888
        if ($oElement instanceof \DOMElement) {
889
            if ($oElement->hasAttribute('x')) {
890
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
891
            }
892
            if ($oElement->hasAttribute('y')) {
893
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
894
            }
895
        }
896
897
        $oElement = $document->getElement('p:xfrm/a:ext', $node);
898
        if ($oElement instanceof \DOMElement) {
899
            if ($oElement->hasAttribute('cx')) {
900
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
901
            }
902
            if ($oElement->hasAttribute('cy')) {
903
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
904
            }
905
        }
906
907
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tblGrid/a:gridCol', $node);
908
        $oShape->setNumColumns($arrayElements->length);
909
        $oShape->createRow();
910
        foreach ($arrayElements as $key => $oElement) {
911
            if ($oElement instanceof \DOMElement && $oElement->getAttribute('w')) {
912
                $oShape->getRow(0)->getCell($key)->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('w')));
913
            }
914
        }
915
916
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tr', $node);
917
        foreach ($arrayElements as $keyRow => $oElementRow) {
918
            if (!($oElementRow instanceof \DOMElement)) {
919
                continue;
920
            }
921
            $oRow = $oShape->getRow($keyRow, true);
922
            if (is_null($oRow)) {
923
                $oRow = $oShape->createRow();
924
            }
925
            if ($oElementRow->hasAttribute('h')) {
926
                $oRow->setHeight(CommonDrawing::emuToPixels($oElementRow->getAttribute('h')));
927
            }
928
            $arrayElementsCell = $document->getElements('a:tc', $oElementRow);
929
            foreach ($arrayElementsCell as $keyCell => $oElementCell) {
930
                if (!($oElementCell instanceof \DOMElement)) {
931
                    continue;
932
                }
933
                $oCell = $oRow->getCell($keyCell);
934
                $oCell->setParagraphs(array());
935
                if ($oElementCell->hasAttribute('gridSpan')) {
936
                    $oCell->setColSpan($oElementCell->getAttribute('gridSpan'));
937
                }
938
                if ($oElementCell->hasAttribute('rowSpan')) {
939
                    $oCell->setRowSpan($oElementCell->getAttribute('rowSpan'));
940
                }
941
942
                foreach ($document->getElements('a:txBody/a:p', $oElementCell) as $oElementPara) {
943
                    $this->loadParagraph($document, $oElementPara, $oCell);
0 ignored issues
show
Bug introduced by
It seems like $oCell defined by $oRow->getCell($keyCell) on line 933 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...
944
                }
945
946
                $oElementTcPr = $document->getElement('a:tcPr', $oElementCell);
947
                if ($oElementTcPr instanceof \DOMElement) {
948
                    $numParagraphs = count($oCell->getParagraphs());
949
                    if ($numParagraphs > 0) {
950
                        if ($oElementTcPr->hasAttribute('anchor')) {
951
                            $oCell->getParagraph(0)->getAlignment()->setVertical($oElementTcPr->getAttribute('anchor'));
952
                        }
953
                        if ($oElementTcPr->hasAttribute('marB')) {
954
                            $oCell->getParagraph(0)->getAlignment()->setMarginBottom($oElementTcPr->getAttribute('marB'));
955
                        }
956
                        if ($oElementTcPr->hasAttribute('marL')) {
957
                            $oCell->getParagraph(0)->getAlignment()->setMarginLeft($oElementTcPr->getAttribute('marL'));
958
                        }
959
                        if ($oElementTcPr->hasAttribute('marR')) {
960
                            $oCell->getParagraph(0)->getAlignment()->setMarginRight($oElementTcPr->getAttribute('marR'));
961
                        }
962
                        if ($oElementTcPr->hasAttribute('marT')) {
963
                            $oCell->getParagraph(0)->getAlignment()->setMarginTop($oElementTcPr->getAttribute('marT'));
964
                        }
965
                    }
966
967
                    $oFill = $this->loadStyleFill($document, $oElementTcPr);
968
                    if ($oFill instanceof Fill) {
969
                        $oCell->setFill($oFill);
970
                    }
971
972
                    $oBorders = new Borders();
973
                    $oElementBorderL = $document->getElement('a:lnL', $oElementTcPr);
974
                    if ($oElementBorderL instanceof \DOMElement) {
975
                        $this->loadStyleBorder($document, $oElementBorderL, $oBorders->getLeft());
976
                    }
977
                    $oElementBorderR = $document->getElement('a:lnR', $oElementTcPr);
978
                    if ($oElementBorderR instanceof \DOMElement) {
979
                        $this->loadStyleBorder($document, $oElementBorderR, $oBorders->getRight());
980
                    }
981
                    $oElementBorderT = $document->getElement('a:lnT', $oElementTcPr);
982
                    if ($oElementBorderT instanceof \DOMElement) {
983
                        $this->loadStyleBorder($document, $oElementBorderT, $oBorders->getTop());
984
                    }
985
                    $oElementBorderB = $document->getElement('a:lnB', $oElementTcPr);
986
                    if ($oElementBorderB instanceof \DOMElement) {
987
                        $this->loadStyleBorder($document, $oElementBorderB, $oBorders->getBottom());
988
                    }
989
                    $oElementBorderDiagDown = $document->getElement('a:lnTlToBr', $oElementTcPr);
990
                    if ($oElementBorderDiagDown instanceof \DOMElement) {
991
                        $this->loadStyleBorder($document, $oElementBorderDiagDown, $oBorders->getDiagonalDown());
992
                    }
993
                    $oElementBorderDiagUp = $document->getElement('a:lnBlToTr', $oElementTcPr);
994
                    if ($oElementBorderDiagUp instanceof \DOMElement) {
995
                        $this->loadStyleBorder($document, $oElementBorderDiagUp, $oBorders->getDiagonalUp());
996
                    }
997
                    $oCell->setBorders($oBorders);
998
                }
999
            }
1000
        }
1001
    }
1002
1003
    /**
1004
     * @param XMLReader $document
1005
     * @param \DOMElement $oElement
1006
     * @param Cell|RichText $oShape
1007
     * @throws \Exception
1008
     */
1009 4
    protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oShape)
1010
    {
1011
        // Core
1012 4
        $oParagraph = $oShape->createParagraph();
1013 4
        $oParagraph->setRichTextElements(array());
1014
1015 4
        $oSubElement = $document->getElement('a:pPr', $oElement);
1016 4
        if ($oSubElement instanceof \DOMElement) {
1017 4
            if ($oSubElement->hasAttribute('algn')) {
1018 3
                $oParagraph->getAlignment()->setHorizontal($oSubElement->getAttribute('algn'));
1019
            }
1020 4
            if ($oSubElement->hasAttribute('fontAlgn')) {
1021 3
                $oParagraph->getAlignment()->setVertical($oSubElement->getAttribute('fontAlgn'));
1022
            }
1023 4
            if ($oSubElement->hasAttribute('marL')) {
1024 3
                $oParagraph->getAlignment()->setMarginLeft(CommonDrawing::emuToPixels($oSubElement->getAttribute('marL')));
1025
            }
1026 4
            if ($oSubElement->hasAttribute('marR')) {
1027 3
                $oParagraph->getAlignment()->setMarginRight(CommonDrawing::emuToPixels($oSubElement->getAttribute('marR')));
1028
            }
1029 4
            if ($oSubElement->hasAttribute('indent')) {
1030 3
                $oParagraph->getAlignment()->setIndent(CommonDrawing::emuToPixels($oSubElement->getAttribute('indent')));
1031
            }
1032 4
            if ($oSubElement->hasAttribute('lvl')) {
1033 4
                $oParagraph->getAlignment()->setLevel($oSubElement->getAttribute('lvl'));
1034
            }
1035
1036 4
            $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NONE);
1037
1038 4
            $oElementBuFont = $document->getElement('a:buFont', $oSubElement);
1039 4
            if ($oElementBuFont instanceof \DOMElement) {
1040 3
                if ($oElementBuFont->hasAttribute('typeface')) {
1041 3
                    $oParagraph->getBulletStyle()->setBulletFont($oElementBuFont->getAttribute('typeface'));
1042
                }
1043
            }
1044 4
            $oElementBuChar = $document->getElement('a:buChar', $oSubElement);
1045 4
            if ($oElementBuChar instanceof \DOMElement) {
1046 3
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET);
1047 3
                if ($oElementBuChar->hasAttribute('char')) {
1048 3
                    $oParagraph->getBulletStyle()->setBulletChar($oElementBuChar->getAttribute('char'));
1049
                }
1050
            }
1051 4
            $oElementBuAutoNum = $document->getElement('a:buAutoNum', $oSubElement);
1052 4
            if ($oElementBuAutoNum instanceof \DOMElement) {
1053
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NUMERIC);
1054
                if ($oElementBuAutoNum->hasAttribute('type')) {
1055
                    $oParagraph->getBulletStyle()->setBulletNumericStyle($oElementBuAutoNum->getAttribute('type'));
1056
                }
1057
                if ($oElementBuAutoNum->hasAttribute('startAt') && $oElementBuAutoNum->getAttribute('startAt') != 1) {
1058
                    $oParagraph->getBulletStyle()->setBulletNumericStartAt($oElementBuAutoNum->getAttribute('startAt'));
1059
                }
1060
            }
1061 4
            $oElementBuClr = $document->getElement('a:buClr', $oSubElement);
1062 4
            if ($oElementBuClr instanceof \DOMElement) {
1063
                $oColor = new Color();
1064
                /**
1065
                 * @todo Create protected for reading Color
1066
                 */
1067
                $oElementColor = $document->getElement('a:srgbClr', $oElementBuClr);
1068
                if ($oElementColor instanceof \DOMElement) {
1069
                    $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
1070
                }
1071
                $oParagraph->getBulletStyle()->setBulletColor($oColor);
1072
            }
1073
        }
1074 4
        $arraySubElements = $document->getElements('(a:r|a:br)', $oElement);
1075 4
        foreach ($arraySubElements as $oSubElement) {
1076 4
            if ($oSubElement->tagName == 'a:br') {
1077 3
                $oParagraph->createBreak();
1078
            }
1079 4
            if ($oSubElement->tagName == 'a:r') {
1080 4
                $oElementrPr = $document->getElement('a:rPr', $oSubElement);
1081 4
                if (is_object($oElementrPr)) {
1082 4
                    $oText = $oParagraph->createTextRun();
1083
1084 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...
1085 3
                        $att = $oElementrPr->getAttribute('b');
1086 3
                        $oText->getFont()->setBold($att == 'true' || $att == '1' ? true : false);
1087
                    }
1088 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...
1089 3
                        $att = $oElementrPr->getAttribute('i');
1090 3
                        $oText->getFont()->setItalic($att == 'true' || $att == '1' ? true : false);
1091
                    }
1092 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...
1093 3
                        $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true);
1094
                    }
1095 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...
1096 3
                        $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100));
1097
                    }
1098 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...
1099 3
                        $oText->getFont()->setUnderline($oElementrPr->getAttribute('u'));
1100
                    }
1101
                    // Color
1102 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...
1103 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...
1104 3
                        $oColor = new Color();
1105 3
                        $oColor->setRGB($oElementSrgbClr->getAttribute('val'));
1106 3
                        $oText->getFont()->setColor($oColor);
1107
                    }
1108
                    // Hyperlink
1109 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...
1110 4
                    if (is_object($oElementHlinkClick)) {
1111 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...
1112 3
                            $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip'));
1113
                        }
1114 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...
1115 3
                            $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']);
1116
                        }
1117
                    }
1118
                    //} else {
1119
                    // $oText = $oParagraph->createText();
1120
1121 4
                    $oSubSubElement = $document->getElement('a:t', $oSubElement);
1122 4
                    $oText->setText($oSubSubElement->nodeValue);
1123
                }
1124
            }
1125
        }
1126 4
    }
1127
1128
    /**
1129
     * @param XMLReader $xmlReader
1130
     * @param \DOMElement $oElement
1131
     * @param Border $oBorder
1132
     */
1133
    protected function loadStyleBorder(XMLReader $xmlReader, \DOMElement $oElement, Border $oBorder)
1134
    {
1135
        if ($oElement->hasAttribute('w')) {
1136
            $oBorder->setLineWidth($oElement->getAttribute('w') / 12700);
1137
        }
1138
        if ($oElement->hasAttribute('cmpd')) {
1139
            $oBorder->setLineStyle($oElement->getAttribute('cmpd'));
1140
        }
1141
1142
        $oElementNoFill = $xmlReader->getElement('a:noFill', $oElement);
1143
        if ($oElementNoFill instanceof \DOMElement && $oBorder->getLineStyle() == Border::LINE_SINGLE) {
1144
            $oBorder->setLineStyle(Border::LINE_NONE);
1145
        }
1146
1147
        $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
1148
        if ($oElementColor instanceof \DOMElement) {
1149
            $oBorder->setColor($this->loadStyleColor($xmlReader, $oElementColor));
1150
        }
1151
1152
        $oElementDashStyle = $xmlReader->getElement('a:prstDash', $oElement);
1153
        if ($oElementDashStyle instanceof \DOMElement && $oElementDashStyle->hasAttribute('val')) {
1154
            $oBorder->setDashStyle($oElementDashStyle->getAttribute('val'));
1155
        }
1156
    }
1157
1158
    /**
1159
     * @param XMLReader $xmlReader
1160
     * @param \DOMElement $oElement
1161
     * @return Color
1162
     */
1163
    protected function loadStyleColor(XMLReader $xmlReader, \DOMElement $oElement)
1164
    {
1165
        $oColor = new Color();
1166
        $oColor->setRGB($oElement->getAttribute('val'));
1167
        $oElementAlpha = $xmlReader->getElement('a:alpha', $oElement);
1168
        if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1169
            $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1170
            $oColor->setRGB($oElement->getAttribute('val'), $alpha);
1171
        }
1172
        return $oColor;
1173
    }
1174
1175
    /**
1176
     * @param XMLReader $xmlReader
1177
     * @param \DOMElement $oElement
1178
     * @return null|Fill
1179
     */
1180
    protected function loadStyleFill(XMLReader $xmlReader, \DOMElement $oElement)
1181
    {
1182
        // Gradient fill
1183
        $oElementFill = $xmlReader->getElement('a:gradFill', $oElement);
1184
        if ($oElementFill instanceof \DOMElement) {
1185
            $oFill = new Fill();
1186
            $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR);
1187
1188
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill);
1189
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1190
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1191
            }
1192
1193
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill);
1194
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1195
                $oFill->setEndColor($this->loadStyleColor($xmlReader, $oElementColor));
1196
            }
1197
1198
            $oRotation = $xmlReader->getElement('a:lin', $oElementFill);
1199
            if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) {
1200
                $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang')));
1201
            }
1202
            return $oFill;
1203
        }
1204
1205
        // Solid fill
1206
        $oElementFill = $xmlReader->getElement('a:solidFill', $oElement);
1207
        if ($oElementFill instanceof \DOMElement) {
1208
            $oFill = new Fill();
1209
            $oFill->setFillType(Fill::FILL_SOLID);
1210
1211
            $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill);
1212
            if ($oElementColor instanceof \DOMElement) {
1213
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1214
            }
1215
            return $oFill;
1216
        }
1217
        return null;
1218
    }
1219
1220
    /**
1221
     * @param string $fileRels
1222
     * @return string
1223
     */
1224 4
    protected function loadRels($fileRels)
1225
    {
1226 4
        $sPart = $this->oZip->getFromName($fileRels);
1227 4
        if ($sPart !== false) {
1228 4
            $xmlReader = new XMLReader();
1229 4
            if ($xmlReader->getDomFromString($sPart)) {
1230 4
                foreach ($xmlReader->getElements('*') as $oNode) {
1231 4
                    if (!($oNode instanceof \DOMElement)) {
1232
                        continue;
1233
                    }
1234 4
                    $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array(
1235 4
                        'Target' => $oNode->getAttribute('Target'),
1236 4
                        'Type' => $oNode->getAttribute('Type'),
1237
                    );
1238
                }
1239
            }
1240
        }
1241 4
    }
1242
1243
    /**
1244
     * @param $oSlide
1245
     * @param \DOMNodeList $oElements
1246
     * @param XMLReader $xmlReader
1247
     * @internal param $baseFile
1248
     */
1249 4
    protected function loadSlideShapes($oSlide, $oElements, $xmlReader)
1250
    {
1251 4
        foreach ($oElements as $oNode) {
1252 4
            switch ($oNode->tagName) {
1253 4
                case 'p:graphicFrame':
1254
                    $this->loadShapeTable($xmlReader, $oNode, $oSlide);
1255
                    break;
1256 4
                case 'p:pic':
1257 3
                    $this->loadShapeDrawing($xmlReader, $oNode, $oSlide);
1258 3
                    break;
1259 4
                case 'p:sp':
1260 4
                    $this->loadShapeRichText($xmlReader, $oNode, $oSlide);
1261 4
                    break;
1262 4
                default:
1263
                    //var_export($oNode->tagName);
1264
            }
1265
        }
1266 4
    }
1267
}
1268