Completed
Pull Request — develop (#401)
by Franck
08:07
created

PowerPoint2007::loadSlide()   D

Complexity

Conditions 15
Paths 105

Size

Total Lines 83
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 74.398

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 83
ccs 19
cts 53
cp 0.3585
rs 4.8263
cc 15
eloc 52
nc 105
nop 2
crap 74.398

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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/a:xfrm', $node);
749 3
        if ($oElement instanceof \DOMElement) {
750 3
            if ($oElement->hasAttribute('rot')) {
751 3
                $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
752
            }
753
        }
754
755 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
756 3
        if ($oElement instanceof \DOMElement) {
757 3
            if ($oElement->hasAttribute('x')) {
758 3
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
759
            }
760 3
            if ($oElement->hasAttribute('y')) {
761 3
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
762
            }
763
        }
764
765 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
766 3
        if ($oElement instanceof \DOMElement) {
767 3
            if ($oElement->hasAttribute('cx')) {
768 3
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
769
            }
770 3
            if ($oElement->hasAttribute('cy')) {
771 3
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
772
            }
773
        }
774
775 3
        $oElement = $document->getElement('p:spPr/a:effectLst', $node);
776 3
        if ($oElement instanceof \DOMElement) {
777 3
            $oShape->getShadow()->setVisible(true);
778
779 3
            $oSubElement = $document->getElement('a:outerShdw', $oElement);
780 3
            if ($oSubElement instanceof \DOMElement) {
781 3
                if ($oSubElement->hasAttribute('blurRad')) {
782 3
                    $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels($oSubElement->getAttribute('blurRad')));
783
                }
784 3
                if ($oSubElement->hasAttribute('dist')) {
785 3
                    $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels($oSubElement->getAttribute('dist')));
786
                }
787 3
                if ($oSubElement->hasAttribute('dir')) {
788 3
                    $oShape->getShadow()->setDirection(CommonDrawing::angleToDegrees($oSubElement->getAttribute('dir')));
789
                }
790 3
                if ($oSubElement->hasAttribute('algn')) {
791 3
                    $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn'));
792
                }
793
            }
794
795 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement);
796 3
            if ($oSubElement instanceof \DOMElement) {
797 3
                if ($oSubElement->hasAttribute('val')) {
798 3
                    $oColor = new Color();
799 3
                    $oColor->setRGB($oSubElement->getAttribute('val'));
800 3
                    $oShape->getShadow()->setColor($oColor);
801
                }
802
            }
803
804 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement);
805 3
            if ($oSubElement instanceof \DOMElement) {
806 3
                if ($oSubElement->hasAttribute('val')) {
807 3
                    $oShape->getShadow()->setAlpha((int)$oSubElement->getAttribute('val') / 1000);
808
                }
809
            }
810
        }
811
812 3
        $oSlide->addShape($oShape);
813 3
    }
814
815
    /**
816
     * @param XMLReader $document
817
     * @param \DOMElement $node
818
     * @param AbstractSlide $oSlide
819
     * @throws \Exception
820
     */
821 4
    protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oSlide)
822
    {
823 4
        if (!$document->elementExists('p:txBody/a:p/a:r', $node)) {
824 4
            return;
825
        }
826
        // Core
827 4
        $oShape = $oSlide->createRichTextShape();
828 4
        $oShape->setParagraphs(array());
829
        // Variables
830 4
        if ($oSlide instanceof AbstractSlide) {
831 4
            $this->fileRels = $oSlide->getRelsIndex();
832
        }
833
834 4
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
835 4
        if ($oElement instanceof \DOMElement && $oElement->hasAttribute('rot')) {
836 4
            $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
837
        }
838
839 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
840 4
        if ($oElement instanceof \DOMElement) {
841 4
            if ($oElement->hasAttribute('x')) {
842 4
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
843
            }
844 4
            if ($oElement->hasAttribute('y')) {
845 4
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
846
            }
847
        }
848
849 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
850 4
        if ($oElement instanceof \DOMElement) {
851 4
            if ($oElement->hasAttribute('cx')) {
852 4
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
853
            }
854 4
            if ($oElement->hasAttribute('cy')) {
855 4
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
856
            }
857
        }
858
859 4
        $oElement = $document->getElement('p:nvSpPr/p:nvPr/p:ph', $node);
860 4
        if ($oElement instanceof \DOMElement) {
861 4
            if ($oElement->hasAttribute('type')) {
862 4
                $placeholder = new Placeholder($oElement->getAttribute('type'));
863 4
                $oShape->setPlaceHolder($placeholder);
864
            }
865
        }
866
867 4
        $arrayElements = $document->getElements('p:txBody/a:p', $node);
868 4
        foreach ($arrayElements as $oElement) {
869 4
            $this->loadParagraph($document, $oElement, $oShape);
870
        }
871
872 4
        if (count($oShape->getParagraphs()) > 0) {
873 4
            $oShape->setActiveParagraph(0);
874
        }
875 4
    }
876
877
    /**
878
     * @param XMLReader $document
879
     * @param \DOMElement $node
880
     * @param AbstractSlide $oSlide
881
     * @throws \Exception
882
     */
883
    protected function loadShapeTable(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
884
    {
885
        $this->fileRels = $oSlide->getRelsIndex();
886
887
        $oShape = $oSlide->createTableShape();
888
889
        $oElement = $document->getElement('p:cNvPr', $node);
890
        if ($oElement instanceof \DOMElement) {
891
            if ($oElement->hasAttribute('name')) {
892
                $oShape->setName($oElement->getAttribute('name'));
893
            }
894
            if ($oElement->hasAttribute('descr')) {
895
                $oShape->setDescription($oElement->getAttribute('descr'));
896
            }
897
        }
898
899
        $oElement = $document->getElement('p:xfrm/a:off', $node);
900
        if ($oElement instanceof \DOMElement) {
901
            if ($oElement->hasAttribute('x')) {
902
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
903
            }
904
            if ($oElement->hasAttribute('y')) {
905
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
906
            }
907
        }
908
909
        $oElement = $document->getElement('p:xfrm/a:ext', $node);
910
        if ($oElement instanceof \DOMElement) {
911
            if ($oElement->hasAttribute('cx')) {
912
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
913
            }
914
            if ($oElement->hasAttribute('cy')) {
915
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
916
            }
917
        }
918
919
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tblGrid/a:gridCol', $node);
920
        $oShape->setNumColumns($arrayElements->length);
921
        $oShape->createRow();
922
        foreach ($arrayElements as $key => $oElement) {
923
            if ($oElement instanceof \DOMElement && $oElement->getAttribute('w')) {
924
                $oShape->getRow(0)->getCell($key)->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('w')));
925
            }
926
        }
927
928
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tr', $node);
929
        foreach ($arrayElements as $keyRow => $oElementRow) {
930
            if (!($oElementRow instanceof \DOMElement)) {
931
                continue;
932
            }
933
            $oRow = $oShape->getRow($keyRow, true);
934
            if (is_null($oRow)) {
935
                $oRow = $oShape->createRow();
936
            }
937
            if ($oElementRow->hasAttribute('h')) {
938
                $oRow->setHeight(CommonDrawing::emuToPixels($oElementRow->getAttribute('h')));
939
            }
940
            $arrayElementsCell = $document->getElements('a:tc', $oElementRow);
941
            foreach ($arrayElementsCell as $keyCell => $oElementCell) {
942
                if (!($oElementCell instanceof \DOMElement)) {
943
                    continue;
944
                }
945
                $oCell = $oRow->getCell($keyCell);
946
                $oCell->setParagraphs(array());
947
                if ($oElementCell->hasAttribute('gridSpan')) {
948
                    $oCell->setColSpan($oElementCell->getAttribute('gridSpan'));
949
                }
950
                if ($oElementCell->hasAttribute('rowSpan')) {
951
                    $oCell->setRowSpan($oElementCell->getAttribute('rowSpan'));
952
                }
953
954
                foreach ($document->getElements('a:txBody/a:p', $oElementCell) as $oElementPara) {
955
                    $this->loadParagraph($document, $oElementPara, $oCell);
0 ignored issues
show
Bug introduced by
It seems like $oCell defined by $oRow->getCell($keyCell) on line 945 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...
956
                }
957
958
                $oElementTcPr = $document->getElement('a:tcPr', $oElementCell);
959
                if ($oElementTcPr instanceof \DOMElement) {
960
                    $numParagraphs = count($oCell->getParagraphs());
961
                    if ($numParagraphs > 0) {
962
                        if ($oElementTcPr->hasAttribute('vert')) {
963
                            $oCell->getParagraph(0)->getAlignment()->setTextDirection($oElementTcPr->getAttribute('vert'));
964
                        }
965
                        if ($oElementTcPr->hasAttribute('anchor')) {
966
                            $oCell->getParagraph(0)->getAlignment()->setVertical($oElementTcPr->getAttribute('anchor'));
967
                        }
968
                        if ($oElementTcPr->hasAttribute('marB')) {
969
                            $oCell->getParagraph(0)->getAlignment()->setMarginBottom($oElementTcPr->getAttribute('marB'));
970
                        }
971
                        if ($oElementTcPr->hasAttribute('marL')) {
972
                            $oCell->getParagraph(0)->getAlignment()->setMarginLeft($oElementTcPr->getAttribute('marL'));
973
                        }
974
                        if ($oElementTcPr->hasAttribute('marR')) {
975
                            $oCell->getParagraph(0)->getAlignment()->setMarginRight($oElementTcPr->getAttribute('marR'));
976
                        }
977
                        if ($oElementTcPr->hasAttribute('marT')) {
978
                            $oCell->getParagraph(0)->getAlignment()->setMarginTop($oElementTcPr->getAttribute('marT'));
979
                        }
980
                    }
981
982
                    $oFill = $this->loadStyleFill($document, $oElementTcPr);
983
                    if ($oFill instanceof Fill) {
984
                        $oCell->setFill($oFill);
985
                    }
986
987
                    $oBorders = new Borders();
988
                    $oElementBorderL = $document->getElement('a:lnL', $oElementTcPr);
989
                    if ($oElementBorderL instanceof \DOMElement) {
990
                        $this->loadStyleBorder($document, $oElementBorderL, $oBorders->getLeft());
991
                    }
992
                    $oElementBorderR = $document->getElement('a:lnR', $oElementTcPr);
993
                    if ($oElementBorderR instanceof \DOMElement) {
994
                        $this->loadStyleBorder($document, $oElementBorderR, $oBorders->getRight());
995
                    }
996
                    $oElementBorderT = $document->getElement('a:lnT', $oElementTcPr);
997
                    if ($oElementBorderT instanceof \DOMElement) {
998
                        $this->loadStyleBorder($document, $oElementBorderT, $oBorders->getTop());
999
                    }
1000
                    $oElementBorderB = $document->getElement('a:lnB', $oElementTcPr);
1001
                    if ($oElementBorderB instanceof \DOMElement) {
1002
                        $this->loadStyleBorder($document, $oElementBorderB, $oBorders->getBottom());
1003
                    }
1004
                    $oElementBorderDiagDown = $document->getElement('a:lnTlToBr', $oElementTcPr);
1005
                    if ($oElementBorderDiagDown instanceof \DOMElement) {
1006
                        $this->loadStyleBorder($document, $oElementBorderDiagDown, $oBorders->getDiagonalDown());
1007
                    }
1008
                    $oElementBorderDiagUp = $document->getElement('a:lnBlToTr', $oElementTcPr);
1009
                    if ($oElementBorderDiagUp instanceof \DOMElement) {
1010
                        $this->loadStyleBorder($document, $oElementBorderDiagUp, $oBorders->getDiagonalUp());
1011
                    }
1012
                    $oCell->setBorders($oBorders);
1013
                }
1014
            }
1015
        }
1016
    }
1017
1018
    /**
1019
     * @param XMLReader $document
1020
     * @param \DOMElement $oElement
1021
     * @param Cell|RichText $oShape
1022
     * @throws \Exception
1023
     */
1024 4
    protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oShape)
1025
    {
1026
        // Core
1027 4
        $oParagraph = $oShape->createParagraph();
1028 4
        $oParagraph->setRichTextElements(array());
1029
1030 4
        $oSubElement = $document->getElement('a:pPr', $oElement);
1031 4
        if ($oSubElement instanceof \DOMElement) {
1032 4
            if ($oSubElement->hasAttribute('algn')) {
1033 3
                $oParagraph->getAlignment()->setHorizontal($oSubElement->getAttribute('algn'));
1034
            }
1035 4
            if ($oSubElement->hasAttribute('fontAlgn')) {
1036 3
                $oParagraph->getAlignment()->setVertical($oSubElement->getAttribute('fontAlgn'));
1037
            }
1038 4
            if ($oSubElement->hasAttribute('marL')) {
1039 3
                $oParagraph->getAlignment()->setMarginLeft(CommonDrawing::emuToPixels($oSubElement->getAttribute('marL')));
1040
            }
1041 4
            if ($oSubElement->hasAttribute('marR')) {
1042 3
                $oParagraph->getAlignment()->setMarginRight(CommonDrawing::emuToPixels($oSubElement->getAttribute('marR')));
1043
            }
1044 4
            if ($oSubElement->hasAttribute('indent')) {
1045 3
                $oParagraph->getAlignment()->setIndent(CommonDrawing::emuToPixels($oSubElement->getAttribute('indent')));
1046
            }
1047 4
            if ($oSubElement->hasAttribute('lvl')) {
1048 4
                $oParagraph->getAlignment()->setLevel($oSubElement->getAttribute('lvl'));
1049
            }
1050
1051 4
            $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NONE);
1052
1053 4
            $oElementBuFont = $document->getElement('a:buFont', $oSubElement);
1054 4
            if ($oElementBuFont instanceof \DOMElement) {
1055 3
                if ($oElementBuFont->hasAttribute('typeface')) {
1056 3
                    $oParagraph->getBulletStyle()->setBulletFont($oElementBuFont->getAttribute('typeface'));
1057
                }
1058
            }
1059 4
            $oElementBuChar = $document->getElement('a:buChar', $oSubElement);
1060 4
            if ($oElementBuChar instanceof \DOMElement) {
1061 3
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET);
1062 3
                if ($oElementBuChar->hasAttribute('char')) {
1063 3
                    $oParagraph->getBulletStyle()->setBulletChar($oElementBuChar->getAttribute('char'));
1064
                }
1065
            }
1066 4
            $oElementBuAutoNum = $document->getElement('a:buAutoNum', $oSubElement);
1067 4
            if ($oElementBuAutoNum instanceof \DOMElement) {
1068
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NUMERIC);
1069
                if ($oElementBuAutoNum->hasAttribute('type')) {
1070
                    $oParagraph->getBulletStyle()->setBulletNumericStyle($oElementBuAutoNum->getAttribute('type'));
1071
                }
1072
                if ($oElementBuAutoNum->hasAttribute('startAt') && $oElementBuAutoNum->getAttribute('startAt') != 1) {
1073
                    $oParagraph->getBulletStyle()->setBulletNumericStartAt($oElementBuAutoNum->getAttribute('startAt'));
1074
                }
1075
            }
1076 4
            $oElementBuClr = $document->getElement('a:buClr', $oSubElement);
1077 4
            if ($oElementBuClr instanceof \DOMElement) {
1078
                $oColor = new Color();
1079
                /**
1080
                 * @todo Create protected for reading Color
1081
                 */
1082
                $oElementColor = $document->getElement('a:srgbClr', $oElementBuClr);
1083
                if ($oElementColor instanceof \DOMElement) {
1084
                    $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
1085
                }
1086
                $oParagraph->getBulletStyle()->setBulletColor($oColor);
1087
            }
1088
        }
1089 4
        $arraySubElements = $document->getElements('(a:r|a:br)', $oElement);
1090 4
        foreach ($arraySubElements as $oSubElement) {
1091 4
            if ($oSubElement->tagName == 'a:br') {
1092 3
                $oParagraph->createBreak();
1093
            }
1094 4
            if ($oSubElement->tagName == 'a:r') {
1095 4
                $oElementrPr = $document->getElement('a:rPr', $oSubElement);
1096 4
                if (is_object($oElementrPr)) {
1097 4
                    $oText = $oParagraph->createTextRun();
1098
1099 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...
1100 3
                        $att = $oElementrPr->getAttribute('b');
1101 3
                        $oText->getFont()->setBold($att == 'true' || $att == '1' ? true : false);
1102
                    }
1103 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...
1104 3
                        $att = $oElementrPr->getAttribute('i');
1105 3
                        $oText->getFont()->setItalic($att == 'true' || $att == '1' ? true : false);
1106
                    }
1107 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...
1108 3
                        $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true);
1109
                    }
1110 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...
1111 3
                        $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100));
1112
                    }
1113 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...
1114 3
                        $oText->getFont()->setUnderline($oElementrPr->getAttribute('u'));
1115
                    }
1116
                    // Color
1117 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...
1118 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...
1119 3
                        $oColor = new Color();
1120 3
                        $oColor->setRGB($oElementSrgbClr->getAttribute('val'));
1121 3
                        $oText->getFont()->setColor($oColor);
1122
                    }
1123
                    // Hyperlink
1124 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...
1125 4
                    if (is_object($oElementHlinkClick)) {
1126 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...
1127 3
                            $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip'));
1128
                        }
1129 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...
1130 3
                            $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']);
1131
                        }
1132
                    }
1133
                    //} else {
1134
                    // $oText = $oParagraph->createText();
1135
1136 4
                    $oSubSubElement = $document->getElement('a:t', $oSubElement);
1137 4
                    $oText->setText($oSubSubElement->nodeValue);
1138
                }
1139
            }
1140
        }
1141 4
    }
1142
1143
    /**
1144
     * @param XMLReader $xmlReader
1145
     * @param \DOMElement $oElement
1146
     * @param Border $oBorder
1147
     */
1148
    protected function loadStyleBorder(XMLReader $xmlReader, \DOMElement $oElement, Border $oBorder)
1149
    {
1150
        if ($oElement->hasAttribute('w')) {
1151
            $oBorder->setLineWidth($oElement->getAttribute('w') / 12700);
1152
        }
1153
        if ($oElement->hasAttribute('cmpd')) {
1154
            $oBorder->setLineStyle($oElement->getAttribute('cmpd'));
1155
        }
1156
1157
        $oElementNoFill = $xmlReader->getElement('a:noFill', $oElement);
1158
        if ($oElementNoFill instanceof \DOMElement && $oBorder->getLineStyle() == Border::LINE_SINGLE) {
1159
            $oBorder->setLineStyle(Border::LINE_NONE);
1160
        }
1161
1162
        $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
1163
        if ($oElementColor instanceof \DOMElement) {
1164
            $oBorder->setColor($this->loadStyleColor($xmlReader, $oElementColor));
1165
        }
1166
1167
        $oElementDashStyle = $xmlReader->getElement('a:prstDash', $oElement);
1168
        if ($oElementDashStyle instanceof \DOMElement && $oElementDashStyle->hasAttribute('val')) {
1169
            $oBorder->setDashStyle($oElementDashStyle->getAttribute('val'));
1170
        }
1171
    }
1172
1173
    /**
1174
     * @param XMLReader $xmlReader
1175
     * @param \DOMElement $oElement
1176
     * @return Color
1177
     */
1178
    protected function loadStyleColor(XMLReader $xmlReader, \DOMElement $oElement)
1179
    {
1180
        $oColor = new Color();
1181
        $oColor->setRGB($oElement->getAttribute('val'));
1182
        $oElementAlpha = $xmlReader->getElement('a:alpha', $oElement);
1183
        if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1184
            $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1185
            $oColor->setRGB($oElement->getAttribute('val'), $alpha);
1186
        }
1187
        return $oColor;
1188
    }
1189
1190
    /**
1191
     * @param XMLReader $xmlReader
1192
     * @param \DOMElement $oElement
1193
     * @return null|Fill
1194
     */
1195
    protected function loadStyleFill(XMLReader $xmlReader, \DOMElement $oElement)
1196
    {
1197
        // Gradient fill
1198
        $oElementFill = $xmlReader->getElement('a:gradFill', $oElement);
1199
        if ($oElementFill instanceof \DOMElement) {
1200
            $oFill = new Fill();
1201
            $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR);
1202
1203
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill);
1204
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1205
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1206
            }
1207
1208
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill);
1209
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1210
                $oFill->setEndColor($this->loadStyleColor($xmlReader, $oElementColor));
1211
            }
1212
1213
            $oRotation = $xmlReader->getElement('a:lin', $oElementFill);
1214
            if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) {
1215
                $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang')));
1216
            }
1217
            return $oFill;
1218
        }
1219
1220
        // Solid fill
1221
        $oElementFill = $xmlReader->getElement('a:solidFill', $oElement);
1222
        if ($oElementFill instanceof \DOMElement) {
1223
            $oFill = new Fill();
1224
            $oFill->setFillType(Fill::FILL_SOLID);
1225
1226
            $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill);
1227
            if ($oElementColor instanceof \DOMElement) {
1228
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1229
            }
1230
            return $oFill;
1231
        }
1232
        return null;
1233
    }
1234
1235
    /**
1236
     * @param string $fileRels
1237
     * @return string
1238
     */
1239 4
    protected function loadRels($fileRels)
1240
    {
1241 4
        $sPart = $this->oZip->getFromName($fileRels);
1242 4
        if ($sPart !== false) {
1243 4
            $xmlReader = new XMLReader();
1244 4
            if ($xmlReader->getDomFromString($sPart)) {
1245 4
                foreach ($xmlReader->getElements('*') as $oNode) {
1246 4
                    if (!($oNode instanceof \DOMElement)) {
1247
                        continue;
1248
                    }
1249 4
                    $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array(
1250 4
                        'Target' => $oNode->getAttribute('Target'),
1251 4
                        'Type' => $oNode->getAttribute('Type'),
1252
                    );
1253
                }
1254
            }
1255
        }
1256 4
    }
1257
1258
    /**
1259
     * @param $oSlide
1260
     * @param \DOMNodeList $oElements
1261
     * @param XMLReader $xmlReader
1262
     * @internal param $baseFile
1263
     */
1264 4
    protected function loadSlideShapes($oSlide, $oElements, $xmlReader)
1265
    {
1266 4
        foreach ($oElements as $oNode) {
1267 4
            switch ($oNode->tagName) {
1268 4
                case 'p:graphicFrame':
1269
                    $this->loadShapeTable($xmlReader, $oNode, $oSlide);
1270
                    break;
1271 4
                case 'p:pic':
1272 3
                    $this->loadShapeDrawing($xmlReader, $oNode, $oSlide);
1273 3
                    break;
1274 4
                case 'p:sp':
1275 4
                    $this->loadShapeRichText($xmlReader, $oNode, $oSlide);
1276 4
                    break;
1277 4
                default:
1278
                    //var_export($oNode->tagName);
1279
            }
1280
        }
1281 4
    }
1282
}
1283