Completed
Push — develop ( f4e000...ba7ca1 )
by Franck
13s
created

PowerPoint2007::loadLayoutSlide()   D

Complexity

Conditions 9
Paths 17

Size

Total Lines 40
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 9.0066

Importance

Changes 0
Metric Value
dl 0
loc 40
ccs 22
cts 23
cp 0.9565
rs 4.909
c 0
b 0
f 0
cc 9
eloc 23
nc 17
nop 3
crap 9.0066
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 $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
                $oElementColor = $xmlReader->getElement('a:solidFill/a:schemeClr', $oElement);
357
                if ($oElementColor instanceof \DOMElement) {
358
                    // Color
359
                    $oColor = new SchemeColor();
360
                    $oColor->setValue($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
361
                    // Background
362
                    $oBackground = new Slide\Background\SchemeColor();
363
                    $oBackground->setSchemeColor($oColor);
364
                    // Slide Background
365
                    $oSlide = $this->oPhpPresentation->getActiveSlide();
366
                    $oSlide->setBackground($oBackground);
367
                }
368
                $oElementImage = $xmlReader->getElement('a:blipFill/a:blip', $oElement);
369
                if ($oElementImage instanceof \DOMElement) {
370
                    $relImg = $this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'][$oElementImage->getAttribute('r:embed')];
371
                    if (is_array($relImg)) {
372
                        // File
373
                        $pathImage = 'ppt/slides/' . $relImg['Target'];
374
                        $pathImage = explode('/', $pathImage);
375
                        foreach ($pathImage as $key => $partPath) {
376
                            if ($partPath == '..') {
377
                                unset($pathImage[$key - 1]);
378
                                unset($pathImage[$key]);
379
                            }
380
                        }
381
                        $pathImage = implode('/', $pathImage);
382
                        $contentImg = $this->oZip->getFromName($pathImage);
383
384
                        $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
385
                        file_put_contents($tmpBkgImg, $contentImg);
386
                        // Background
387
                        $oBackground = new Slide\Background\Image();
388
                        $oBackground->setPath($tmpBkgImg);
389
                        // Slide Background
390
                        $oSlide = $this->oPhpPresentation->getActiveSlide();
391
                        $oSlide->setBackground($oBackground);
392
                    }
393
                }
394
            }
395
396
            // Shapes
397 4
            $arrayElements = $xmlReader->getElements('/p:sld/p:cSld/p:spTree/*');
398 4
            if ($arrayElements) {
399 4
                $this->loadSlideShapes($oSlide, $arrayElements, $xmlReader);
400
            }
401
402
            // Layout
403 4
            $oSlide = $this->oPhpPresentation->getActiveSlide();
404 4
            foreach ($this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'] as $valueRel) {
405 4
                if ($valueRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout') {
406 4
                    $layoutBasename = basename($valueRel['Target']);
407 4
                    if (array_key_exists($layoutBasename, $this->arraySlideLayouts)) {
408 4
                        $oSlide->setSlideLayout($this->arraySlideLayouts[$layoutBasename]);
409
                    }
410 4
                    break;
411
                }
412
            }
413
        }
414 4
    }
415
416
    /**
417
     * @param string $sPart
418
     * @param string $baseFile
419
     */
420 4
    protected function loadMasterSlide($sPart, $baseFile)
421
    {
422 4
        $xmlReader = new XMLReader();
423 4
        if ($xmlReader->getDomFromString($sPart)) {
424
            // Core
425 4
            $oSlideMaster = $this->oPhpPresentation->createMasterSlide();
426 4
            $oSlideMaster->setTextStyles(new TextStyle(false));
427 4
            $oSlideMaster->setRelsIndex('ppt/slideMasters/_rels/' . $baseFile . '.rels');
428
429
            // Background
430 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:cSld/p:bg');
431 4
            if ($oElement instanceof \DOMElement) {
432 4
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideMaster);
433
            }
434
435
            // Shapes
436 4
            $arrayElements = $xmlReader->getElements('/p:sldMaster/p:cSld/p:spTree/*');
437 4
            if ($arrayElements) {
438 4
                $this->loadSlideShapes($oSlideMaster, $arrayElements, $xmlReader);
439
            }
440
            // Header & Footer
441
442
            // ColorMapping
443 4
            $colorMap = array();
444 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:clrMap');
445 4
            if ($oElement->hasAttributes()) {
446 4
                foreach ($oElement->attributes as $attr) {
447 4
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
448
                }
449 4
                $oSlideMaster->colorMap->setMapping($colorMap);
450
            }
451
452
            // TextStyles
453 4
            $arrayElementTxStyles = $xmlReader->getElements('/p:sldMaster/p:txStyles/*');
454 4
            if ($arrayElementTxStyles) {
455 4
                foreach ($arrayElementTxStyles as $oElementTxStyle) {
456 4
                    $arrayElementsLvl = $xmlReader->getElements('/p:sldMaster/p:txStyles/' . $oElementTxStyle->nodeName . '/*');
457 4
                    foreach ($arrayElementsLvl as $oElementLvl) {
458 4
                        if (!($oElementLvl instanceof \DOMElement) || $oElementLvl->nodeName == 'a:extLst') {
459 1
                            continue;
460
                        }
461 4
                        $oRTParagraph = new Paragraph();
462
463 4
                        if ($oElementLvl->nodeName == 'a:defPPr') {
464 3
                            $level = 0;
465
                        } else {
466 4
                            $level = str_replace('a:lvl', '', $oElementLvl->nodeName);
467 4
                            $level = str_replace('pPr', '', $level);
468
                        }
469
470 4
                        if ($oElementLvl->hasAttribute('algn')) {
471 4
                            $oRTParagraph->getAlignment()->setHorizontal($oElementLvl->getAttribute('algn'));
472
                        }
473 4
                        if ($oElementLvl->hasAttribute('marL')) {
474 4
                            $val = $oElementLvl->getAttribute('marL');
475 4
                            $val = CommonDrawing::emuToPixels($val);
476 4
                            $oRTParagraph->getAlignment()->setMarginLeft($val);
477
                        }
478 4
                        if ($oElementLvl->hasAttribute('marR')) {
479
                            $val = $oElementLvl->getAttribute('marR');
480
                            $val = CommonDrawing::emuToPixels($val);
481
                            $oRTParagraph->getAlignment()->setMarginRight($val);
482
                        }
483 4
                        if ($oElementLvl->hasAttribute('indent')) {
484 4
                            $val = $oElementLvl->getAttribute('indent');
485 4
                            $val = CommonDrawing::emuToPixels($val);
486 4
                            $oRTParagraph->getAlignment()->setIndent($val);
487
                        }
488 4
                        $oElementLvlDefRPR = $xmlReader->getElement('a:defRPr', $oElementLvl);
489 4
                        if ($oElementLvlDefRPR instanceof \DOMElement) {
490 4
                            if ($oElementLvlDefRPR->hasAttribute('sz')) {
491 4
                                $oRTParagraph->getFont()->setSize($oElementLvlDefRPR->getAttribute('sz') / 100);
492
                            }
493 4
                            if ($oElementLvlDefRPR->hasAttribute('b') && $oElementLvlDefRPR->getAttribute('b') == 1) {
494 1
                                $oRTParagraph->getFont()->setBold(true);
495
                            }
496 4
                            if ($oElementLvlDefRPR->hasAttribute('i') && $oElementLvlDefRPR->getAttribute('i') == 1) {
497
                                $oRTParagraph->getFont()->setItalic(true);
498
                            }
499
                        }
500 4
                        $oElementSchemeColor = $xmlReader->getElement('a:defRPr/a:solidFill/a:schemeClr', $oElementLvl);
501 4
                        if ($oElementSchemeColor instanceof \DOMElement) {
502 4
                            if ($oElementSchemeColor->hasAttribute('val')) {
503 4
                                $oSchemeColor = new SchemeColor();
504 4
                                $oSchemeColor->setValue($oElementSchemeColor->getAttribute('val'));
505 4
                                $oRTParagraph->getFont()->setColor($oSchemeColor);
506
                            }
507
                        }
508
509 4
                        switch ($oElementTxStyle->nodeName) {
510 4
                            case 'p:bodyStyle':
511 4
                                $oSlideMaster->getTextStyles()->setBodyStyleAtLvl($oRTParagraph, $level);
512 4
                                break;
513 4
                            case 'p:otherStyle':
514 4
                                $oSlideMaster->getTextStyles()->setOtherStyleAtLvl($oRTParagraph, $level);
515 4
                                break;
516 4
                            case 'p:titleStyle':
517 4
                                $oSlideMaster->getTextStyles()->setTitleStyleAtLvl($oRTParagraph, $level);
518 4
                                break;
519
                        }
520
                    }
521
                }
522
            }
523
524
            // Load the theme
525 4
            foreach ($this->arrayRels[$oSlideMaster->getRelsIndex()] as $arrayRel) {
526 4
                if ($arrayRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') {
527 4
                    $pptTheme = $this->oZip->getFromName('ppt/' . substr($arrayRel['Target'], strrpos($arrayRel['Target'], '../') + 3));
528 4
                    if ($pptTheme !== false) {
529 4
                        $this->loadTheme($pptTheme, $oSlideMaster);
530
                    }
531 4
                    break;
532
                }
533
            }
534
535
            // Load the Layoutslide
536 4
            foreach ($xmlReader->getElements('/p:sldMaster/p:sldLayoutIdLst/p:sldLayoutId') as $oElement) {
537 4
                if (!($oElement instanceof \DOMElement)) {
538
                    continue;
539
                }
540 4
                $rId = $oElement->getAttribute('r:id');
541
                // Get the path to the masterslide from the array with _rels files
542 4
                $pathLayoutSlide = isset($this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]) ?
543 4
                    $this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]['Target'] : '';
544 4
                if (!empty($pathLayoutSlide)) {
545 4
                    $pptLayoutSlide = $this->oZip->getFromName('ppt/' . substr($pathLayoutSlide, strrpos($pathLayoutSlide, '../') + 3));
546 4
                    if ($pptLayoutSlide !== false) {
547 4
                        $this->loadRels('ppt/slideLayouts/_rels/' . basename($pathLayoutSlide) . '.rels');
548 4
                        $oSlideMaster->addSlideLayout(
549 4
                            $this->loadLayoutSlide($pptLayoutSlide, basename($pathLayoutSlide), $oSlideMaster)
550
                        );
551
                    }
552
                }
553
            }
554
        }
555 4
    }
556
557
    /**
558
     * @param string $sPart
559
     * @param string $baseFile
560
     * @param SlideMaster $oSlideMaster
561
     * @return SlideLayout|null
562
     */
563 4
    protected function loadLayoutSlide($sPart, $baseFile, SlideMaster $oSlideMaster)
564
    {
565 4
        $xmlReader = new XMLReader();
566 4
        if ($xmlReader->getDomFromString($sPart)) {
567
            // Core
568 4
            $oSlideLayout = new SlideLayout($oSlideMaster);
569 4
            $oSlideLayout->setRelsIndex('ppt/slideLayouts/_rels/' . $baseFile . '.rels');
570
571
            // Name
572 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld');
573 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttribute('name')) {
574 4
                $oSlideLayout->setLayoutName($oElement->getAttribute('name'));
575
            }
576
577
            // Background
578 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld/p:bg');
579 4
            if ($oElement instanceof \DOMElement) {
580 1
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideLayout);
581
            }
582
583
            // ColorMapping
584 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:clrMapOvr/a:overrideClrMapping');
585 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttributes()) {
586 1
                $colorMap = array();
587 1
                foreach ($oElement->attributes as $attr) {
588 1
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
589
                }
590 1
                $oSlideLayout->colorMap->setMapping($colorMap);
591
            }
592
593
            // Shapes
594 4
            $oElements = $xmlReader->getElements('/p:sldLayout/p:cSld/p:spTree/*');
595 4
            if ($oElements) {
596 4
                $this->loadSlideShapes($oSlideLayout, $oElements, $xmlReader);
597
            }
598 4
            $this->arraySlideLayouts[$baseFile] = &$oSlideLayout;
599 4
            return $oSlideLayout;
600
        }
601
        return null;
602
    }
603
604
    /**
605
     * @param string $sPart
606
     * @param SlideMaster $oSlideMaster
607
     */
608 4
    protected function loadTheme($sPart, SlideMaster $oSlideMaster)
609
    {
610 4
        $xmlReader = new XMLReader();
611 4
        if ($xmlReader->getDomFromString($sPart)) {
612 4
            $oElements = $xmlReader->getElements('/a:theme/a:themeElements/a:clrScheme/*');
613 4
            if ($oElements) {
614 4
                foreach ($oElements as $oElement) {
615 4
                    $oSchemeColor = new SchemeColor();
616 4
                    $oSchemeColor->setValue(str_replace('a:', '', $oElement->tagName));
617 4
                    $colorElement = $xmlReader->getElement('*', $oElement);
618 4
                    if ($colorElement instanceof \DOMElement) {
619 4
                        if ($colorElement->hasAttribute('lastClr')) {
620 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('lastClr'));
621 4
                        } elseif ($colorElement->hasAttribute('val')) {
622 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('val'));
623
                        }
624
                    }
625 4
                    $oSlideMaster->addSchemeColor($oSchemeColor);
626
                }
627
            }
628
        }
629 4
    }
630
631
    /**
632
     * @param XMLReader $xmlReader
633
     * @param \DOMElement $oElement
634
     * @param AbstractSlide $oSlide
635
     */
636 4
    protected function loadSlideBackground(XMLReader $xmlReader, \DOMElement $oElement, AbstractSlide $oSlide)
637
    {
638
        // Background color
639 4
        $oElementColor = $xmlReader->getElement('p:bgPr/a:solidFill/a:srgbClr', $oElement);
640 4
        if ($oElementColor instanceof \DOMElement) {
641
            // Color
642
            $oColor = new Color();
643
            $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
644
            // Background
645
            $oBackground = new Slide\Background\Color();
646
            $oBackground->setColor($oColor);
647
            // Slide Background
648
            $oSlide->setBackground($oBackground);
649
        }
650
651
        // Background scheme color
652 4
        $oElementSchemeColor = $xmlReader->getElement('p:bgRef/a:schemeClr', $oElement);
653 4
        if ($oElementSchemeColor instanceof \DOMElement) {
654
            // Color
655 4
            $oColor = new SchemeColor();
656 4
            $oColor->setValue($oElementSchemeColor->hasAttribute('val') ? $oElementSchemeColor->getAttribute('val') : null);
657
            // Background
658 4
            $oBackground = new Slide\Background\SchemeColor();
659 4
            $oBackground->setSchemeColor($oColor);
660
            // Slide Background
661 4
            $oSlide->setBackground($oBackground);
662
        }
663
664
        // Background image
665 4
        $oElementImage = $xmlReader->getElement('p:bgPr/a:blipFill/a:blip', $oElement);
666 4
        if ($oElementImage instanceof \DOMElement) {
667
            $relImg = $this->arrayRels[$oSlide->getRelsIndex()][$oElementImage->getAttribute('r:embed')];
668
            if (is_array($relImg)) {
669
                // File
670
                $pathImage = 'ppt/slides/' . $relImg['Target'];
671
                $pathImage = explode('/', $pathImage);
672
                foreach ($pathImage as $key => $partPath) {
673
                    if ($partPath == '..') {
674
                        unset($pathImage[$key - 1]);
675
                        unset($pathImage[$key]);
676
                    }
677
                }
678
                $pathImage = implode('/', $pathImage);
679
                $contentImg = $this->oZip->getFromName($pathImage);
680
681
                $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
682
                file_put_contents($tmpBkgImg, $contentImg);
683
                // Background
684
                $oBackground = new Slide\Background\Image();
685
                $oBackground->setPath($tmpBkgImg);
686
                // Slide Background
687
                $oSlide->setBackground($oBackground);
688
            }
689
        }
690 4
    }
691
692
    /**
693
     * @param string $baseFile
694
     * @param Slide $oSlide
695
     */
696
    protected function loadSlideNote($baseFile, Slide $oSlide)
697
    {
698
        $sPart = $this->oZip->getFromName('ppt/notesSlides/' . $baseFile);
699
        $xmlReader = new XMLReader();
700
        if ($xmlReader->getDomFromString($sPart)) {
701
            $oNote = $oSlide->getNote();
702
703
            $arrayElements = $xmlReader->getElements('/p:notes/p:cSld/p:spTree/*');
704
            if ($arrayElements) {
705
                $this->loadSlideShapes($oNote, $arrayElements, $xmlReader);
706
            }
707
        }
708
    }
709
710
    /**
711
     * @param XMLReader $document
712
     * @param \DOMElement $node
713
     * @param AbstractSlide $oSlide
714
     */
715 3
    protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
716
    {
717
        // Core
718 3
        $oShape = new Gd();
719 3
        $oShape->getShadow()->setVisible(false);
720
        // Variables
721 3
        $fileRels = $oSlide->getRelsIndex();
722
723 3
        $oElement = $document->getElement('p:nvPicPr/p:cNvPr', $node);
724 3
        if ($oElement instanceof \DOMElement) {
725 3
            $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : '');
726 3
            $oShape->setDescription($oElement->hasAttribute('descr') ? $oElement->getAttribute('descr') : '');
727
        }
728
729 3
        $oElement = $document->getElement('p:blipFill/a:blip', $node);
730 3
        if ($oElement instanceof \DOMElement) {
731 3
            if ($oElement->hasAttribute('r:embed') && isset($this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'])) {
732 3
                $pathImage = 'ppt/slides/' . $this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'];
733 3
                $pathImage = explode('/', $pathImage);
734 3
                foreach ($pathImage as $key => $partPath) {
735 3
                    if ($partPath == '..') {
736 3
                        unset($pathImage[$key - 1]);
737 3
                        unset($pathImage[$key]);
738
                    }
739
                }
740 3
                $pathImage = implode('/', $pathImage);
741 3
                $imageFile = $this->oZip->getFromName($pathImage);
742 3
                if (!empty($imageFile)) {
743 3
                    $oShape->setImageResource(imagecreatefromstring($imageFile));
744
                }
745
            }
746
        }
747
748 3
        $oElement = $document->getElement('p:spPr', $node);
749 3
        if ($oElement instanceof \DOMElement) {
750 3
            $oFill = $this->loadStyleFill($document, $oElement);
751 3
            $oShape->setFill($oFill);
752
        }
753
754 3
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
755 3
        if ($oElement instanceof \DOMElement) {
756 3
            if ($oElement->hasAttribute('rot')) {
757 3
                $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
758
            }
759
        }
760
761 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
762 3
        if ($oElement instanceof \DOMElement) {
763 3
            if ($oElement->hasAttribute('x')) {
764 3
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
765
            }
766 3
            if ($oElement->hasAttribute('y')) {
767 3
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
768
            }
769
        }
770
771 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
772 3
        if ($oElement instanceof \DOMElement) {
773 3
            if ($oElement->hasAttribute('cx')) {
774 3
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
775
            }
776 3
            if ($oElement->hasAttribute('cy')) {
777 3
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
778
            }
779
        }
780
781 3
        $oElement = $document->getElement('p:spPr/a:effectLst', $node);
782 3
        if ($oElement instanceof \DOMElement) {
783 3
            $oShape->getShadow()->setVisible(true);
784
785 3
            $oSubElement = $document->getElement('a:outerShdw', $oElement);
786 3
            if ($oSubElement instanceof \DOMElement) {
787 3
                if ($oSubElement->hasAttribute('blurRad')) {
788 3
                    $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels($oSubElement->getAttribute('blurRad')));
789
                }
790 3
                if ($oSubElement->hasAttribute('dist')) {
791 3
                    $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels($oSubElement->getAttribute('dist')));
792
                }
793 3
                if ($oSubElement->hasAttribute('dir')) {
794 3
                    $oShape->getShadow()->setDirection(CommonDrawing::angleToDegrees($oSubElement->getAttribute('dir')));
795
                }
796 3
                if ($oSubElement->hasAttribute('algn')) {
797 3
                    $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn'));
798
                }
799
            }
800
801 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement);
802 3
            if ($oSubElement instanceof \DOMElement) {
803 3
                if ($oSubElement->hasAttribute('val')) {
804 3
                    $oColor = new Color();
805 3
                    $oColor->setRGB($oSubElement->getAttribute('val'));
806 3
                    $oShape->getShadow()->setColor($oColor);
807
                }
808
            }
809
810 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement);
811 3
            if ($oSubElement instanceof \DOMElement) {
812 3
                if ($oSubElement->hasAttribute('val')) {
813 3
                    $oShape->getShadow()->setAlpha((int)$oSubElement->getAttribute('val') / 1000);
814
                }
815
            }
816
        }
817
818 3
        $oSlide->addShape($oShape);
819 3
    }
820
821
    /**
822
     * @param XMLReader $document
823
     * @param \DOMElement $node
824
     * @param AbstractSlide $oSlide
825
     * @throws \Exception
826
     */
827 4
    protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oSlide)
828
    {
829 4
        if (!$document->elementExists('p:txBody/a:p/a:r', $node)) {
830 4
            return;
831
        }
832
        // Core
833 4
        $oShape = $oSlide->createRichTextShape();
834 4
        $oShape->setParagraphs(array());
835
        // Variables
836 4
        if ($oSlide instanceof AbstractSlide) {
837 4
            $this->fileRels = $oSlide->getRelsIndex();
838
        }
839
840 4
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
841 4
        if ($oElement instanceof \DOMElement && $oElement->hasAttribute('rot')) {
842 4
            $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
843
        }
844
845 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
846 4
        if ($oElement instanceof \DOMElement) {
847 4
            if ($oElement->hasAttribute('x')) {
848 4
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
849
            }
850 4
            if ($oElement->hasAttribute('y')) {
851 4
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
852
            }
853
        }
854
855 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
856 4
        if ($oElement instanceof \DOMElement) {
857 4
            if ($oElement->hasAttribute('cx')) {
858 4
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
859
            }
860 4
            if ($oElement->hasAttribute('cy')) {
861 4
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
862
            }
863
        }
864
865 4
        $oElement = $document->getElement('p:nvSpPr/p:nvPr/p:ph', $node);
866 4
        if ($oElement instanceof \DOMElement) {
867 4
            if ($oElement->hasAttribute('type')) {
868 4
                $placeholder = new Placeholder($oElement->getAttribute('type'));
869 4
                $oShape->setPlaceHolder($placeholder);
870
            }
871
        }
872
873 4
        $arrayElements = $document->getElements('p:txBody/a:p', $node);
874 4
        foreach ($arrayElements as $oElement) {
875 4
            $this->loadParagraph($document, $oElement, $oShape);
876
        }
877
878 4
        if (count($oShape->getParagraphs()) > 0) {
879 4
            $oShape->setActiveParagraph(0);
880
        }
881 4
    }
882
883
    /**
884
     * @param XMLReader $document
885
     * @param \DOMElement $node
886
     * @param AbstractSlide $oSlide
887
     * @throws \Exception
888
     */
889
    protected function loadShapeTable(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
890
    {
891
        $this->fileRels = $oSlide->getRelsIndex();
892
893
        $oShape = $oSlide->createTableShape();
894
895
        $oElement = $document->getElement('p:cNvPr', $node);
896
        if ($oElement instanceof \DOMElement) {
897
            if ($oElement->hasAttribute('name')) {
898
                $oShape->setName($oElement->getAttribute('name'));
899
            }
900
            if ($oElement->hasAttribute('descr')) {
901
                $oShape->setDescription($oElement->getAttribute('descr'));
902
            }
903
        }
904
905
        $oElement = $document->getElement('p:xfrm/a:off', $node);
906
        if ($oElement instanceof \DOMElement) {
907
            if ($oElement->hasAttribute('x')) {
908
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
909
            }
910
            if ($oElement->hasAttribute('y')) {
911
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
912
            }
913
        }
914
915
        $oElement = $document->getElement('p:xfrm/a:ext', $node);
916
        if ($oElement instanceof \DOMElement) {
917
            if ($oElement->hasAttribute('cx')) {
918
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
919
            }
920
            if ($oElement->hasAttribute('cy')) {
921
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
922
            }
923
        }
924
925
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tblGrid/a:gridCol', $node);
926
        $oShape->setNumColumns($arrayElements->length);
927
        $oShape->createRow();
928
        foreach ($arrayElements as $key => $oElement) {
929
            if ($oElement instanceof \DOMElement && $oElement->getAttribute('w')) {
930
                $oShape->getRow(0)->getCell($key)->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('w')));
931
            }
932
        }
933
934
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tr', $node);
935
        foreach ($arrayElements as $keyRow => $oElementRow) {
936
            if (!($oElementRow instanceof \DOMElement)) {
937
                continue;
938
            }
939
            $oRow = $oShape->getRow($keyRow, true);
940
            if (is_null($oRow)) {
941
                $oRow = $oShape->createRow();
942
            }
943
            if ($oElementRow->hasAttribute('h')) {
944
                $oRow->setHeight(CommonDrawing::emuToPixels($oElementRow->getAttribute('h')));
945
            }
946
            $arrayElementsCell = $document->getElements('a:tc', $oElementRow);
947
            foreach ($arrayElementsCell as $keyCell => $oElementCell) {
948
                if (!($oElementCell instanceof \DOMElement)) {
949
                    continue;
950
                }
951
                $oCell = $oRow->getCell($keyCell);
952
                $oCell->setParagraphs(array());
953
                if ($oElementCell->hasAttribute('gridSpan')) {
954
                    $oCell->setColSpan($oElementCell->getAttribute('gridSpan'));
955
                }
956
                if ($oElementCell->hasAttribute('rowSpan')) {
957
                    $oCell->setRowSpan($oElementCell->getAttribute('rowSpan'));
958
                }
959
960
                foreach ($document->getElements('a:txBody/a:p', $oElementCell) as $oElementPara) {
961
                    $this->loadParagraph($document, $oElementPara, $oCell);
0 ignored issues
show
Bug introduced by
It seems like $oCell defined by $oRow->getCell($keyCell) on line 951 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...
962
                }
963
964
                $oElementTcPr = $document->getElement('a:tcPr', $oElementCell);
965
                if ($oElementTcPr instanceof \DOMElement) {
966
                    $numParagraphs = count($oCell->getParagraphs());
967
                    if ($numParagraphs > 0) {
968
                        if ($oElementTcPr->hasAttribute('vert')) {
969
                            $oCell->getParagraph(0)->getAlignment()->setTextDirection($oElementTcPr->getAttribute('vert'));
970
                        }
971
                        if ($oElementTcPr->hasAttribute('anchor')) {
972
                            $oCell->getParagraph(0)->getAlignment()->setVertical($oElementTcPr->getAttribute('anchor'));
973
                        }
974
                        if ($oElementTcPr->hasAttribute('marB')) {
975
                            $oCell->getParagraph(0)->getAlignment()->setMarginBottom($oElementTcPr->getAttribute('marB'));
976
                        }
977
                        if ($oElementTcPr->hasAttribute('marL')) {
978
                            $oCell->getParagraph(0)->getAlignment()->setMarginLeft($oElementTcPr->getAttribute('marL'));
979
                        }
980
                        if ($oElementTcPr->hasAttribute('marR')) {
981
                            $oCell->getParagraph(0)->getAlignment()->setMarginRight($oElementTcPr->getAttribute('marR'));
982
                        }
983
                        if ($oElementTcPr->hasAttribute('marT')) {
984
                            $oCell->getParagraph(0)->getAlignment()->setMarginTop($oElementTcPr->getAttribute('marT'));
985
                        }
986
                    }
987
988
                    $oFill = $this->loadStyleFill($document, $oElementTcPr);
989
                    if ($oFill instanceof Fill) {
990
                        $oCell->setFill($oFill);
991
                    }
992
993
                    $oBorders = new Borders();
994
                    $oElementBorderL = $document->getElement('a:lnL', $oElementTcPr);
995
                    if ($oElementBorderL instanceof \DOMElement) {
996
                        $this->loadStyleBorder($document, $oElementBorderL, $oBorders->getLeft());
997
                    }
998
                    $oElementBorderR = $document->getElement('a:lnR', $oElementTcPr);
999
                    if ($oElementBorderR instanceof \DOMElement) {
1000
                        $this->loadStyleBorder($document, $oElementBorderR, $oBorders->getRight());
1001
                    }
1002
                    $oElementBorderT = $document->getElement('a:lnT', $oElementTcPr);
1003
                    if ($oElementBorderT instanceof \DOMElement) {
1004
                        $this->loadStyleBorder($document, $oElementBorderT, $oBorders->getTop());
1005
                    }
1006
                    $oElementBorderB = $document->getElement('a:lnB', $oElementTcPr);
1007
                    if ($oElementBorderB instanceof \DOMElement) {
1008
                        $this->loadStyleBorder($document, $oElementBorderB, $oBorders->getBottom());
1009
                    }
1010
                    $oElementBorderDiagDown = $document->getElement('a:lnTlToBr', $oElementTcPr);
1011
                    if ($oElementBorderDiagDown instanceof \DOMElement) {
1012
                        $this->loadStyleBorder($document, $oElementBorderDiagDown, $oBorders->getDiagonalDown());
1013
                    }
1014
                    $oElementBorderDiagUp = $document->getElement('a:lnBlToTr', $oElementTcPr);
1015
                    if ($oElementBorderDiagUp instanceof \DOMElement) {
1016
                        $this->loadStyleBorder($document, $oElementBorderDiagUp, $oBorders->getDiagonalUp());
1017
                    }
1018
                    $oCell->setBorders($oBorders);
1019
                }
1020
            }
1021
        }
1022
    }
1023
1024
    /**
1025
     * @param XMLReader $document
1026
     * @param \DOMElement $oElement
1027
     * @param Cell|RichText $oShape
1028
     * @throws \Exception
1029
     */
1030 4
    protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oShape)
1031
    {
1032
        // Core
1033 4
        $oParagraph = $oShape->createParagraph();
1034 4
        $oParagraph->setRichTextElements(array());
1035
1036 4
        $oSubElement = $document->getElement('a:pPr', $oElement);
1037 4
        if ($oSubElement instanceof \DOMElement) {
1038 4
            if ($oSubElement->hasAttribute('algn')) {
1039 3
                $oParagraph->getAlignment()->setHorizontal($oSubElement->getAttribute('algn'));
1040
            }
1041 4
            if ($oSubElement->hasAttribute('fontAlgn')) {
1042 3
                $oParagraph->getAlignment()->setVertical($oSubElement->getAttribute('fontAlgn'));
1043
            }
1044 4
            if ($oSubElement->hasAttribute('marL')) {
1045 3
                $oParagraph->getAlignment()->setMarginLeft(CommonDrawing::emuToPixels($oSubElement->getAttribute('marL')));
1046
            }
1047 4
            if ($oSubElement->hasAttribute('marR')) {
1048 3
                $oParagraph->getAlignment()->setMarginRight(CommonDrawing::emuToPixels($oSubElement->getAttribute('marR')));
1049
            }
1050 4
            if ($oSubElement->hasAttribute('indent')) {
1051 3
                $oParagraph->getAlignment()->setIndent(CommonDrawing::emuToPixels($oSubElement->getAttribute('indent')));
1052
            }
1053 4
            if ($oSubElement->hasAttribute('lvl')) {
1054 4
                $oParagraph->getAlignment()->setLevel($oSubElement->getAttribute('lvl'));
1055
            }
1056
1057 4
            $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NONE);
1058
1059 4
            $oElementBuFont = $document->getElement('a:buFont', $oSubElement);
1060 4
            if ($oElementBuFont instanceof \DOMElement) {
1061 3
                if ($oElementBuFont->hasAttribute('typeface')) {
1062 3
                    $oParagraph->getBulletStyle()->setBulletFont($oElementBuFont->getAttribute('typeface'));
1063
                }
1064
            }
1065 4
            $oElementBuChar = $document->getElement('a:buChar', $oSubElement);
1066 4
            if ($oElementBuChar instanceof \DOMElement) {
1067 3
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET);
1068 3
                if ($oElementBuChar->hasAttribute('char')) {
1069 3
                    $oParagraph->getBulletStyle()->setBulletChar($oElementBuChar->getAttribute('char'));
1070
                }
1071
            }
1072 4
            $oElementBuAutoNum = $document->getElement('a:buAutoNum', $oSubElement);
1073 4
            if ($oElementBuAutoNum instanceof \DOMElement) {
1074
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NUMERIC);
1075
                if ($oElementBuAutoNum->hasAttribute('type')) {
1076
                    $oParagraph->getBulletStyle()->setBulletNumericStyle($oElementBuAutoNum->getAttribute('type'));
1077
                }
1078
                if ($oElementBuAutoNum->hasAttribute('startAt') && $oElementBuAutoNum->getAttribute('startAt') != 1) {
1079
                    $oParagraph->getBulletStyle()->setBulletNumericStartAt($oElementBuAutoNum->getAttribute('startAt'));
1080
                }
1081
            }
1082 4
            $oElementBuClr = $document->getElement('a:buClr', $oSubElement);
1083 4
            if ($oElementBuClr instanceof \DOMElement) {
1084
                $oColor = new Color();
1085
                /**
1086
                 * @todo Create protected for reading Color
1087
                 */
1088
                $oElementColor = $document->getElement('a:srgbClr', $oElementBuClr);
1089
                if ($oElementColor instanceof \DOMElement) {
1090
                    $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
1091
                }
1092
                $oParagraph->getBulletStyle()->setBulletColor($oColor);
1093
            }
1094
        }
1095 4
        $arraySubElements = $document->getElements('(a:r|a:br)', $oElement);
1096 4
        foreach ($arraySubElements as $oSubElement) {
1097 4
            if ($oSubElement->tagName == 'a:br') {
1098 3
                $oParagraph->createBreak();
1099
            }
1100 4
            if ($oSubElement->tagName == 'a:r') {
1101 4
                $oElementrPr = $document->getElement('a:rPr', $oSubElement);
1102 4
                if (is_object($oElementrPr)) {
1103 4
                    $oText = $oParagraph->createTextRun();
1104
1105 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...
1106 3
                        $att = $oElementrPr->getAttribute('b');
1107 3
                        $oText->getFont()->setBold($att == 'true' || $att == '1' ? true : false);
1108
                    }
1109 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...
1110 3
                        $att = $oElementrPr->getAttribute('i');
1111 3
                        $oText->getFont()->setItalic($att == 'true' || $att == '1' ? true : false);
1112
                    }
1113 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...
1114 3
                        $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true);
1115
                    }
1116 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...
1117 3
                        $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100));
1118
                    }
1119 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...
1120 3
                        $oText->getFont()->setUnderline($oElementrPr->getAttribute('u'));
1121
                    }
1122
                    // Color
1123 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...
1124 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...
1125 3
                        $oColor = new Color();
1126 3
                        $oColor->setRGB($oElementSrgbClr->getAttribute('val'));
1127 3
                        $oText->getFont()->setColor($oColor);
1128
                    }
1129
                    // Hyperlink
1130 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...
1131 4
                    if (is_object($oElementHlinkClick)) {
1132 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...
1133 3
                            $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip'));
1134
                        }
1135 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...
1136 3
                            $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']);
1137
                        }
1138
                    }
1139
                    //} else {
1140
                    // $oText = $oParagraph->createText();
1141
1142 4
                    $oSubSubElement = $document->getElement('a:t', $oSubElement);
1143 4
                    $oText->setText($oSubSubElement->nodeValue);
1144
                }
1145
            }
1146
        }
1147 4
    }
1148
1149
    /**
1150
     * @param XMLReader $xmlReader
1151
     * @param \DOMElement $oElement
1152
     * @param Border $oBorder
1153
     */
1154
    protected function loadStyleBorder(XMLReader $xmlReader, \DOMElement $oElement, Border $oBorder)
1155
    {
1156
        if ($oElement->hasAttribute('w')) {
1157
            $oBorder->setLineWidth($oElement->getAttribute('w') / 12700);
1158
        }
1159
        if ($oElement->hasAttribute('cmpd')) {
1160
            $oBorder->setLineStyle($oElement->getAttribute('cmpd'));
1161
        }
1162
1163
        $oElementNoFill = $xmlReader->getElement('a:noFill', $oElement);
1164
        if ($oElementNoFill instanceof \DOMElement && $oBorder->getLineStyle() == Border::LINE_SINGLE) {
1165
            $oBorder->setLineStyle(Border::LINE_NONE);
1166
        }
1167
1168
        $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
1169
        if ($oElementColor instanceof \DOMElement) {
1170
            $oBorder->setColor($this->loadStyleColor($xmlReader, $oElementColor));
1171
        }
1172
1173
        $oElementDashStyle = $xmlReader->getElement('a:prstDash', $oElement);
1174
        if ($oElementDashStyle instanceof \DOMElement && $oElementDashStyle->hasAttribute('val')) {
1175
            $oBorder->setDashStyle($oElementDashStyle->getAttribute('val'));
1176
        }
1177
    }
1178
1179
    /**
1180
     * @param XMLReader $xmlReader
1181
     * @param \DOMElement $oElement
1182
     * @return Color
1183
     */
1184
    protected function loadStyleColor(XMLReader $xmlReader, \DOMElement $oElement)
1185
    {
1186
        $oColor = new Color();
1187
        $oColor->setRGB($oElement->getAttribute('val'));
1188
        $oElementAlpha = $xmlReader->getElement('a:alpha', $oElement);
1189
        if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1190
            $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1191
            $oColor->setRGB($oElement->getAttribute('val'), $alpha);
1192
        }
1193
        return $oColor;
1194
    }
1195
1196
    /**
1197
     * @param XMLReader $xmlReader
1198
     * @param \DOMElement $oElement
1199
     * @return null|Fill
1200
     */
1201 3
    protected function loadStyleFill(XMLReader $xmlReader, \DOMElement $oElement)
1202
    {
1203
        // Gradient fill
1204 3
        $oElementFill = $xmlReader->getElement('a:gradFill', $oElement);
1205 3
        if ($oElementFill instanceof \DOMElement) {
1206
            $oFill = new Fill();
1207
            $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR);
1208
1209
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill);
1210
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1211
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1212
            }
1213
1214
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill);
1215
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1216
                $oFill->setEndColor($this->loadStyleColor($xmlReader, $oElementColor));
1217
            }
1218
1219
            $oRotation = $xmlReader->getElement('a:lin', $oElementFill);
1220
            if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) {
1221
                $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang')));
1222
            }
1223
            return $oFill;
1224
        }
1225
1226
        // Solid fill
1227 3
        $oElementFill = $xmlReader->getElement('a:solidFill', $oElement);
1228 3
        if ($oElementFill instanceof \DOMElement) {
1229
            $oFill = new Fill();
1230
            $oFill->setFillType(Fill::FILL_SOLID);
1231
1232
            $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill);
1233
            if ($oElementColor instanceof \DOMElement) {
1234
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1235
            }
1236
            return $oFill;
1237
        }
1238 3
        return null;
1239
    }
1240
1241
    /**
1242
     * @param string $fileRels
1243
     * @return string
1244
     */
1245 4
    protected function loadRels($fileRels)
1246
    {
1247 4
        $sPart = $this->oZip->getFromName($fileRels);
1248 4
        if ($sPart !== false) {
1249 4
            $xmlReader = new XMLReader();
1250 4
            if ($xmlReader->getDomFromString($sPart)) {
1251 4
                foreach ($xmlReader->getElements('*') as $oNode) {
1252 4
                    if (!($oNode instanceof \DOMElement)) {
1253
                        continue;
1254
                    }
1255 4
                    $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array(
1256 4
                        'Target' => $oNode->getAttribute('Target'),
1257 4
                        'Type' => $oNode->getAttribute('Type'),
1258
                    );
1259
                }
1260
            }
1261
        }
1262 4
    }
1263
1264
    /**
1265
     * @param $oSlide
1266
     * @param \DOMNodeList $oElements
1267
     * @param XMLReader $xmlReader
1268
     * @internal param $baseFile
1269
     */
1270 4
    protected function loadSlideShapes($oSlide, $oElements, $xmlReader)
1271
    {
1272 4
        foreach ($oElements as $oNode) {
1273 4
            switch ($oNode->tagName) {
1274 4
                case 'p:graphicFrame':
1275
                    $this->loadShapeTable($xmlReader, $oNode, $oSlide);
1276
                    break;
1277 4
                case 'p:pic':
1278 3
                    $this->loadShapeDrawing($xmlReader, $oNode, $oSlide);
1279 3
                    break;
1280 4
                case 'p:sp':
1281 4
                    $this->loadShapeRichText($xmlReader, $oNode, $oSlide);
1282 4
                    break;
1283 4
                default:
1284
                    //var_export($oNode->tagName);
1285
            }
1286
        }
1287 4
    }
1288
}
1289