Completed
Pull Request — develop (#565)
by
unknown
06:32
created

PowerPoint2007::loadViewProperties()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

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

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

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

Loading history...
1134 3
                        $att = $oElementrPr->getAttribute('b');
1135 3
                        $oText->getFont()->setBold($att == 'true' || $att == '1' ? true : false);
1136
                    }
1137 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...
1138 3
                        $att = $oElementrPr->getAttribute('i');
1139 3
                        $oText->getFont()->setItalic($att == 'true' || $att == '1' ? true : false);
1140
                    }
1141 4
                    if ($oElementrPr->hasAttribute('strike')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

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

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

Loading history...
1142 3
                        $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true);
1143
                    }
1144 4
                    if ($oElementrPr->hasAttribute('sz')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

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

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

Loading history...
1145 3
                        $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100));
1146
                    }
1147 4
                    if ($oElementrPr->hasAttribute('u')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

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

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

Loading history...
1148 3
                        $oText->getFont()->setUnderline($oElementrPr->getAttribute('u'));
1149
                    }
1150
                    // Color
1151 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...
1152 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...
1153 3
                        $oColor = new Color();
1154 3
                        $oColor->setRGB($oElementSrgbClr->getAttribute('val'));
1155 3
                        $oText->getFont()->setColor($oColor);
1156
                    }
1157
                    // Hyperlink
1158 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...
1159 4
                    if (is_object($oElementHlinkClick)) {
1160 3
                        if ($oElementHlinkClick->hasAttribute('tooltip')) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

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

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

Loading history...
1161 3
                            $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip'));
1162
                        }
1163 3
                        if ($oElementHlinkClick->hasAttribute('r:id') && isset($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target'])) {
0 ignored issues
show
Bug introduced by
The method hasAttribute() does not exist on DOMNode. Did you maybe mean hasAttributes()?

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

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

Loading history...
1164 3
                            $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']);
1165
                        }
1166
                    }
1167
                    //} else {
1168
                    // $oText = $oParagraph->createText();
1169
1170 4
                    $oSubSubElement = $document->getElement('a:t', $oSubElement);
1171 4
                    $oText->setText($oSubSubElement->nodeValue);
1172
                }
1173
            }
1174
        }
1175 4
    }
1176
1177
    /**
1178
     * @param XMLReader $xmlReader
1179
     * @param \DOMElement $oElement
1180
     * @param Border $oBorder
1181
     * @throws \Exception
1182
     */
1183
    protected function loadStyleBorder(XMLReader $xmlReader, \DOMElement $oElement, Border $oBorder)
1184
    {
1185
        if ($oElement->hasAttribute('w')) {
1186
            $oBorder->setLineWidth($oElement->getAttribute('w') / 12700);
1187
        }
1188
        if ($oElement->hasAttribute('cmpd')) {
1189
            $oBorder->setLineStyle($oElement->getAttribute('cmpd'));
1190
        }
1191
1192
        $oElementNoFill = $xmlReader->getElement('a:noFill', $oElement);
1193
        if ($oElementNoFill instanceof \DOMElement && $oBorder->getLineStyle() == Border::LINE_SINGLE) {
1194
            $oBorder->setLineStyle(Border::LINE_NONE);
1195
        }
1196
1197
        $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement);
1198
        if ($oElementColor instanceof \DOMElement) {
1199
            $oBorder->setColor($this->loadStyleColor($xmlReader, $oElementColor));
1200
        }
1201
1202
        $oElementDashStyle = $xmlReader->getElement('a:prstDash', $oElement);
1203
        if ($oElementDashStyle instanceof \DOMElement && $oElementDashStyle->hasAttribute('val')) {
1204
            $oBorder->setDashStyle($oElementDashStyle->getAttribute('val'));
1205
        }
1206
    }
1207
1208
    /**
1209
     * @param XMLReader $xmlReader
1210
     * @param \DOMElement $oElement
1211
     * @return Color
1212
     */
1213
    protected function loadStyleColor(XMLReader $xmlReader, \DOMElement $oElement)
1214
    {
1215
        $oColor = new Color();
1216
        $oColor->setRGB($oElement->getAttribute('val'));
1217
        $oElementAlpha = $xmlReader->getElement('a:alpha', $oElement);
1218
        if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) {
1219
            $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255));
1220
            $oColor->setRGB($oElement->getAttribute('val'), $alpha);
1221
        }
1222
        return $oColor;
1223
    }
1224
1225
    /**
1226
     * @param XMLReader $xmlReader
1227
     * @param \DOMElement $oElement
1228
     * @return null|Fill
1229
     * @throws \Exception
1230
     */
1231 3
    protected function loadStyleFill(XMLReader $xmlReader, \DOMElement $oElement)
1232
    {
1233
        // Gradient fill
1234 3
        $oElementFill = $xmlReader->getElement('a:gradFill', $oElement);
1235 3
        if ($oElementFill instanceof \DOMElement) {
1236
            $oFill = new Fill();
1237
            $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR);
1238
1239
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill);
1240
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1241
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1242
            }
1243
1244
            $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill);
1245
            if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) {
1246
                $oFill->setEndColor($this->loadStyleColor($xmlReader, $oElementColor));
1247
            }
1248
1249
            $oRotation = $xmlReader->getElement('a:lin', $oElementFill);
1250
            if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) {
1251
                $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang')));
1252
            }
1253
            return $oFill;
1254
        }
1255
1256
        // Solid fill
1257 3
        $oElementFill = $xmlReader->getElement('a:solidFill', $oElement);
1258 3
        if ($oElementFill instanceof \DOMElement) {
1259
            $oFill = new Fill();
1260
            $oFill->setFillType(Fill::FILL_SOLID);
1261
1262
            $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill);
1263
            if ($oElementColor instanceof \DOMElement) {
1264
                $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor));
1265
            }
1266
            return $oFill;
1267
        }
1268 3
        return null;
1269
    }
1270
1271
    /**
1272
     * @param string $fileRels
1273
     */
1274 4
    protected function loadRels($fileRels)
1275
    {
1276 4
        $sPart = $this->oZip->getFromName($fileRels);
1277 4
        if ($sPart !== false) {
1278 4
            $xmlReader = new XMLReader();
1279 4
            if ($xmlReader->getDomFromString($sPart)) {
1280 4
                foreach ($xmlReader->getElements('*') as $oNode) {
1281 4
                    if (!($oNode instanceof \DOMElement)) {
1282
                        continue;
1283
                    }
1284 4
                    $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array(
1285 4
                        'Target' => $oNode->getAttribute('Target'),
1286 4
                        'Type' => $oNode->getAttribute('Type'),
1287
                    );
1288
                }
1289
            }
1290
        }
1291 4
    }
1292
1293
    /**
1294
     * @param $oSlide
1295
     * @param \DOMNodeList $oElements
1296
     * @param XMLReader $xmlReader
1297
     * @throws \Exception
1298
     * @internal param $baseFile
1299
     */
1300 4
    protected function loadSlideShapes($oSlide, $oElements, XMLReader $xmlReader)
1301
    {
1302 4
        foreach ($oElements as $oNode) {
1303 4
            switch ($oNode->tagName) {
1304 4
                case 'p:graphicFrame':
1305
                    $this->loadShapeTable($xmlReader, $oNode, $oSlide);
1306
                    break;
1307 4
                case 'p:pic':
1308 3
                    $this->loadShapeDrawing($xmlReader, $oNode, $oSlide);
1309 3
                    break;
1310 4
                case 'p:sp':
1311 4
                    $this->loadShapeRichText($xmlReader, $oNode, $oSlide);
1312 4
                    break;
1313 4
                default:
1314
                    //var_export($oNode->tagName);
1315
            }
1316
        }
1317 4
    }
1318
}
1319