Completed
Push — develop ( 7bd91a...e67d8e )
by Franck
14s
created

src/PhpPresentation/Reader/PowerPoint2007.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
                $oElementImage = $xmlReader->getElement('a:blipFill/a:blip', $oElement);
357
                if ($oElementImage instanceof \DOMElement) {
358
                    $relImg = $this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'][$oElementImage->getAttribute('r:embed')];
359
                    if (is_array($relImg)) {
360
                        // File
361
                        $pathImage = 'ppt/slides/' . $relImg['Target'];
362
                        $pathImage = explode('/', $pathImage);
363
                        foreach ($pathImage as $key => $partPath) {
364
                            if ($partPath == '..') {
365
                                unset($pathImage[$key - 1]);
366
                                unset($pathImage[$key]);
367
                            }
368
                        }
369
                        $pathImage = implode('/', $pathImage);
370
                        $contentImg = $this->oZip->getFromName($pathImage);
371
372
                        $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
373
                        file_put_contents($tmpBkgImg, $contentImg);
374
                        // Background
375
                        $oBackground = new Slide\Background\Image();
376
                        $oBackground->setPath($tmpBkgImg);
377
                        // Slide Background
378
                        $oSlide = $this->oPhpPresentation->getActiveSlide();
379
                        $oSlide->setBackground($oBackground);
380
                    }
381
                }
382
            }
383
384
            // Shapes
385 4
            $arrayElements = $xmlReader->getElements('/p:sld/p:cSld/p:spTree/*');
386 4
            if ($arrayElements) {
387 4
                $this->loadSlideShapes($oSlide, $arrayElements, $xmlReader);
388
            }
389
390
            // Layout
391 4
            $oSlide = $this->oPhpPresentation->getActiveSlide();
392 4
            foreach ($this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'] as $valueRel) {
393 4
                if ($valueRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout') {
394 4
                    $layoutBasename = basename($valueRel['Target']);
395 4
                    if (array_key_exists($layoutBasename, $this->arraySlideLayouts)) {
396 4
                        $oSlide->setSlideLayout($this->arraySlideLayouts[$layoutBasename]);
397
                    }
398 4
                    break;
399
                }
400
            }
401
        }
402 4
    }
403
404
    /**
405
     * @param string $sPart
406
     * @param string $baseFile
407
     */
408 4
    protected function loadMasterSlide($sPart, $baseFile)
409
    {
410 4
        $xmlReader = new XMLReader();
411 4
        if ($xmlReader->getDomFromString($sPart)) {
412
            // Core
413 4
            $oSlideMaster = $this->oPhpPresentation->createMasterSlide();
414 4
            $oSlideMaster->setTextStyles(new TextStyle(false));
415 4
            $oSlideMaster->setRelsIndex('ppt/slideMasters/_rels/' . $baseFile . '.rels');
416
417
            // Background
418 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:cSld/p:bg');
419 4
            if ($oElement instanceof \DOMElement) {
420 4
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideMaster);
421
            }
422
423
            // Shapes
424 4
            $arrayElements = $xmlReader->getElements('/p:sldMaster/p:cSld/p:spTree/*');
425 4
            if ($arrayElements) {
426 4
                $this->loadSlideShapes($oSlideMaster, $arrayElements, $xmlReader);
427
            }
428
            // Header & Footer
429
430
            // ColorMapping
431 4
            $colorMap = array();
432 4
            $oElement = $xmlReader->getElement('/p:sldMaster/p:clrMap');
433 4
            if ($oElement->hasAttributes()) {
434 4
                foreach ($oElement->attributes as $attr) {
435 4
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
436
                }
437 4
                $oSlideMaster->colorMap->setMapping($colorMap);
438
            }
439
440
            // TextStyles
441 4
            $arrayElementTxStyles = $xmlReader->getElements('/p:sldMaster/p:txStyles/*');
442 4
            if ($arrayElementTxStyles) {
443 4
                foreach ($arrayElementTxStyles as $oElementTxStyle) {
444 4
                    $arrayElementsLvl = $xmlReader->getElements('/p:sldMaster/p:txStyles/' . $oElementTxStyle->nodeName . '/*');
445 4
                    foreach ($arrayElementsLvl as $oElementLvl) {
446 4
                        if (!($oElementLvl instanceof \DOMElement) || $oElementLvl->nodeName == 'a:extLst') {
447 1
                            continue;
448
                        }
449 4
                        $oRTParagraph = new Paragraph();
450
451 4
                        if ($oElementLvl->nodeName == 'a:defPPr') {
452 3
                            $level = 0;
453
                        } else {
454 4
                            $level = str_replace('a:lvl', '', $oElementLvl->nodeName);
455 4
                            $level = str_replace('pPr', '', $level);
456
                        }
457
458 4
                        if ($oElementLvl->hasAttribute('algn')) {
459 4
                            $oRTParagraph->getAlignment()->setHorizontal($oElementLvl->getAttribute('algn'));
460
                        }
461 4
                        if ($oElementLvl->hasAttribute('marL')) {
462 4
                            $val = $oElementLvl->getAttribute('marL');
463 4
                            $val = CommonDrawing::emuToPixels($val);
464 4
                            $oRTParagraph->getAlignment()->setMarginLeft($val);
465
                        }
466 4
                        if ($oElementLvl->hasAttribute('marR')) {
467
                            $val = $oElementLvl->getAttribute('marR');
468
                            $val = CommonDrawing::emuToPixels($val);
469
                            $oRTParagraph->getAlignment()->setMarginRight($val);
470
                        }
471 4
                        if ($oElementLvl->hasAttribute('indent')) {
472 4
                            $val = $oElementLvl->getAttribute('indent');
473 4
                            $val = CommonDrawing::emuToPixels($val);
474 4
                            $oRTParagraph->getAlignment()->setIndent($val);
475
                        }
476 4
                        $oElementLvlDefRPR = $xmlReader->getElement('a:defRPr', $oElementLvl);
477 4
                        if ($oElementLvlDefRPR instanceof \DOMElement) {
478 4
                            if ($oElementLvlDefRPR->hasAttribute('sz')) {
479 4
                                $oRTParagraph->getFont()->setSize($oElementLvlDefRPR->getAttribute('sz') / 100);
480
                            }
481 4
                            if ($oElementLvlDefRPR->hasAttribute('b') && $oElementLvlDefRPR->getAttribute('b') == 1) {
482 1
                                $oRTParagraph->getFont()->setBold(true);
483
                            }
484 4
                            if ($oElementLvlDefRPR->hasAttribute('i') && $oElementLvlDefRPR->getAttribute('i') == 1) {
485
                                $oRTParagraph->getFont()->setItalic(true);
486
                            }
487
                        }
488 4
                        $oElementSchemeColor = $xmlReader->getElement('a:defRPr/a:solidFill/a:schemeClr', $oElementLvl);
489 4
                        if ($oElementSchemeColor instanceof \DOMElement) {
490 4
                            if ($oElementSchemeColor->hasAttribute('val')) {
491 4
                                $oSchemeColor = new SchemeColor();
492 4
                                $oSchemeColor->setValue($oElementSchemeColor->getAttribute('val'));
493 4
                                $oRTParagraph->getFont()->setColor($oSchemeColor);
494
                            }
495
                        }
496
497 4
                        switch ($oElementTxStyle->nodeName) {
498 4
                            case 'p:bodyStyle':
499 4
                                $oSlideMaster->getTextStyles()->setBodyStyleAtLvl($oRTParagraph, $level);
500 4
                                break;
501 4
                            case 'p:otherStyle':
502 4
                                $oSlideMaster->getTextStyles()->setOtherStyleAtLvl($oRTParagraph, $level);
503 4
                                break;
504 4
                            case 'p:titleStyle':
505 4
                                $oSlideMaster->getTextStyles()->setTitleStyleAtLvl($oRTParagraph, $level);
506 4
                                break;
507
                        }
508
                    }
509
                }
510
            }
511
512
            // Load the theme
513 4
            foreach ($this->arrayRels[$oSlideMaster->getRelsIndex()] as $arrayRel) {
514 4
                if ($arrayRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') {
515 4
                    $pptTheme = $this->oZip->getFromName('ppt/' . substr($arrayRel['Target'], strrpos($arrayRel['Target'], '../') + 3));
516 4
                    if ($pptTheme !== false) {
517 4
                        $this->loadTheme($pptTheme, $oSlideMaster);
518
                    }
519 4
                    break;
520
                }
521
            }
522
523
            // Load the Layoutslide
524 4
            foreach ($xmlReader->getElements('/p:sldMaster/p:sldLayoutIdLst/p:sldLayoutId') as $oElement) {
525 4
                if (!($oElement instanceof \DOMElement)) {
526
                    continue;
527
                }
528 4
                $rId = $oElement->getAttribute('r:id');
529
                // Get the path to the masterslide from the array with _rels files
530 4
                $pathLayoutSlide = isset($this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]) ?
531 4
                    $this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]['Target'] : '';
532 4
                if (!empty($pathLayoutSlide)) {
533 4
                    $pptLayoutSlide = $this->oZip->getFromName('ppt/' . substr($pathLayoutSlide, strrpos($pathLayoutSlide, '../') + 3));
534 4
                    if ($pptLayoutSlide !== false) {
535 4
                        $this->loadRels('ppt/slideLayouts/_rels/' . basename($pathLayoutSlide) . '.rels');
536 4
                        $oSlideMaster->addSlideLayout(
537 4
                            $this->loadLayoutSlide($pptLayoutSlide, basename($pathLayoutSlide), $oSlideMaster)
538
                        );
539
                    }
540
                }
541
            }
542
        }
543 4
    }
544
545
    /**
546
     * @param string $sPart
547
     * @param string $baseFile
548
     * @param SlideMaster $oSlideMaster
549
     * @return SlideLayout|null
550
     */
551 4
    protected function loadLayoutSlide($sPart, $baseFile, SlideMaster $oSlideMaster)
552
    {
553 4
        $xmlReader = new XMLReader();
554 4
        if ($xmlReader->getDomFromString($sPart)) {
555
            // Core
556 4
            $oSlideLayout = new SlideLayout($oSlideMaster);
557 4
            $oSlideLayout->setRelsIndex('ppt/slideLayouts/_rels/' . $baseFile . '.rels');
558
559
            // Name
560 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld');
561 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttribute('name')) {
562 4
                $oSlideLayout->setLayoutName($oElement->getAttribute('name'));
563
            }
564
565
            // Background
566 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld/p:bg');
567 4
            if ($oElement instanceof \DOMElement) {
568 1
                $this->loadSlideBackground($xmlReader, $oElement, $oSlideLayout);
569
            }
570
571
            // ColorMapping
572 4
            $oElement = $xmlReader->getElement('/p:sldLayout/p:clrMapOvr/a:overrideClrMapping');
573 4
            if ($oElement instanceof \DOMElement && $oElement->hasAttributes()) {
574 1
                $colorMap = array();
575 1
                foreach ($oElement->attributes as $attr) {
576 1
                    $colorMap[$attr->nodeName] = $attr->nodeValue;
577
                }
578 1
                $oSlideLayout->colorMap->setMapping($colorMap);
579
            }
580
581
            // Shapes
582 4
            $oElements = $xmlReader->getElements('/p:sldLayout/p:cSld/p:spTree/*');
583 4
            if ($oElements) {
584 4
                $this->loadSlideShapes($oSlideLayout, $oElements, $xmlReader);
585
            }
586 4
            $this->arraySlideLayouts[$baseFile] = &$oSlideLayout;
587 4
            return $oSlideLayout;
588
        }
589
        return null;
590
    }
591
592
    /**
593
     * @param string $sPart
594
     * @param SlideMaster $oSlideMaster
595
     */
596 4
    protected function loadTheme($sPart, SlideMaster $oSlideMaster)
597
    {
598 4
        $xmlReader = new XMLReader();
599 4
        if ($xmlReader->getDomFromString($sPart)) {
600 4
            $oElements = $xmlReader->getElements('/a:theme/a:themeElements/a:clrScheme/*');
601 4
            if ($oElements) {
602 4
                foreach ($oElements as $oElement) {
603 4
                    $oSchemeColor = new SchemeColor();
604 4
                    $oSchemeColor->setValue(str_replace('a:', '', $oElement->tagName));
605 4
                    $colorElement = $xmlReader->getElement('*', $oElement);
606 4
                    if ($colorElement instanceof \DOMElement) {
607 4
                        if ($colorElement->hasAttribute('lastClr')) {
608 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('lastClr'));
609 4
                        } elseif ($colorElement->hasAttribute('val')) {
610 4
                            $oSchemeColor->setRGB($colorElement->getAttribute('val'));
611
                        }
612
                    }
613 4
                    $oSlideMaster->addSchemeColor($oSchemeColor);
614
                }
615
            }
616
        }
617 4
    }
618
619
    /**
620
     * @param XMLReader $xmlReader
621
     * @param \DOMElement $oElement
622
     * @param AbstractSlide $oSlide
623
     */
624 4
    protected function loadSlideBackground(XMLReader $xmlReader, \DOMElement $oElement, AbstractSlide $oSlide)
625
    {
626
        // Background color
627 4
        $oElementColor = $xmlReader->getElement('p:bgPr/a:solidFill/a:srgbClr', $oElement);
628 4
        if ($oElementColor instanceof \DOMElement) {
629
            // Color
630
            $oColor = new Color();
631
            $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
632
            // Background
633
            $oBackground = new Slide\Background\Color();
634
            $oBackground->setColor($oColor);
635
            // Slide Background
636
            $oSlide->setBackground($oBackground);
637
        }
638
639
        // Background scheme color
640 4
        $oElementSchemeColor = $xmlReader->getElement('p:bgRef/a:schemeClr', $oElement);
641 4
        if ($oElementSchemeColor instanceof \DOMElement) {
642
            // Color
643 4
            $oColor = new SchemeColor();
644 4
            $oColor->setValue($oElementSchemeColor->hasAttribute('val') ? $oElementSchemeColor->getAttribute('val') : null);
645
            // Background
646 4
            $oBackground = new Slide\Background\SchemeColor();
647 4
            $oBackground->setSchemeColor($oColor);
648
            // Slide Background
649 4
            $oSlide->setBackground($oBackground);
650
        }
651
652
        // Background image
653 4
        $oElementImage = $xmlReader->getElement('p:bgPr/a:blipFill/a:blip', $oElement);
654 4
        if ($oElementImage instanceof \DOMElement) {
655
            $relImg = $this->arrayRels[$oSlide->getRelsIndex()][$oElementImage->getAttribute('r:embed')];
656
            if (is_array($relImg)) {
657
                // File
658
                $pathImage = 'ppt/slides/' . $relImg['Target'];
659
                $pathImage = explode('/', $pathImage);
660
                foreach ($pathImage as $key => $partPath) {
661
                    if ($partPath == '..') {
662
                        unset($pathImage[$key - 1]);
663
                        unset($pathImage[$key]);
664
                    }
665
                }
666
                $pathImage = implode('/', $pathImage);
667
                $contentImg = $this->oZip->getFromName($pathImage);
668
669
                $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg');
670
                file_put_contents($tmpBkgImg, $contentImg);
671
                // Background
672
                $oBackground = new Slide\Background\Image();
673
                $oBackground->setPath($tmpBkgImg);
674
                // Slide Background
675
                $oSlide->setBackground($oBackground);
676
            }
677
        }
678 4
    }
679
680
    /**
681
     * @param string $baseFile
682
     * @param Slide $oSlide
683
     */
684
    protected function loadSlideNote($baseFile, Slide $oSlide)
685
    {
686
        $sPart = $this->oZip->getFromName('ppt/notesSlides/' . $baseFile);
687
        $xmlReader = new XMLReader();
688
        if ($xmlReader->getDomFromString($sPart)) {
689
            $oNote = $oSlide->getNote();
690
691
            $arrayElements = $xmlReader->getElements('/p:notes/p:cSld/p:spTree/*');
692
            if ($arrayElements) {
693
                $this->loadSlideShapes($oNote, $arrayElements, $xmlReader);
694
            }
695
        }
696
    }
697
698
    /**
699
     * @param XMLReader $document
700
     * @param \DOMElement $node
701
     * @param AbstractSlide $oSlide
702
     */
703 3
    protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
704
    {
705
        // Core
706 3
        $oShape = new Gd();
707 3
        $oShape->getShadow()->setVisible(false);
708
        // Variables
709 3
        $fileRels = $oSlide->getRelsIndex();
710
711 3
        $oElement = $document->getElement('p:nvPicPr/p:cNvPr', $node);
712 3
        if ($oElement instanceof \DOMElement) {
713 3
            $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : '');
714 3
            $oShape->setDescription($oElement->hasAttribute('descr') ? $oElement->getAttribute('descr') : '');
715
        }
716
717 3
        $oElement = $document->getElement('p:blipFill/a:blip', $node);
718 3
        if ($oElement instanceof \DOMElement) {
719 3
            if ($oElement->hasAttribute('r:embed') && isset($this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'])) {
720 3
                $pathImage = 'ppt/slides/' . $this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'];
721 3
                $pathImage = explode('/', $pathImage);
722 3
                foreach ($pathImage as $key => $partPath) {
723 3
                    if ($partPath == '..') {
724 3
                        unset($pathImage[$key - 1]);
725 3
                        unset($pathImage[$key]);
726
                    }
727
                }
728 3
                $pathImage = implode('/', $pathImage);
729 3
                $imageFile = $this->oZip->getFromName($pathImage);
730 3
                if (!empty($imageFile)) {
731 3
                    $oShape->setImageResource(imagecreatefromstring($imageFile));
732
                }
733
            }
734
        }
735
736 3
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
737 3
        if ($oElement instanceof \DOMElement) {
738 3
            if ($oElement->hasAttribute('rot')) {
739 3
                $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
740
            }
741
        }
742
743 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
744 3
        if ($oElement instanceof \DOMElement) {
745 3
            if ($oElement->hasAttribute('x')) {
746 3
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
747
            }
748 3
            if ($oElement->hasAttribute('y')) {
749 3
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
750
            }
751
        }
752
753 3
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
754 3
        if ($oElement instanceof \DOMElement) {
755 3
            if ($oElement->hasAttribute('cx')) {
756 3
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
757
            }
758 3
            if ($oElement->hasAttribute('cy')) {
759 3
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
760
            }
761
        }
762
763 3
        $oElement = $document->getElement('p:spPr/a:effectLst', $node);
764 3
        if ($oElement instanceof \DOMElement) {
765 3
            $oShape->getShadow()->setVisible(true);
766
767 3
            $oSubElement = $document->getElement('a:outerShdw', $oElement);
768 3
            if ($oSubElement instanceof \DOMElement) {
769 3
                if ($oSubElement->hasAttribute('blurRad')) {
770 3
                    $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels($oSubElement->getAttribute('blurRad')));
771
                }
772 3
                if ($oSubElement->hasAttribute('dist')) {
773 3
                    $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels($oSubElement->getAttribute('dist')));
774
                }
775 3
                if ($oSubElement->hasAttribute('dir')) {
776 3
                    $oShape->getShadow()->setDirection(CommonDrawing::angleToDegrees($oSubElement->getAttribute('dir')));
777
                }
778 3
                if ($oSubElement->hasAttribute('algn')) {
779 3
                    $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn'));
780
                }
781
            }
782
783 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement);
784 3
            if ($oSubElement instanceof \DOMElement) {
785 3
                if ($oSubElement->hasAttribute('val')) {
786 3
                    $oColor = new Color();
787 3
                    $oColor->setRGB($oSubElement->getAttribute('val'));
788 3
                    $oShape->getShadow()->setColor($oColor);
789
                }
790
            }
791
792 3
            $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement);
793 3
            if ($oSubElement instanceof \DOMElement) {
794 3
                if ($oSubElement->hasAttribute('val')) {
795 3
                    $oShape->getShadow()->setAlpha((int)$oSubElement->getAttribute('val') / 1000);
796
                }
797
            }
798
        }
799
800 3
        $oSlide->addShape($oShape);
801 3
    }
802
803
    /**
804
     * @param XMLReader $document
805
     * @param \DOMElement $node
806
     * @param AbstractSlide $oSlide
807
     * @throws \Exception
808
     */
809 4
    protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oSlide)
810
    {
811 4
        if (!$document->elementExists('p:txBody/a:p/a:r', $node)) {
812 4
            return;
813
        }
814
        // Core
815 4
        $oShape = $oSlide->createRichTextShape();
816 4
        $oShape->setParagraphs(array());
817
        // Variables
818 4
        if ($oSlide instanceof AbstractSlide) {
819 4
            $this->fileRels = $oSlide->getRelsIndex();
820
        }
821
822 4
        $oElement = $document->getElement('p:spPr/a:xfrm', $node);
823 4
        if ($oElement instanceof \DOMElement && $oElement->hasAttribute('rot')) {
824 4
            $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot')));
825
        }
826
827 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node);
828 4
        if ($oElement instanceof \DOMElement) {
829 4
            if ($oElement->hasAttribute('x')) {
830 4
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
831
            }
832 4
            if ($oElement->hasAttribute('y')) {
833 4
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
834
            }
835
        }
836
837 4
        $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node);
838 4
        if ($oElement instanceof \DOMElement) {
839 4
            if ($oElement->hasAttribute('cx')) {
840 4
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
841
            }
842 4
            if ($oElement->hasAttribute('cy')) {
843 4
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
844
            }
845
        }
846
847 4
        $oElement = $document->getElement('p:nvSpPr/p:nvPr/p:ph', $node);
848 4
        if ($oElement instanceof \DOMElement) {
849 4
            if ($oElement->hasAttribute('type')) {
850 4
                $placeholder = new Placeholder($oElement->getAttribute('type'));
851 4
                $oShape->setPlaceHolder($placeholder);
852
            }
853
        }
854
855 4
        $arrayElements = $document->getElements('p:txBody/a:p', $node);
856 4
        foreach ($arrayElements as $oElement) {
857 4
            $this->loadParagraph($document, $oElement, $oShape);
858
        }
859
860 4
        if (count($oShape->getParagraphs()) > 0) {
861 4
            $oShape->setActiveParagraph(0);
862
        }
863 4
    }
864
865
    /**
866
     * @param XMLReader $document
867
     * @param \DOMElement $node
868
     * @param AbstractSlide $oSlide
869
     * @throws \Exception
870
     */
871
    protected function loadShapeTable(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide)
872
    {
873
        $this->fileRels = $oSlide->getRelsIndex();
874
875
        $oShape = $oSlide->createTableShape();
876
877
        $oElement = $document->getElement('p:cNvPr', $node);
878
        if ($oElement instanceof \DOMElement) {
879
            if ($oElement->hasAttribute('name')) {
880
                $oShape->setName($oElement->getAttribute('name'));
881
            }
882
            if ($oElement->hasAttribute('descr')) {
883
                $oShape->setDescription($oElement->getAttribute('descr'));
884
            }
885
        }
886
887
        $oElement = $document->getElement('p:xfrm/a:off', $node);
888
        if ($oElement instanceof \DOMElement) {
889
            if ($oElement->hasAttribute('x')) {
890
                $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x')));
891
            }
892
            if ($oElement->hasAttribute('y')) {
893
                $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y')));
894
            }
895
        }
896
897
        $oElement = $document->getElement('p:xfrm/a:ext', $node);
898
        if ($oElement instanceof \DOMElement) {
899
            if ($oElement->hasAttribute('cx')) {
900
                $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx')));
901
            }
902
            if ($oElement->hasAttribute('cy')) {
903
                $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy')));
904
            }
905
        }
906
907
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tblGrid/a:gridCol', $node);
908
        $oShape->setNumColumns($arrayElements->length);
909
        $oShape->createRow();
910
        foreach ($arrayElements as $key => $oElement) {
911
            if ($oElement instanceof \DOMElement && $oElement->getAttribute('w')) {
912
                $oShape->getRow(0)->getCell($key)->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('w')));
913
            }
914
        }
915
916
        $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tr', $node);
917
        foreach ($arrayElements as $keyRow => $oElementRow) {
918
            if (!($oElementRow instanceof \DOMElement)) {
919
                continue;
920
            }
921
            $oRow = $oShape->getRow($keyRow, true);
922
            if (is_null($oRow)) {
923
                $oRow = $oShape->createRow();
924
            }
925
            if ($oElementRow->hasAttribute('h')) {
926
                $oRow->setHeight(CommonDrawing::emuToPixels($oElementRow->getAttribute('h')));
927
            }
928
            $arrayElementsCell = $document->getElements('a:tc', $oElementRow);
929
            foreach ($arrayElementsCell as $keyCell => $oElementCell) {
930
                if (!($oElementCell instanceof \DOMElement)) {
931
                    continue;
932
                }
933
                $oCell = $oRow->getCell($keyCell);
934
                $oCell->setParagraphs(array());
935
                if ($oElementCell->hasAttribute('gridSpan')) {
936
                    $oCell->setColSpan($oElementCell->getAttribute('gridSpan'));
937
                }
938
                if ($oElementCell->hasAttribute('rowSpan')) {
939
                    $oCell->setRowSpan($oElementCell->getAttribute('rowSpan'));
940
                }
941
942
                foreach ($document->getElements('a:txBody/a:p', $oElementCell) as $oElementPara) {
943
                    $this->loadParagraph($document, $oElementPara, $oCell);
944
                }
945
946
                $oElementTcPr = $document->getElement('a:tcPr', $oElementCell);
947
                if ($oElementTcPr instanceof \DOMElement) {
948
                    $numParagraphs = count($oCell->getParagraphs());
949
                    if ($numParagraphs > 0) {
950
                        if ($oElementTcPr->hasAttribute('vert')) {
951
                            $oCell->getParagraph(0)->getAlignment()->setTextDirection($oElementTcPr->getAttribute('vert'));
952
                        }
953
                        if ($oElementTcPr->hasAttribute('anchor')) {
954
                            $oCell->getParagraph(0)->getAlignment()->setVertical($oElementTcPr->getAttribute('anchor'));
955
                        }
956
                        if ($oElementTcPr->hasAttribute('marB')) {
957
                            $oCell->getParagraph(0)->getAlignment()->setMarginBottom($oElementTcPr->getAttribute('marB'));
958
                        }
959
                        if ($oElementTcPr->hasAttribute('marL')) {
960
                            $oCell->getParagraph(0)->getAlignment()->setMarginLeft($oElementTcPr->getAttribute('marL'));
961
                        }
962
                        if ($oElementTcPr->hasAttribute('marR')) {
963
                            $oCell->getParagraph(0)->getAlignment()->setMarginRight($oElementTcPr->getAttribute('marR'));
964
                        }
965
                        if ($oElementTcPr->hasAttribute('marT')) {
966
                            $oCell->getParagraph(0)->getAlignment()->setMarginTop($oElementTcPr->getAttribute('marT'));
967
                        }
968
                    }
969
970
                    $oFill = $this->loadStyleFill($document, $oElementTcPr);
971
                    if ($oFill instanceof Fill) {
972
                        $oCell->setFill($oFill);
973
                    }
974
975
                    $oBorders = new Borders();
976
                    $oElementBorderL = $document->getElement('a:lnL', $oElementTcPr);
977
                    if ($oElementBorderL instanceof \DOMElement) {
978
                        $this->loadStyleBorder($document, $oElementBorderL, $oBorders->getLeft());
979
                    }
980
                    $oElementBorderR = $document->getElement('a:lnR', $oElementTcPr);
981
                    if ($oElementBorderR instanceof \DOMElement) {
982
                        $this->loadStyleBorder($document, $oElementBorderR, $oBorders->getRight());
983
                    }
984
                    $oElementBorderT = $document->getElement('a:lnT', $oElementTcPr);
985
                    if ($oElementBorderT instanceof \DOMElement) {
986
                        $this->loadStyleBorder($document, $oElementBorderT, $oBorders->getTop());
987
                    }
988
                    $oElementBorderB = $document->getElement('a:lnB', $oElementTcPr);
989
                    if ($oElementBorderB instanceof \DOMElement) {
990
                        $this->loadStyleBorder($document, $oElementBorderB, $oBorders->getBottom());
991
                    }
992
                    $oElementBorderDiagDown = $document->getElement('a:lnTlToBr', $oElementTcPr);
993
                    if ($oElementBorderDiagDown instanceof \DOMElement) {
994
                        $this->loadStyleBorder($document, $oElementBorderDiagDown, $oBorders->getDiagonalDown());
995
                    }
996
                    $oElementBorderDiagUp = $document->getElement('a:lnBlToTr', $oElementTcPr);
997
                    if ($oElementBorderDiagUp instanceof \DOMElement) {
998
                        $this->loadStyleBorder($document, $oElementBorderDiagUp, $oBorders->getDiagonalUp());
999
                    }
1000
                    $oCell->setBorders($oBorders);
1001
                }
1002
            }
1003
        }
1004
    }
1005
1006
    /**
1007
     * @param XMLReader $document
1008
     * @param \DOMElement $oElement
1009
     * @param Cell|RichText $oShape
1010
     * @throws \Exception
1011
     */
1012 4
    protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oShape)
1013
    {
1014
        // Core
1015 4
        $oParagraph = $oShape->createParagraph();
1016 4
        $oParagraph->setRichTextElements(array());
1017
1018 4
        $oSubElement = $document->getElement('a:pPr', $oElement);
1019 4
        if ($oSubElement instanceof \DOMElement) {
1020 4
            if ($oSubElement->hasAttribute('algn')) {
1021 3
                $oParagraph->getAlignment()->setHorizontal($oSubElement->getAttribute('algn'));
1022
            }
1023 4
            if ($oSubElement->hasAttribute('fontAlgn')) {
1024 3
                $oParagraph->getAlignment()->setVertical($oSubElement->getAttribute('fontAlgn'));
1025
            }
1026 4
            if ($oSubElement->hasAttribute('marL')) {
1027 3
                $oParagraph->getAlignment()->setMarginLeft(CommonDrawing::emuToPixels($oSubElement->getAttribute('marL')));
1028
            }
1029 4
            if ($oSubElement->hasAttribute('marR')) {
1030 3
                $oParagraph->getAlignment()->setMarginRight(CommonDrawing::emuToPixels($oSubElement->getAttribute('marR')));
1031
            }
1032 4
            if ($oSubElement->hasAttribute('indent')) {
1033 3
                $oParagraph->getAlignment()->setIndent(CommonDrawing::emuToPixels($oSubElement->getAttribute('indent')));
1034
            }
1035 4
            if ($oSubElement->hasAttribute('lvl')) {
1036 4
                $oParagraph->getAlignment()->setLevel($oSubElement->getAttribute('lvl'));
1037
            }
1038
1039 4
            $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NONE);
1040
1041 4
            $oElementBuFont = $document->getElement('a:buFont', $oSubElement);
1042 4
            if ($oElementBuFont instanceof \DOMElement) {
1043 3
                if ($oElementBuFont->hasAttribute('typeface')) {
1044 3
                    $oParagraph->getBulletStyle()->setBulletFont($oElementBuFont->getAttribute('typeface'));
1045
                }
1046
            }
1047 4
            $oElementBuChar = $document->getElement('a:buChar', $oSubElement);
1048 4
            if ($oElementBuChar instanceof \DOMElement) {
1049 3
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET);
1050 3
                if ($oElementBuChar->hasAttribute('char')) {
1051 3
                    $oParagraph->getBulletStyle()->setBulletChar($oElementBuChar->getAttribute('char'));
1052
                }
1053
            }
1054 4
            $oElementBuAutoNum = $document->getElement('a:buAutoNum', $oSubElement);
1055 4
            if ($oElementBuAutoNum instanceof \DOMElement) {
1056
                $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NUMERIC);
1057
                if ($oElementBuAutoNum->hasAttribute('type')) {
1058
                    $oParagraph->getBulletStyle()->setBulletNumericStyle($oElementBuAutoNum->getAttribute('type'));
1059
                }
1060
                if ($oElementBuAutoNum->hasAttribute('startAt') && $oElementBuAutoNum->getAttribute('startAt') != 1) {
1061
                    $oParagraph->getBulletStyle()->setBulletNumericStartAt($oElementBuAutoNum->getAttribute('startAt'));
1062
                }
1063
            }
1064 4
            $oElementBuClr = $document->getElement('a:buClr', $oSubElement);
1065 4
            if ($oElementBuClr instanceof \DOMElement) {
1066
                $oColor = new Color();
1067
                /**
1068
                 * @todo Create protected for reading Color
1069
                 */
1070
                $oElementColor = $document->getElement('a:srgbClr', $oElementBuClr);
1071
                if ($oElementColor instanceof \DOMElement) {
1072
                    $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null);
1073
                }
1074
                $oParagraph->getBulletStyle()->setBulletColor($oColor);
1075
            }
1076
        }
1077 4
        $arraySubElements = $document->getElements('(a:r|a:br)', $oElement);
1078 4
        foreach ($arraySubElements as $oSubElement) {
1079 4
            if ($oSubElement->tagName == 'a:br') {
1080 3
                $oParagraph->createBreak();
1081
            }
1082 4
            if ($oSubElement->tagName == 'a:r') {
1083 4
                $oElementrPr = $document->getElement('a:rPr', $oSubElement);
1084 4
                if (is_object($oElementrPr)) {
1085 4
                    $oText = $oParagraph->createTextRun();
1086
1087 4
                    if ($oElementrPr->hasAttribute('b')) {
1088 3
                        $att = $oElementrPr->getAttribute('b');
1089 3
                        $oText->getFont()->setBold($att == 'true' || $att == '1' ? true : false);
1090
                    }
1091 4
                    if ($oElementrPr->hasAttribute('i')) {
1092 3
                        $att = $oElementrPr->getAttribute('i');
1093 3
                        $oText->getFont()->setItalic($att == 'true' || $att == '1' ? true : false);
1094
                    }
1095 4
                    if ($oElementrPr->hasAttribute('strike')) {
0 ignored issues
show
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1096 3
                        $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true);
1097
                    }
1098 4
                    if ($oElementrPr->hasAttribute('sz')) {
1099 3
                        $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100));
1100
                    }
1101 4
                    if ($oElementrPr->hasAttribute('u')) {
1102 3
                        $oText->getFont()->setUnderline($oElementrPr->getAttribute('u'));
1103
                    }
1104
                    // Color
1105 4
                    $oElementSrgbClr = $document->getElement('a:solidFill/a:srgbClr', $oElementrPr);
1106 4
                    if (is_object($oElementSrgbClr) && $oElementSrgbClr->hasAttribute('val')) {
1107 3
                        $oColor = new Color();
1108 3
                        $oColor->setRGB($oElementSrgbClr->getAttribute('val'));
1109 3
                        $oText->getFont()->setColor($oColor);
1110
                    }
1111
                    // Hyperlink
1112 4
                    $oElementHlinkClick = $document->getElement('a:hlinkClick', $oElementrPr);
1113 4
                    if (is_object($oElementHlinkClick)) {
1114 3
                        if ($oElementHlinkClick->hasAttribute('tooltip')) {
1115 3
                            $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip'));
1116
                        }
1117 3
                        if ($oElementHlinkClick->hasAttribute('r:id') && isset($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target'])) {
1118 3
                            $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']);
1119
                        }
1120
                    }
1121
                    //} else {
1122
                    // $oText = $oParagraph->createText();
1123
1124 4
                    $oSubSubElement = $document->getElement('a:t', $oSubElement);
1125 4
                    $oText->setText($oSubSubElement->nodeValue);
1126
                }
1127
            }
1128
        }
1129 4
    }
1130
1131
    /**
1132
     * @param XMLReader $xmlReader
1133
     * @param \DOMElement $oElement
1134
     * @param Border $oBorder
1135
     */
1136
    protected function loadStyleBorder(XMLReader $xmlReader, \DOMElement $oElement, Border $oBorder)
1137
    {
1138
        if ($oElement->hasAttribute('w')) {
1139
            $oBorder->setLineWidth($oElement->getAttribute('w') / 12700);
1140
        }
1141
        if ($oElement->hasAttribute('cmpd')) {
1142
            $oBorder->setLineStyle($oElement->getAttribute('cmpd'));
1143
        }
1144
1145
        $oElementNoFill = $xmlReader->getElement('a:noFill', $oElement);
1146
        if ($oElementNoFill instanceof \DOMElement && $oBorder->getLineStyle() == Border::LINE_SINGLE) {
1147
            $oBorder->setLineStyle(Border::LINE_NONE);
1148
        }
1149
1150
        $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
1151
        if ($oElementColor instanceof \DOMElement) {
1152
            $oBorder->setColor($this->loadStyleColor($xmlReader, $oElementColor));
1153
        }
1154
1155
        $oElementDashStyle = $xmlReader->getElement('a:prstDash', $oElement);
1156
        if ($oElementDashStyle instanceof \DOMElement && $oElementDashStyle->hasAttribute('val')) {
1157
            $oBorder->setDashStyle($oElementDashStyle->getAttribute('val'));
1158
        }
1159
    }
1160
1161
    /**
1162
     * @param XMLReader $xmlReader
1163
     * @param \DOMElement $oElement
1164
     * @return Color
1165
     */
1166
    protected function loadStyleColor(XMLReader $xmlReader, \DOMElement $oElement)
1167
    {
1168
        $oColor = new Color();
1169
        $oColor->setRGB($oElement->getAttribute('val'));
1170
        $oElementAlpha = $xmlReader->getElement('a:alpha', $oElement);
1171
        if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1172
            $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1173
            $oColor->setRGB($oElement->getAttribute('val'), $alpha);
1174
        }
1175
        return $oColor;
1176
    }
1177
1178
    /**
1179
     * @param XMLReader $xmlReader
1180
     * @param \DOMElement $oElement
1181
     * @return null|Fill
1182
     */
1183
    protected function loadStyleFill(XMLReader $xmlReader, \DOMElement $oElement)
1184
    {
1185
        // Gradient fill
1186
        $oElementFill = $xmlReader->getElement('a:gradFill', $oElement);
1187
        if ($oElementFill instanceof \DOMElement) {
1188
            $oFill = new Fill();
1189
            $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR);
1190
1191
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill);
1192
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1193
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1194
            }
1195
1196
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill);
1197
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1198
                $oFill->setEndColor($this->loadStyleColor($xmlReader, $oElementColor));
1199
            }
1200
1201
            $oRotation = $xmlReader->getElement('a:lin', $oElementFill);
1202
            if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) {
1203
                $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang')));
1204
            }
1205
            return $oFill;
1206
        }
1207
1208
        // Solid fill
1209
        $oElementFill = $xmlReader->getElement('a:solidFill', $oElement);
1210
        if ($oElementFill instanceof \DOMElement) {
1211
            $oFill = new Fill();
1212
            $oFill->setFillType(Fill::FILL_SOLID);
1213
1214
            $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill);
1215
            if ($oElementColor instanceof \DOMElement) {
1216
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1217
            }
1218
            return $oFill;
1219
        }
1220
        return null;
1221
    }
1222
1223
    /**
1224
     * @param string $fileRels
1225
     * @return string
1226
     */
1227 4
    protected function loadRels($fileRels)
1228
    {
1229 4
        $sPart = $this->oZip->getFromName($fileRels);
1230 4
        if ($sPart !== false) {
1231 4
            $xmlReader = new XMLReader();
1232 4
            if ($xmlReader->getDomFromString($sPart)) {
1233 4
                foreach ($xmlReader->getElements('*') as $oNode) {
1234 4
                    if (!($oNode instanceof \DOMElement)) {
1235
                        continue;
1236
                    }
1237 4
                    $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array(
1238 4
                        'Target' => $oNode->getAttribute('Target'),
1239 4
                        'Type' => $oNode->getAttribute('Type'),
1240
                    );
1241
                }
1242
            }
1243
        }
1244 4
    }
1245
1246
    /**
1247
     * @param $oSlide
1248
     * @param \DOMNodeList $oElements
1249
     * @param XMLReader $xmlReader
1250
     * @internal param $baseFile
1251
     */
1252 4
    protected function loadSlideShapes($oSlide, $oElements, $xmlReader)
1253
    {
1254 4
        foreach ($oElements as $oNode) {
1255 4
            switch ($oNode->tagName) {
1256 4
                case 'p:graphicFrame':
1257
                    $this->loadShapeTable($xmlReader, $oNode, $oSlide);
1258
                    break;
1259 4
                case 'p:pic':
1260 3
                    $this->loadShapeDrawing($xmlReader, $oNode, $oSlide);
1261 3
                    break;
1262 4
                case 'p:sp':
1263 4
                    $this->loadShapeRichText($xmlReader, $oNode, $oSlide);
1264 4
                    break;
1265 4
                default:
1266
                    //var_export($oNode->tagName);
1267
            }
1268
        }
1269 4
    }
1270
}
1271