Completed
Pull Request — develop (#546)
by Franck
10:13
created

PowerPoint2007::loadLayoutSlide()   B

Complexity

Conditions 9
Paths 17

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 9.0036

Importance

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