Completed
Pull Request — develop (#335)
by Franck
18:00 queued 45s
created

PowerPoint2007::loadCustomProperties()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

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

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

Loading history...
1093
    {
1094
        // Gradient fill
1095
        $oElementFill = $xmlReader->getElement('a:gradFill', $oElement);
1096
        if ($oElementFill instanceof \DOMElement) {
1097
            $oFill = new Fill();
1098
            $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR);
1099
1100
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill);
1101
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1102
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1103
            }
1104
1105
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill);
1106
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1107
                $oFill->setEndColor($this->loadStyleColor($xmlReader, $oElementColor));
1108
            }
1109
1110
            $oRotation = $xmlReader->getElement('a:lin', $oElementFill);
1111
            if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) {
1112
                $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang')));
1113
            }
1114
            return $oFill;
1115
        }
1116
1117
        // Solid fill
1118
        $oElementFill = $xmlReader->getElement('a:solidFill', $oElement);
1119
        if ($oElementFill instanceof \DOMElement) {
1120
            $oFill = new Fill();
1121
            $oFill->setFillType(Fill::FILL_SOLID);
1122
1123
            $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill);
1124
            if ($oElementColor instanceof \DOMElement) {
1125
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1126
            }
1127
            return $oFill;
1128
        }
1129
        return null;
1130
    }
1131
1132
    /**
1133
     * @param XMLReader $xmlReader
1134
     * @param \DOMElement $oElement
1135
     * @return Color
1136
     */
1137
    protected function loadStyleColor(XMLReader $xmlReader, \DOMElement $oElement)
1138
    {
1139
        $oColor = new Color();
1140
        $oColor->setRGB($oElement->getAttribute('val'));
1141
        $oElementAlpha = $xmlReader->getElement('a:alpha', $oElement);
1142
        if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1143
            $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1144
            $oColor->setRGB($oElement->getAttribute('val'), $alpha);
1145
        }
1146
        return $oColor;
1147
    }
1148
1149
    /**
1150
     * @param XMLReader $xmlReader
1151
     * @param \DOMElement $oElement
1152
     * @param Border $oBorder
1153
     */
1154
    protected function loadBorder(XMLReader $xmlReader, \DOMElement $oElement, Border $oBorder)
1155
    {
1156
        if ($oElement->hasAttribute('w')) {
1157
            $oBorder->setLineWidth($oElement->getAttribute('w') / 12700);
1158
        }
1159
        if ($oElement->hasAttribute('cmpd')) {
1160
            $oBorder->setLineStyle($oElement->getAttribute('cmpd'));
1161
        }
1162
1163
        $oElementNoFill = $xmlReader->getElement('a:noFill', $oElement);
1164
        if ($oElementNoFill instanceof \DOMElement && $oBorder->getLineStyle() == Border::LINE_SINGLE) {
1165
            $oBorder->setLineStyle(Border::LINE_NONE);
1166
        }
1167
1168
        $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
1169
        if ($oElementColor instanceof \DOMElement) {
1170
            $oBorder->setColor($this->loadStyleColor($xmlReader, $oElementColor));
1171
        }
1172
1173
        $oElementDashStyle = $xmlReader->getElement('a:prstDash', $oElement);
1174
        if ($oElementDashStyle instanceof \DOMElement && $oElementDashStyle->hasAttribute('val')) {
1175
            $oBorder->setDashStyle($oElementDashStyle->getAttribute('val'));
1176
        }
1177
    }
1178
    /**
1179
     *
1180
     * @param string $fileRels
1181
     * @return string
1182
     */
1183
    protected function loadRels($fileRels)
1184
    {
1185
        $sPart = $this->oZip->getFromName($fileRels);
1186
        if ($sPart !== false) {
1187
            $xmlReader = new XMLReader();
1188
            if ($xmlReader->getDomFromString($sPart)) {
1189
                foreach ($xmlReader->getElements('*') as $oNode) {
1190
                    $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array(
1191
                        'Target' => $oNode->getAttribute('Target'),
1192
                        'Type' => $oNode->getAttribute('Type'),
1193
                    );
1194
                }
1195
            }
1196
        }
1197
    }
1198
1199
    /**
1200
     * @param $oSlide
1201
     * @param \DOMNodeList $oElements
1202
     * @param XMLReader $xmlReader
1203
     * @internal param $baseFile
1204
     */
1205
    private function loadSlideShapes($oSlide, $oElements, $xmlReader)
1206
    {
1207
        foreach ($oElements as $oNode) {
1208
            switch ($oNode->tagName) {
1209
                case 'p:graphicFrame':
1210
                    $this->loadShapeTable($xmlReader, $oNode, $oSlide);
1211
                    break;
1212
                case 'p:pic':
1213
                    $this->loadShapeDrawing($xmlReader, $oNode, $oSlide);
1214
                    break;
1215
                case 'p:sp':
1216
                    $this->loadShapeRichText($xmlReader, $oNode, $oSlide);
1217
                    break;
1218
                default:
1219
                    //var_export($oNode->tagName);
1220
            }
1221
        }
1222
    }
1223
}
1224