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

PptSlides   F

Complexity

Total Complexity 132

Size/Duplication

Total Lines 1695
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 26

Test Coverage

Coverage 81.22%

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 132
c 5
b 0
f 1
lcom 1
cbo 26
dl 0
loc 1695
ccs 787
cts 969
cp 0.8122
rs 0.5217

12 Methods

Rating   Name   Duplication   Size   Complexity  
B writeSlide() 0 146 4
F writeSlideRelationships() 0 290 61
B render() 0 22 5
A writeHyperlink() 0 14 3
D writeSlideAnimations() 0 243 9
A writeShapeGroup() 0 60 1
A writeShapeChart() 0 67 2
B writeShapeDrawing() 0 119 4
F writeShapeText() 0 137 16
D writeParagraphs() 0 120 15
D writeShapeLine() 0 104 9
B writeNote() 0 280 3

How to fix   Complexity   

Complex Class

Complex classes like PptSlides often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PptSlides, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace PhpOffice\PhpPresentation\Writer\PowerPoint2007;
4
5
use PhpOffice\Common\Drawing as CommonDrawing;
6
use PhpOffice\Common\Text;
7
use PhpOffice\Common\XMLWriter;
8
use PhpOffice\PhpPresentation\Shape\Chart as ShapeChart;
9
use PhpOffice\PhpPresentation\Shape\Comment;
10
use PhpOffice\PhpPresentation\Shape\Drawing as ShapeDrawing;
11
use PhpOffice\PhpPresentation\Shape\Group;
12
use PhpOffice\PhpPresentation\Shape\Line;
13
use PhpOffice\PhpPresentation\Shape\Media;
14
use PhpOffice\PhpPresentation\Shape\RichText;
15
use PhpOffice\PhpPresentation\Shape\RichText\BreakElement;
16
use PhpOffice\PhpPresentation\Shape\RichText\Run;
17
use PhpOffice\PhpPresentation\Shape\RichText\TextElement;
18
use PhpOffice\PhpPresentation\Shape\Table as ShapeTable;
19
use PhpOffice\PhpPresentation\Slide;
20
use PhpOffice\PhpPresentation\Slide\Background\Image;
21
use PhpOffice\PhpPresentation\Slide\Note;
22
use PhpOffice\PhpPresentation\Style\Alignment;
23
use PhpOffice\PhpPresentation\Style\Bullet;
24
use PhpOffice\PhpPresentation\Style\Border;
25
use PhpOffice\PhpPresentation\Style\Color;
26
27
class PptSlides extends AbstractSlide
28
{
29
    /**
30
     * Add slides (drawings, ...) and slide relationships (drawings, ...)
31
     * @return \PhpOffice\Common\Adapter\Zip\ZipInterface
32
     */
33
    public function render()
34 103
    {
35
        foreach ($this->oPresentation->getAllSlides() as $idx => $oSlide) {
36 103
            $this->oZip->addFromString('ppt/slides/_rels/slide' . ($idx + 1) . '.xml.rels', $this->writeSlideRelationships($oSlide));
37 103
            $this->oZip->addFromString('ppt/slides/slide' . ($idx + 1) . '.xml', $this->writeSlide($oSlide));
38 103
39
            // Add note slide
40
            if ($oSlide->getNote() instanceof Note) {
41 103
                if ($oSlide->getNote()->getShapeCollection()->count() > 0) {
42 103
                    $this->oZip->addFromString('ppt/notesSlides/notesSlide' . ($idx + 1) . '.xml', $this->writeNote($oSlide->getNote()));
43 1
                }
44 1
            }
45 103
46
            // Add background image slide
47
            $oBkgImage = $oSlide->getBackground();
48 103
            if ($oBkgImage instanceof Image) {
49 103
                $this->oZip->addFromString('ppt/media/'.$oBkgImage->getIndexedFilename($idx), file_get_contents($oBkgImage->getPath()));
50
            }
51
        }
52 103
53
        return $this->oZip;
54 103
    }
55
56
    /**
57
     * Write slide relationships to XML format
58
     *
59
     * @param  \PhpOffice\PhpPresentation\Slide $pSlide
60
     * @return string              XML Output
61
     * @throws \Exception
62
     */
63
    protected function writeSlideRelationships(Slide $pSlide)
64 103
    {
65
        //@todo Group all getShapeCollection()->getIterator
66
67
        // Create XML writer
68
        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
69 103
70
        // XML header
71
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
72 103
73
        // Relationships
74
        $objWriter->startElement('Relationships');
75 103
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
76 103
77
        // Starting relation id
78
        $relId = 1;
79 103
        $idxSlide = $pSlide->getParent()->getIndex($pSlide);
80 103
81
        // Write slideLayout relationship
82
        $layoutId = 1;
83 103
        if ($pSlide->getSlideLayout()) {
84 103
            $layoutId = $pSlide->getSlideLayout()->layoutNr;
85 103
        }
86 103
        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout', '../slideLayouts/slideLayout' . $layoutId . '.xml');
87 103
        ++$relId;
88 103
89
        // Write drawing relationships?
90
        if ($pSlide->getShapeCollection()->count() > 0) {
91 103
            // Loop trough images and write relationships
92
            $iterator = $pSlide->getShapeCollection()->getIterator();
93 76
            while ($iterator->valid()) {
94 76
                if ($iterator->current() instanceof Media) {
95 76
                    // Write relationship for image drawing
96
                    $iterator->current()->relationId = 'rId' . $relId;
97 1
                    $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/video', '../media/' . $iterator->current()->getIndexedFilename());
98 1
                    ++$relId;
99 1
                    $this->writeRelationship($objWriter, $relId, 'http://schemas.microsoft.com/office/2007/relationships/media', '../media/' . $iterator->current()->getIndexedFilename());
100 1
                    ++$relId;
101 1
                } elseif ($iterator->current() instanceof ShapeDrawing\AbstractDrawingAdapter) {
102 76
                    // Write relationship for image drawing
103
                    $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', '../media/' . $iterator->current()->getIndexedFilename());
104 7
                    $iterator->current()->relationId = 'rId' . $relId;
105 7
                    ++$relId;
106 7
                } elseif ($iterator->current() instanceof ShapeChart) {
107 75
                    // Write relationship for chart drawing
108
                    $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', '../charts/' . $iterator->current()->getIndexedFilename());
109 26
110
                    $iterator->current()->relationId = 'rId' . $relId;
111 26
112
                    ++$relId;
113 26
                } elseif ($iterator->current() instanceof Group) {
114 68
                    $iterator2 = $iterator->current()->getShapeCollection()->getIterator();
115 1
                    while ($iterator2->valid()) {
116 1
                        if ($iterator2->current() instanceof Media) {
117 1
                            // Write relationship for image drawing
118
                            $iterator2->current()->relationId = 'rId' . $relId;
119
                            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/video', '../media/' . $iterator->current()->getIndexedFilename());
120
                            ++$relId;
121
                            $this->writeRelationship($objWriter, $relId, 'http://schemas.microsoft.com/office/2007/relationships/media', '../media/' . $iterator->current()->getIndexedFilename());
122
                            ++$relId;
123
                        } elseif ($iterator2->current() instanceof ShapeDrawing\AbstractDrawingAdapter) {
124 1
                            // Write relationship for image drawing
125
                            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', '../media/' . $iterator2->current()->getIndexedFilename());
126
                            $iterator2->current()->relationId = 'rId' . $relId;
127
128
                            ++$relId;
129
                        } elseif ($iterator2->current() instanceof ShapeChart) {
130 1
                            // Write relationship for chart drawing
131
                            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', '../charts/' . $iterator2->current()->getIndexedFilename());
132
                            $iterator2->current()->relationId = 'rId' . $relId;
133
134
                            ++$relId;
135
                        }
136
                        $iterator2->next();
137 1
                    }
138 1
                }
139 1
140
                $iterator->next();
141 76
            }
142 76
        }
143 76
144
        // Write background relationships?
145
        $oBackground = $pSlide->getBackground();
146 103
        if ($oBackground instanceof Image) {
147 103
            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', '../media/' . $oBackground->getIndexedFilename($idxSlide));
148
            $oBackground->relationId = 'rId' . $relId;
149
            ++$relId;
150
        }
151
152
        // Write hyperlink relationships?
153
        if ($pSlide->getShapeCollection()->count() > 0) {
154 103
            // Loop trough hyperlinks and write relationships
155
            $iterator = $pSlide->getShapeCollection()->getIterator();
156 76
            while ($iterator->valid()) {
157 76
                // Hyperlink on shape
158
                if ($iterator->current()->hasHyperlink()) {
159 76
                    // Write relationship for hyperlink
160
                    $hyperlink               = $iterator->current()->getHyperlink();
161 2
                    $hyperlink->relationId = 'rId' . $relId;
162 2
163
                    if (!$hyperlink->isInternal()) {
164 2
                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
165 2
                    } else {
166 2
                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
167
                    }
168
169
                    ++$relId;
170 2
                }
171 2
172
                // Hyperlink on rich text run
173
                if ($iterator->current() instanceof RichText) {
174 76
                    foreach ($iterator->current()->getParagraphs() as $paragraph) {
175 24
                        foreach ($paragraph->getRichTextElements() as $element) {
176 24
                            if ($element instanceof Run || $element instanceof TextElement) {
177 19
                                if ($element->hasHyperlink()) {
178 18
                                    // Write relationship for hyperlink
179
                                    $hyperlink               = $element->getHyperlink();
180 2
                                    $hyperlink->relationId = 'rId' . $relId;
181 2
182
                                    if (!$hyperlink->isInternal()) {
183 2
                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
184 1
                                    } else {
185 1
                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
186 1
                                    }
187
188
                                    ++$relId;
189 2
                                }
190 2
                            }
191 18
                        }
192 24
                    }
193 24
                }
194 24
195
                // Hyperlink in table
196
                if ($iterator->current() instanceof ShapeTable) {
197 76
                    // Rows
198
                    $countRows = count($iterator->current()->getRows());
199 10
                    for ($row = 0; $row < $countRows; $row++) {
200 10
                        // Cells in rows
201
                        $countCells = count($iterator->current()->getRow($row)->getCells());
202 10
                        for ($cell = 0; $cell < $countCells; $cell++) {
203 10
                            $currentCell = $iterator->current()->getRow($row)->getCell($cell);
204 10
                            // Paragraphs in cell
205
                            foreach ($currentCell->getParagraphs() as $paragraph) {
206 10
                                // RichText in paragraph
207
                                foreach ($paragraph->getRichTextElements() as $element) {
208 10
                                    // Run or Text in RichText
209
                                    if ($element instanceof Run || $element instanceof TextElement) {
210 10
                                        if ($element->hasHyperlink()) {
211 10
                                            // Write relationship for hyperlink
212
                                            $hyperlink               = $element->getHyperlink();
213 1
                                            $hyperlink->relationId = 'rId' . $relId;
214 1
215
                                            if (!$hyperlink->isInternal()) {
216 1
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
217 1
                                            } else {
218 1
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
219
                                            }
220
221
                                            ++$relId;
222 1
                                        }
223 1
                                    }
224 10
                                }
225 10
                            }
226 10
                        }
227 10
                    }
228 10
                }
229 10
230
                if ($iterator->current() instanceof Group) {
231 76
                    $iterator2 = $pSlide->getShapeCollection()->getIterator();
232 1
                    while ($iterator2->valid()) {
233 1
                        // Hyperlink on shape
234
                        if ($iterator2->current()->hasHyperlink()) {
235 1
                            // Write relationship for hyperlink
236
                            $hyperlink             = $iterator2->current()->getHyperlink();
237
                            $hyperlink->relationId = 'rId' . $relId;
238
239
                            if (!$hyperlink->isInternal()) {
240
                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
241
                            } else {
242
                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
243
                            }
244
245
                            ++$relId;
246
                        }
247
248
                        // Hyperlink on rich text run
249
                        if ($iterator2->current() instanceof RichText) {
250 1
                            foreach ($iterator2->current()->getParagraphs() as $paragraph) {
251
                                foreach ($paragraph->getRichTextElements() as $element) {
252
                                    if ($element instanceof Run || $element instanceof TextElement) {
253
                                        if ($element->hasHyperlink()) {
254
                                            // Write relationship for hyperlink
255
                                            $hyperlink              = $element->getHyperlink();
256
                                            $hyperlink->relationId = 'rId' . $relId;
257
258
                                            if (!$hyperlink->isInternal()) {
259
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
260
                                            } else {
261
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
262
                                            }
263
264
                                            ++$relId;
265
                                        }
266
                                    }
267
                                }
268
                            }
269
                        }
270
271
                        // Hyperlink in table
272
                        if ($iterator2->current() instanceof ShapeTable) {
273 1
                            // Rows
274
                            $countRows = count($iterator2->current()->getRows());
275
                            for ($row = 0; $row < $countRows; $row++) {
276
                                // Cells in rows
277
                                $countCells = count($iterator2->current()->getRow($row)->getCells());
278
                                for ($cell = 0; $cell < $countCells; $cell++) {
279
                                    $currentCell = $iterator2->current()->getRow($row)->getCell($cell);
280
                                    // Paragraphs in cell
281
                                    foreach ($currentCell->getParagraphs() as $paragraph) {
282
                                        // RichText in paragraph
283
                                        foreach ($paragraph->getRichTextElements() as $element) {
284
                                            // Run or Text in RichText
285
                                            if ($element instanceof Run || $element instanceof TextElement) {
286
                                                if ($element->hasHyperlink()) {
287
                                                    // Write relationship for hyperlink
288
                                                    $hyperlink               = $element->getHyperlink();
289
                                                    $hyperlink->relationId = 'rId' . $relId;
290
291
                                                    if (!$hyperlink->isInternal()) {
292
                                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
293
                                                    } else {
294
                                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
295
                                                    }
296
297
                                                    ++$relId;
298
                                                }
299
                                            }
300
                                        }
301
                                    }
302
                                }
303
                            }
304
                        }
305
306
                        $iterator2->next();
307 1
                    }
308 1
                }
309 1
310
                $iterator->next();
311 76
            }
312 76
        }
313 76
314
        // Write comment relationships
315
        if ($pSlide->getShapeCollection()->count() > 0) {
316 103
            $hasSlideComment = false;
317 76
318
            // Loop trough images and write relationships
319
            $iterator = $pSlide->getShapeCollection()->getIterator();
320 76
            while ($iterator->valid()) {
321 76
                if ($iterator->current() instanceof Comment) {
322 76
                    $hasSlideComment = true;
323 6
                    break;
324 6
                } elseif ($iterator->current() instanceof Group) {
325 70
                    $iterator2 = $iterator->current()->getShapeCollection()->getIterator();
326 1
                    while ($iterator2->valid()) {
327 1
                        if ($iterator2->current() instanceof Comment) {
328 1
                            $hasSlideComment = true;
329 1
                            break 2;
330 1
                        }
331
                        $iterator2->next();
332
                    }
333
                }
334
335
                $iterator->next();
336 69
            }
337 69
338
            if ($hasSlideComment) {
339 76
                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments', '../comments/comment'.($idxSlide + 1).'.xml');
340 7
                ++$relId;
341 7
            }
342 7
        }
343 76
344
        if ($pSlide->getNote()->getShapeCollection()->count() > 0) {
345 103
            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide', '../notesSlides/notesSlide'.($idxSlide + 1).'.xml');
346 1
        }
347 1
348
        $objWriter->endElement();
349 103
350
        // Return
351
        return $objWriter->getData();
352 103
    }
353
354
    /**
355
     * Write slide to XML format
356
     *
357
     * @param  \PhpOffice\PhpPresentation\Slide $pSlide
358
     * @return string              XML Output
359
     * @throws \Exception
360
     */
361
    public function writeSlide(Slide $pSlide)
362 103
    {
363
        // Create XML writer
364
        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
365 103
366
        // XML header
367
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
368 103
369
        // p:sld
370
        $objWriter->startElement('p:sld');
371 103
        $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
372 103
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
373 103
        $objWriter->writeAttribute('xmlns:p', 'http://schemas.openxmlformats.org/presentationml/2006/main');
374 103
        $objWriter->writeAttributeIf(!$pSlide->isVisible(), 'show', 0);
375 103
376
        // p:sld/p:cSld
377
        $objWriter->startElement('p:cSld');
378 103
379
        // Background
380
        if ($pSlide->getBackground() instanceof Slide\AbstractBackground) {
381 103
            $oBackground = $pSlide->getBackground();
382
            // p:bg
383
            $objWriter->startElement('p:bg');
384
385
            // p:bgPr
386
            $objWriter->startElement('p:bgPr');
387
388
            if ($oBackground instanceof Slide\Background\Color) {
389
                // a:solidFill
390
                $objWriter->startElement('a:solidFill');
391
392
                $this->writeColor($objWriter, $oBackground->getColor());
393
394
                // > a:solidFill
395
                $objWriter->endElement();
396
            }
397
398
            if ($oBackground instanceof Slide\Background\Image) {
399
                // a:blipFill
400
                $objWriter->startElement('a:blipFill');
401
402
                // a:blip
403
                $objWriter->startElement('a:blip');
404
                $objWriter->writeAttribute('r:embed', $oBackground->relationId);
405
406
                // > a:blipFill
407
                $objWriter->endElement();
408
409
                // a:stretch
410
                $objWriter->startElement('a:stretch');
411
412
                // a:fillRect
413
                $objWriter->writeElement('a:fillRect');
414
415
                // > a:stretch
416
                $objWriter->endElement();
417
418
                // > a:blipFill
419
                $objWriter->endElement();
420
            }
421
422
            // > p:bgPr
423
            $objWriter->endElement();
424
425
            // > p:bg
426
            $objWriter->endElement();
427
        }
428
429
        // p:spTree
430
        $objWriter->startElement('p:spTree');
431 103
432
        // p:nvGrpSpPr
433
        $objWriter->startElement('p:nvGrpSpPr');
434 103
435
        // p:cNvPr
436
        $objWriter->startElement('p:cNvPr');
437 103
        $objWriter->writeAttribute('id', '1');
438 103
        $objWriter->writeAttribute('name', '');
439 103
        $objWriter->endElement();
440 103
441
        // p:cNvGrpSpPr
442
        $objWriter->writeElement('p:cNvGrpSpPr', null);
443 103
444
        // p:nvPr
445
        $objWriter->writeElement('p:nvPr', null);
446 103
447
        $objWriter->endElement();
448 103
449
        // p:grpSpPr
450
        $objWriter->startElement('p:grpSpPr');
451 103
452
        // a:xfrm
453
        $objWriter->startElement('a:xfrm');
454 103
455
        // a:off
456
        $objWriter->startElement('a:off');
457 103
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pSlide->getOffsetX()));
458 103
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pSlide->getOffsetY()));
459 103
        $objWriter->endElement(); // a:off
460 103
461
        // a:ext
462
        $objWriter->startElement('a:ext');
463 103
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pSlide->getExtentX()));
464 103
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pSlide->getExtentY()));
465 103
        $objWriter->endElement(); // a:ext
466 103
467
        // a:chOff
468
        $objWriter->startElement('a:chOff');
469 103
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pSlide->getOffsetX()));
470 103
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pSlide->getOffsetY()));
471 103
        $objWriter->endElement(); // a:chOff
472 103
473
        // a:chExt
474
        $objWriter->startElement('a:chExt');
475 103
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pSlide->getExtentX()));
476 103
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pSlide->getExtentY()));
477 103
        $objWriter->endElement(); // a:chExt
478 103
479
        $objWriter->endElement();
480 103
481
        $objWriter->endElement();
482 103
483
        // Loop shapes
484
        $this->writeShapeCollection($objWriter, $pSlide->getShapeCollection());
485 103
486
        // TODO
487
        $objWriter->endElement();
488 103
489
        $objWriter->endElement();
490 103
491
        // p:clrMapOvr
492
        $objWriter->startElement('p:clrMapOvr');
493 103
        // p:clrMapOvr\a:masterClrMapping
494
        $objWriter->writeElement('a:masterClrMapping', null);
495 103
        // ##p:clrMapOvr
496
        $objWriter->endElement();
497 103
498
        $this->writeSlideTransition($objWriter, $pSlide->getTransition());
499 103
500
        $this->writeSlideAnimations($objWriter, $pSlide);
501 103
502
        $objWriter->endElement();
503 103
504
        // Return
505
        return $objWriter->getData();
506 103
    }
507
508
    /**
509
     * @param XMLWriter $objWriter
510
     * @param Slide $oSlide
511
     */
512
    protected function writeSlideAnimations(XMLWriter $objWriter, Slide $oSlide)
513 103
    {
514
        $arrayAnimations = $oSlide->getAnimations();
515 103
        if (empty($arrayAnimations)) {
516 103
            return;
517 102
        }
518
519
        // Variables
520
        $shapeId = 1;
521 1
        $idCount = 1;
522 1
        $hashToIdMap = array();
523 1
        $arrayAnimationIds = array();
524 1
525
        foreach ($oSlide->getShapeCollection() as $shape) {
526 1
            $hashToIdMap[$shape->getHashCode()] = ++$shapeId;
527 1
        }
528 1
        foreach ($arrayAnimations as $oAnimation) {
529 1
            foreach ($oAnimation->getShapeCollection() as $oShape) {
530 1
                $arrayAnimationIds[] = $hashToIdMap[$oShape->getHashCode()];
531 1
            }
532 1
        }
533 1
534
        // p:timing
535
        $objWriter->startElement('p:timing');
536 1
        // p:timing/p:tnLst
537
        $objWriter->startElement('p:tnLst');
538 1
        // p:timing/p:tnLst/p:par
539
        $objWriter->startElement('p:par');
540 1
        // p:timing/p:tnLst/p:par/p:cTn
541
        $objWriter->startElement('p:cTn');
542 1
        $objWriter->writeAttribute('id', $idCount++);
543 1
        $objWriter->writeAttribute('dur', 'indefinite');
544 1
        $objWriter->writeAttribute('restart', 'never');
545 1
        $objWriter->writeAttribute('nodeType', 'tmRoot');
546 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst
547
        $objWriter->startElement('p:childTnLst');
548 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq
549
        $objWriter->startElement('p:seq');
550 1
        $objWriter->writeAttribute('concurrent', '1');
551 1
        $objWriter->writeAttribute('nextAc', 'seek');
552 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn
553
        $objWriter->startElement('p:cTn');
554 1
        $objWriter->writeAttribute('id', $idCount++);
555 1
        $objWriter->writeAttribute('dur', 'indefinite');
556 1
        $objWriter->writeAttribute('nodeType', 'mainSeq');
557 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst
558
        $objWriter->startElement('p:childTnLst');
559 1
560
        // Each animation has multiple shapes
561
        foreach ($arrayAnimations as $oAnimation) {
562 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par
563
            $objWriter->startElement('p:par');
564 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn
565
            $objWriter->startElement('p:cTn');
566 1
            $objWriter->writeAttribute('id', $idCount++);
567 1
            $objWriter->writeAttribute('fill', 'hold');
568 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:stCondLst
569
            $objWriter->startElement('p:stCondLst');
570 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:stCondLst/p:cond
571
            $objWriter->startElement('p:cond');
572 1
            $objWriter->writeAttribute('delay', 'indefinite');
573 1
            $objWriter->endElement();
574 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn\##p:stCondLst
575
            $objWriter->endElement();
576 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst
577
            $objWriter->startElement('p:childTnLst');
578 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par
579
            $objWriter->startElement('p:par');
580 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn
581
            $objWriter->startElement('p:cTn');
582 1
            $objWriter->writeAttribute('id', $idCount++);
583 1
            $objWriter->writeAttribute('fill', 'hold');
584 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:stCondLst
585
            $objWriter->startElement('p:stCondLst');
586 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:stCondLst/p:cond
587
            $objWriter->startElement('p:cond');
588 1
            $objWriter->writeAttribute('delay', '0');
589 1
            $objWriter->endElement();
590 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn\##p:stCondLst
591
            $objWriter->endElement();
592 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst
593
            $objWriter->startElement('p:childTnLst');
594 1
595
            $firstAnimation = true;
596 1
            foreach ($oAnimation->getShapeCollection() as $oShape) {
597 1
                $nodeType = $firstAnimation ? 'clickEffect' : 'withEffect';
598 1
                $shapeId = $hashToIdMap[$oShape->getHashCode()];
599 1
600
                // p:par
601
                $objWriter->startElement('p:par');
602 1
                // p:par/p:cTn
603
                $objWriter->startElement('p:cTn');
604 1
                $objWriter->writeAttribute('id', $idCount++);
605 1
                $objWriter->writeAttribute('presetID', '1');
606 1
                $objWriter->writeAttribute('presetClass', 'entr');
607 1
                $objWriter->writeAttribute('fill', 'hold');
608 1
                $objWriter->writeAttribute('presetSubtype', '0');
609 1
                $objWriter->writeAttribute('grpId', '0');
610 1
                $objWriter->writeAttribute('nodeType', $nodeType);
611 1
                // p:par/p:cTn/p:stCondLst
612
                $objWriter->startElement('p:stCondLst');
613 1
                // p:par/p:cTn/p:stCondLst/p:cond
614
                $objWriter->startElement('p:cond');
615 1
                $objWriter->writeAttribute('delay', '0');
616 1
                $objWriter->endElement();
617 1
                // p:par/p:cTn\##p:stCondLst
618
                $objWriter->endElement();
619 1
                // p:par/p:cTn/p:childTnLst
620
                $objWriter->startElement('p:childTnLst');
621 1
                // p:par/p:cTn/p:childTnLst/p:set
622
                $objWriter->startElement('p:set');
623 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr
624
                $objWriter->startElement('p:cBhvr');
625 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn
626
                $objWriter->startElement('p:cTn');
627 1
                $objWriter->writeAttribute('id', $idCount++);
628 1
                $objWriter->writeAttribute('dur', '1');
629 1
                $objWriter->writeAttribute('fill', 'hold');
630 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn/p:stCondLst
631
                $objWriter->startElement('p:stCondLst');
632 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn/p:stCondLst/p:cond
633
                $objWriter->startElement('p:cond');
634 1
                $objWriter->writeAttribute('delay', '0');
635 1
                $objWriter->endElement();
636 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn\##p:stCondLst
637
                $objWriter->endElement();
638 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr\##p:cTn
639
                $objWriter->endElement();
640 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:tgtEl
641
                $objWriter->startElement('p:tgtEl');
642 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:tgtEl/p:spTgt
643
                $objWriter->startElement('p:spTgt');
644 1
                $objWriter->writeAttribute('spid', $shapeId);
645 1
                $objWriter->endElement();
646 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr\##p:tgtEl
647
                $objWriter->endElement();
648 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:attrNameLst
649
                $objWriter->startElement('p:attrNameLst');
650 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:attrNameLst/p:attrName
651
                $objWriter->writeElement('p:attrName', 'style.visibility');
652 1
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr\##p:attrNameLst
653
                $objWriter->endElement();
654 1
                // p:par/p:cTn/p:childTnLst/p:set\##p:cBhvr
655
                $objWriter->endElement();
656 1
                // p:par/p:cTn/p:childTnLst/p:set/p:to
657
                $objWriter->startElement('p:to');
658 1
                // p:par/p:cTn/p:childTnLst/p:set/p:to/p:strVal
659
                $objWriter->startElement('p:strVal');
660 1
                $objWriter->writeAttribute('val', 'visible');
661 1
                $objWriter->endElement();
662 1
                // p:par/p:cTn/p:childTnLst/p:set\##p:to
663
                $objWriter->endElement();
664 1
                // p:par/p:cTn/p:childTnLst\##p:set
665
                $objWriter->endElement();
666 1
                // p:par/p:cTn\##p:childTnLst
667
                $objWriter->endElement();
668 1
                // p:par\##p:cTn
669
                $objWriter->endElement();
670 1
                // ##p:par
671
                $objWriter->endElement();
672 1
673
                $firstAnimation = false;
674 1
            }
675 1
676
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par/p:cTn\##p:childTnLst
677
            $objWriter->endElement();
678 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par\##p:cTn
679
            $objWriter->endElement();
680 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst\##p:par
681
            $objWriter->endElement();
682 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn\##p:childTnLst
683
            $objWriter->endElement();
684 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par\##p:cTn
685
            $objWriter->endElement();
686 1
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst\##p:par
687
            $objWriter->endElement();
688 1
        }
689 1
690
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn\##p:childTnLst
691
        $objWriter->endElement();
692 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq\##p:cTn
693
        $objWriter->endElement();
694 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst
695
        $objWriter->startElement('p:prevCondLst');
696 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond
697
        $objWriter->startElement('p:cond');
698 1
        $objWriter->writeAttribute('evt', 'onPrev');
699 1
        $objWriter->writeAttribute('delay', '0');
700 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond/p:tgtEl
701
        $objWriter->startElement('p:tgtEl');
702 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond/p:tgtEl/p:sldTgt
703
        $objWriter->writeElement('p:sldTgt', null);
704 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond\##p:tgtEl
705
        $objWriter->endElement();
706 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst\##p:cond
707
        $objWriter->endElement();
708 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq\##p:prevCondLst
709
        $objWriter->endElement();
710 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst
711
        $objWriter->startElement('p:nextCondLst');
712 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond
713
        $objWriter->startElement('p:cond');
714 1
        $objWriter->writeAttribute('evt', 'onNext');
715 1
        $objWriter->writeAttribute('delay', '0');
716 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond/p:tgtEl
717
        $objWriter->startElement('p:tgtEl');
718 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond/p:tgtEl/p:sldTgt
719
        $objWriter->writeElement('p:sldTgt', null);
720 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond\##p:tgtEl
721
        $objWriter->endElement();
722 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst\##p:cond
723
        $objWriter->endElement();
724 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq\##p:nextCondLst
725
        $objWriter->endElement();
726 1
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst\##p:seq
727
        $objWriter->endElement();
728 1
        // p:timing/p:tnLst/p:par/p:cTn\##p:childTnLst
729
        $objWriter->endElement();
730 1
        // p:timing/p:tnLst/p:par\##p:cTn
731
        $objWriter->endElement();
732 1
        // p:timing/p:tnLst\##p:par
733
        $objWriter->endElement();
734 1
        // p:timing\##p:tnLst
735
        $objWriter->endElement();
736 1
737
        // p:timing/p:bldLst
738
        $objWriter->startElement('p:bldLst');
739 1
740
        // Add in ids of all shapes in this slides animations
741
        foreach ($arrayAnimationIds as $id) {
742 1
            // p:timing/p:bldLst/p:bldP
743
            $objWriter->startElement('p:bldP');
744 1
            $objWriter->writeAttribute('spid', $id);
745 1
            $objWriter->writeAttribute('grpId', 0);
746 1
            $objWriter->endELement();
747 1
        }
748 1
749
        // p:timing\##p:bldLst
750
        $objWriter->endElement();
751 1
752
        // ##p:timing
753
        $objWriter->endElement();
754 1
    }
755 1
756
    /**
757
     * Write group
758
     *
759
     * @param \PhpOffice\Common\XMLWriter $objWriter XML Writer
760
     * @param \PhpOffice\PhpPresentation\Shape\Group $group
761
     * @param  int $shapeId
762
     */
763
    protected function writeShapeGroup(XMLWriter $objWriter, Group $group, &$shapeId)
764 1
    {
765
        // p:grpSp
766
        $objWriter->startElement('p:grpSp');
767 1
768
        // p:nvGrpSpPr
769
        $objWriter->startElement('p:nvGrpSpPr');
770 1
771
        // p:cNvPr
772
        $objWriter->startElement('p:cNvPr');
773 1
        $objWriter->writeAttribute('name', 'Group '.$shapeId++);
774 1
        $objWriter->writeAttribute('id', $shapeId);
775 1
        $objWriter->endElement(); // p:cNvPr
776 1
        // NOTE: Re: $shapeId This seems to be how PowerPoint 2010 does business.
777
778
        // p:cNvGrpSpPr
779
        $objWriter->writeElement('p:cNvGrpSpPr', null);
780 1
781
        // p:nvPr
782
        $objWriter->writeElement('p:nvPr', null);
783 1
784
        $objWriter->endElement(); // p:nvGrpSpPr
785 1
786
        // p:grpSpPr
787
        $objWriter->startElement('p:grpSpPr');
788 1
789
        // a:xfrm
790
        $objWriter->startElement('a:xfrm');
791 1
792
        // a:off
793
        $objWriter->startElement('a:off');
794 1
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($group->getOffsetX()));
795 1
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($group->getOffsetY()));
796 1
        $objWriter->endElement(); // a:off
797 1
798
        // a:ext
799
        $objWriter->startElement('a:ext');
800 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($group->getExtentX()));
801 1
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($group->getExtentY()));
802 1
        $objWriter->endElement(); // a:ext
803 1
804
        // a:chOff
805
        $objWriter->startElement('a:chOff');
806 1
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($group->getOffsetX()));
807 1
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($group->getOffsetY()));
808 1
        $objWriter->endElement(); // a:chOff
809 1
810
        // a:chExt
811
        $objWriter->startElement('a:chExt');
812 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($group->getExtentX()));
813 1
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($group->getExtentY()));
814 1
        $objWriter->endElement(); // a:chExt
815 1
816
        $objWriter->endElement(); // a:xfrm
817 1
818
        $objWriter->endElement(); // p:grpSpPr
819 1
820
        $this->writeShapeCollection($objWriter, $group->getShapeCollection(), $shapeId);
821 1
        $objWriter->endElement(); // p:grpSp
822 1
    }
823 1
824
    /**
825
     * Write chart
826
     *
827
     * @param \PhpOffice\Common\XMLWriter $objWriter XML Writer
828
     * @param \PhpOffice\PhpPresentation\Shape\Chart $shape
829
     * @param  int $shapeId
830
     */
831
    protected function writeShapeChart(XMLWriter $objWriter, ShapeChart $shape, $shapeId)
832 26
    {
833
        // p:graphicFrame
834
        $objWriter->startElement('p:graphicFrame');
835 26
836
        // p:nvGraphicFramePr
837
        $objWriter->startElement('p:nvGraphicFramePr');
838 26
839
        // p:cNvPr
840
        $objWriter->startElement('p:cNvPr');
841 26
        $objWriter->writeAttribute('id', $shapeId);
842 26
        $objWriter->writeAttribute('name', $shape->getName());
843 26
        $objWriter->writeAttribute('descr', $shape->getDescription());
844 26
        $objWriter->endElement();
845 26
846
        // p:cNvGraphicFramePr
847
        $objWriter->writeElement('p:cNvGraphicFramePr', null);
848 26
849
        // p:nvPr
850
        $objWriter->startElement('p:nvPr');
851 26
        if ($shape->isPlaceholder()) {
852 26
            $objWriter->startElement('p:ph');
853
            $objWriter->writeAttribute('type', $shape->getPlaceholder()->getType());
854
            $objWriter->endElement();
855
        }
856
        $objWriter->endElement();
857 26
858
        $objWriter->endElement();
859 26
860
        // p:xfrm
861
        $objWriter->startElement('p:xfrm');
862 26
        $objWriter->writeAttributeIf($shape->getRotation() != 0, 'rot', CommonDrawing::degreesToAngle($shape->getRotation()));
863 26
864
        // a:off
865
        $objWriter->startElement('a:off');
866 26
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
867 26
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
868 26
        $objWriter->endElement();
869 26
870
        // a:ext
871
        $objWriter->startElement('a:ext');
872 26
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
873 26
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
874 26
        $objWriter->endElement();
875 26
876
        $objWriter->endElement();
877 26
878
        // a:graphic
879
        $objWriter->startElement('a:graphic');
880 26
881
        // a:graphicData
882
        $objWriter->startElement('a:graphicData');
883 26
        $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
884 26
885
        // c:chart
886
        $objWriter->startElement('c:chart');
887 26
        $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
888 26
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
889 26
        $objWriter->writeAttribute('r:id', $shape->relationId);
890 26
        $objWriter->endElement();
891 26
892
        $objWriter->endElement();
893 26
894
        $objWriter->endElement();
895 26
896
        $objWriter->endElement();
897 26
    }
898 26
899
    /**
900
     * Write pic
901
     *
902
     * @param  \PhpOffice\Common\XMLWriter  $objWriter XML Writer
903
     * @param  \PhpOffice\PhpPresentation\Shape\Drawing\AbstractDrawingAdapter $shape
904
     * @param  int $shapeId
905
     * @throws \Exception
906
     */
907
    protected function writeShapeDrawing(XMLWriter $objWriter, ShapeDrawing\AbstractDrawingAdapter $shape, $shapeId)
908
    {
909
        // p:pic
910
        $objWriter->startElement('p:pic');
911
912
        // p:nvPicPr
913
        $objWriter->startElement('p:nvPicPr');
914
915
        // p:cNvPr
916
        $objWriter->startElement('p:cNvPr');
917
        $objWriter->writeAttribute('id', $shapeId);
918
        $objWriter->writeAttribute('name', $shape->getName());
919
        $objWriter->writeAttribute('descr', $shape->getDescription());
920
921
        // a:hlinkClick
922
        if ($shape->hasHyperlink()) {
923
            $this->writeHyperlink($objWriter, $shape);
924
        }
925
926
        $objWriter->endElement();
927
928
        // p:cNvPicPr
929
        $objWriter->startElement('p:cNvPicPr');
930
931
        // a:picLocks
932
        $objWriter->startElement('a:picLocks');
933
        $objWriter->writeAttribute('noChangeAspect', '1');
934
        $objWriter->endElement();
935
936
        $objWriter->endElement();
937
938
        // p:nvPr
939
        $objWriter->startElement('p:nvPr');
940
        // PlaceHolder
941
        if ($shape->isPlaceholder()) {
942
            $objWriter->startElement('p:ph');
943
            $objWriter->writeAttribute('type', $shape->getPlaceholder()->getType());
944
            $objWriter->endElement();
945
        }
946
        /**
947
         * @link : https://github.com/stefslon/exportToPPTX/blob/master/exportToPPTX.m#L2128
948
         */
949
        if ($shape instanceof Media) {
950
            // p:nvPr > a:videoFile
951
            $objWriter->startElement('a:videoFile');
952
            $objWriter->writeAttribute('r:link', $shape->relationId);
953
            $objWriter->endElement();
954
            // p:nvPr > p:extLst
955
            $objWriter->startElement('p:extLst');
956
            // p:nvPr > p:extLst > p:ext
957
            $objWriter->startElement('p:ext');
958
            $objWriter->writeAttribute('uri', '{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}');
959
            // p:nvPr > p:extLst > p:ext > p14:media
960
            $objWriter->startElement('p14:media');
961
            $objWriter->writeAttribute('r:embed', ($shape->relationId + 1));
962
            $objWriter->writeAttribute('xmlns:p14', 'http://schemas.microsoft.com/office/powerpoint/2010/main');
963
            // p:nvPr > p:extLst > p:ext > ##p14:media
964
            $objWriter->endElement();
965
            // p:nvPr > p:extLst > ##p:ext
966
            $objWriter->endElement();
967
            // p:nvPr > ##p:extLst
968
            $objWriter->endElement();
969
        }
970
        // ##p:nvPr
971
        $objWriter->endElement();
972
        $objWriter->endElement();
973
974
        // p:blipFill
975
        $objWriter->startElement('p:blipFill');
976
977
        // a:blip
978
        $objWriter->startElement('a:blip');
979
        $objWriter->writeAttribute('r:embed', $shape->relationId);
980
        $objWriter->endElement();
981
982
        // a:stretch
983
        $objWriter->startElement('a:stretch');
984
        $objWriter->writeElement('a:fillRect', null);
985
        $objWriter->endElement();
986
987
        $objWriter->endElement();
988
989
        // p:spPr
990
        $objWriter->startElement('p:spPr');
991
        // a:xfrm
992
        $objWriter->startElement('a:xfrm');
993
        $objWriter->writeAttributeIf($shape->getRotation() != 0, 'rot', CommonDrawing::degreesToAngle($shape->getRotation()));
994
995
        // a:off
996
        $objWriter->startElement('a:off');
997
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
998
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
999
        $objWriter->endElement();
1000
1001
        // a:ext
1002
        $objWriter->startElement('a:ext');
1003
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1004
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1005
        $objWriter->endElement();
1006
1007
        $objWriter->endElement();
1008
1009
        // a:prstGeom
1010
        $objWriter->startElement('a:prstGeom');
1011
        $objWriter->writeAttribute('prst', 'rect');
1012
1013
        // a:avLst
1014
        $objWriter->writeElement('a:avLst', null);
1015
1016
        $objWriter->endElement();
1017
1018
        $this->writeBorder($objWriter, $shape->getBorder(), '');
1019
1020
        $this->writeShadow($objWriter, $shape->getShadow());
1021
1022
        $objWriter->endElement();
1023
1024
        $objWriter->endElement();
1025
    }
1026
1027
    /**
1028
     * Write txt
1029
     *
1030
     * @param  \PhpOffice\Common\XMLWriter $objWriter XML Writer
1031
     * @param  \PhpOffice\PhpPresentation\Shape\RichText   $shape
1032
     * @param  int                            $shapeId
1033
     * @throws \Exception
1034
     */
1035
    protected function writeShapeText(XMLWriter $objWriter, RichText $shape, $shapeId)
1036 24
    {
1037
        // p:sp
1038
        $objWriter->startElement('p:sp');
1039 24
1040
        // p:sp/p:nvSpPr
1041
        $objWriter->startElement('p:nvSpPr');
1042 24
1043
        // p:sp/p:nvSpPr/p:cNvPr
1044
        $objWriter->startElement('p:cNvPr');
1045 24
        $objWriter->writeAttribute('id', $shapeId);
1046 24
        $objWriter->writeAttribute('name', '');
1047 24
1048
        // Hyperlink
1049
        if ($shape->hasHyperlink()) {
1050 24
            $this->writeHyperlink($objWriter, $shape);
1051 1
        }
1052 1
        // > p:sp/p:nvSpPr
1053
        $objWriter->endElement();
1054 24
1055
        // p:sp/p:cNvSpPr
1056
        $objWriter->startElement('p:cNvSpPr');
1057 24
        $objWriter->writeAttribute('txBox', '1');
1058 24
        $objWriter->endElement();
1059 24
        // p:sp/p:cNvSpPr/p:nvPr
1060
        $objWriter->startElement('p:nvPr');
1061 24
        if ($shape->isPlaceholder()) {
1062 24
            $objWriter->startElement('p:ph');
1063
            $objWriter->writeAttribute('type', $shape->getPlaceholder()->getType());
1064
            $objWriter->endElement();
1065
        }
1066
        $objWriter->endElement();
1067 24
1068
        // > p:sp/p:cNvSpPr
1069
        $objWriter->endElement();
1070 24
1071
        // p:sp/p:spPr
1072
        $objWriter->startElement('p:spPr');
1073 24
1074
        if (!$shape->isPlaceholder()) {
1075 24
            // p:sp/p:spPr\a:xfrm
1076
            $objWriter->startElement('a:xfrm');
1077 24
            $objWriter->writeAttributeIf($shape->getRotation() != 0, 'rot', CommonDrawing::degreesToAngle($shape->getRotation()));
1078 24
1079
            // p:sp/p:spPr\a:xfrm\a:off
1080
            $objWriter->startElement('a:off');
1081 24
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1082 24
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1083 24
            $objWriter->endElement();
1084 24
1085
            // p:sp/p:spPr\a:xfrm\a:ext
1086
            $objWriter->startElement('a:ext');
1087 24
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1088 24
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1089 24
            $objWriter->endElement();
1090 24
1091
            // > p:sp/p:spPr\a:xfrm
1092
            $objWriter->endElement();
1093 24
1094
            // p:sp/p:spPr\a:prstGeom
1095
            $objWriter->startElement('a:prstGeom');
1096 24
            $objWriter->writeAttribute('prst', 'rect');
1097 24
            $objWriter->endElement();
1098 24
        }
1099 24
1100
        $this->writeFill($objWriter, $shape->getFill());
1101 24
        $this->writeBorder($objWriter, $shape->getBorder(), '');
1102 24
        $this->writeShadow($objWriter, $shape->getShadow());
1103 24
1104
        // > p:sp/p:spPr
1105
        $objWriter->endElement();
1106 24
1107
        // p:txBody
1108
        $objWriter->startElement('p:txBody');
1109 24
1110
        // a:bodyPr
1111
        //@link :http://msdn.microsoft.com/en-us/library/documentformat.openxml.drawing.bodyproperties%28v=office.14%29.aspx
1112
        $objWriter->startElement('a:bodyPr');
1113 24
        if (!$shape->isPlaceholder()) {
1114 24
            $verticalAlign = $shape->getActiveParagraph()->getAlignment()->getVertical();
1115 24
            if ($verticalAlign != Alignment::VERTICAL_BASE && $verticalAlign != Alignment::VERTICAL_AUTO) {
1116 24
                $objWriter->writeAttribute('anchor', $verticalAlign);
1117 3
            }
1118 3
            if ($shape->getWrap() != RichText::WRAP_SQUARE) {
1119 24
                $objWriter->writeAttribute('wrap', $shape->getWrap());
1120
            }
1121
            $objWriter->writeAttribute('rtlCol', '0');
1122 24
1123
            if ($shape->getHorizontalOverflow() != RichText::OVERFLOW_OVERFLOW) {
1124 24
                $objWriter->writeAttribute('horzOverflow', $shape->getHorizontalOverflow());
1125
            }
1126
            if ($shape->getVerticalOverflow() != RichText::OVERFLOW_OVERFLOW) {
1127 24
                $objWriter->writeAttribute('vertOverflow', $shape->getVerticalOverflow());
1128
            }
1129
1130
            if ($shape->isUpright()) {
1131 24
                $objWriter->writeAttribute('upright', '1');
1132 1
            }
1133 1
            if ($shape->isVertical()) {
1134 24
                $objWriter->writeAttribute('vert', 'vert');
1135 1
            }
1136 1
1137
            $objWriter->writeAttribute('bIns', CommonDrawing::pixelsToEmu($shape->getInsetBottom()));
1138 24
            $objWriter->writeAttribute('lIns', CommonDrawing::pixelsToEmu($shape->getInsetLeft()));
1139 24
            $objWriter->writeAttribute('rIns', CommonDrawing::pixelsToEmu($shape->getInsetRight()));
1140 24
            $objWriter->writeAttribute('tIns', CommonDrawing::pixelsToEmu($shape->getInsetTop()));
1141 24
1142
            if ($shape->getColumns() <> 1) {
1143 24
                $objWriter->writeAttribute('numCol', $shape->getColumns());
1144
            }
1145
1146
            // a:spAutoFit
1147
            $objWriter->startElement('a:' . $shape->getAutoFit());
1148 24
            if ($shape->getAutoFit() == RichText::AUTOFIT_NORMAL) {
1149 24
                if (!is_null($shape->getFontScale())) {
1150 1
                    $objWriter->writeAttribute('fontScale', (int)($shape->getFontScale() * 1000));
1151 1
                }
1152 1
                if (!is_null($shape->getLineSpaceReduction())) {
1153 1
                    $objWriter->writeAttribute('lnSpcReduction', (int)($shape->getLineSpaceReduction() * 1000));
1154 1
                }
1155 1
            }
1156 1
1157
            $objWriter->endElement();
1158 24
        }
1159 24
        $objWriter->endElement();
1160 24
1161
        // a:lstStyle
1162
        $objWriter->startElement('a:lstStyle');
1163 24
        $objWriter->endElement();
1164 24
1165
        // Write paragraphs
1166
        $this->writeParagraphs($objWriter, $shape->getParagraphs(), $shape->isPlaceholder());
1167 24
1168
        $objWriter->endElement();
1169 24
1170
        $objWriter->endElement();
1171 24
    }
1172 24
1173
    /**
1174
     * Write paragraphs
1175
     *
1176
     * @param  \PhpOffice\Common\XMLWriter           $objWriter  XML Writer
1177
     * @param  \PhpOffice\PhpPresentation\Shape\RichText\Paragraph[] $paragraphs
1178
     * @param  bool $bIsPlaceholder
1179
     * @throws \Exception
1180
     */
1181
    protected function writeParagraphs(XMLWriter $objWriter, $paragraphs, $bIsPlaceholder = false)
1182 10
    {
1183
        // Loop trough paragraphs
1184
        foreach ($paragraphs as $paragraph) {
1185 10
            // a:p
1186
            $objWriter->startElement('a:p');
1187
1188 10
            // a:pPr
1189
            if (!$bIsPlaceholder) {
1190
                $objWriter->startElement('a:pPr');
1191 10
                $objWriter->writeAttribute('algn', $paragraph->getAlignment()->getHorizontal());
1192 10
                $objWriter->writeAttribute('fontAlgn', $paragraph->getAlignment()->getVertical());
1193 10
                $objWriter->writeAttribute('marL', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginLeft()));
1194 10
                $objWriter->writeAttribute('marR', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginRight()));
1195
                $objWriter->writeAttribute('indent', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getIndent()));
1196 10
                $objWriter->writeAttribute('lvl', $paragraph->getAlignment()->getLevel());
1197
1198
                $objWriter->startElement('a:lnSpc');
1199 10
                $objWriter->startElement('a:spcPct');
1200
                $objWriter->writeAttribute('val', $paragraph->getLineSpacing() * 1000);
1201
                $objWriter->endElement();
1202 10
                $objWriter->endElement();
1203 10
1204 10
                // Bullet type specified?
1205
                if ($paragraph->getBulletStyle()->getBulletType() != Bullet::TYPE_NONE) {
1206 10
                    // Color
1207
                    // a:buClr must be before a:buFont (else PowerPoint crashes at launch)
1208
                    if ($paragraph->getBulletStyle()->getBulletColor() instanceof Color) {
1209 10
                        $objWriter->startElement('a:buClr');
1210 10
                        $this->writeColor($objWriter, $paragraph->getBulletStyle()->getBulletColor());
1211
                        $objWriter->endElement();
1212
                    }
1213
1214
                    // a:buFont
1215 10
                    $objWriter->startElement('a:buFont');
1216
                    $objWriter->writeAttribute('typeface', $paragraph->getBulletStyle()->getBulletFont());
1217 10
                    $objWriter->endElement();
1218
1219
                    if ($paragraph->getBulletStyle()->getBulletType() == Bullet::TYPE_BULLET) {
1220 10
                        // a:buChar
1221
                        $objWriter->startElement('a:buChar');
1222
                        $objWriter->writeAttribute('char', $paragraph->getBulletStyle()->getBulletChar());
1223 10
                        $objWriter->endElement();
1224 10
                    } elseif ($paragraph->getBulletStyle()->getBulletType() == Bullet::TYPE_NUMERIC) {
1225 10
                        // a:buAutoNum
1226 10
                        $objWriter->startElement('a:buAutoNum');
1227
                        $objWriter->writeAttribute('type', $paragraph->getBulletStyle()->getBulletNumericStyle());
1228
                        if ($paragraph->getBulletStyle()->getBulletNumericStartAt() != 1) {
1229 10
                            $objWriter->writeAttribute('startAt', $paragraph->getBulletStyle()->getBulletNumericStartAt());
1230 10
                        }
1231 10
                        $objWriter->endElement();
1232 10
                    }
1233
                }
1234 10
1235
                $objWriter->endElement();
1236
            }
1237 10
1238
            // Loop trough rich text elements
1239
            $elements = $paragraph->getRichTextElements();
1240 10
            foreach ($elements as $element) {
1241 10
                if ($element instanceof BreakElement) {
1242
                    // a:br
1243
                    $objWriter->writeElement('a:br', null);
1244 10
                } elseif ($element instanceof Run || $element instanceof TextElement) {
1245
                    // a:r
1246
                    $objWriter->startElement('a:r');
1247 10
1248 10
                    // a:rPr
1249 10
                    if ($element instanceof Run && !$bIsPlaceholder) {
1250
                        // a:rPr
1251 10
                        $objWriter->startElement('a:rPr');
1252
1253
                        // Lang
1254 10
                        $objWriter->writeAttribute('lang', ($element->getLanguage() ? $element->getLanguage() : 'en-US'));
1255
1256
                        $objWriter->writeAttributeIf($element->getFont()->isBold(), 'b', '1');
1257 10
                        $objWriter->writeAttributeIf($element->getFont()->isItalic(), 'i', '1');
1258 10
                        $objWriter->writeAttributeIf($element->getFont()->isStrikethrough(), 'strike', 'sngStrike');
1259
1260 10
                        // Size
1261
                        $objWriter->writeAttribute('sz', ($element->getFont()->getSize() * 100));
1262
1263 10
                        // Character spacing
1264 10
                        $objWriter->writeAttribute('spc', $element->getFont()->getCharacterSpacing());
1265 10
1266 10
                        // Underline
1267 10
                        $objWriter->writeAttribute('u', $element->getFont()->getUnderline());
1268 10
1269
                        // Superscript / subscript
1270 10
                        $objWriter->writeAttributeIf($element->getFont()->isSuperScript(), 'baseline', '30000');
1271 10
                        $objWriter->writeAttributeIf($element->getFont()->isSubScript(), 'baseline', '-25000');
1272 10
1273
                        // Color - a:solidFill
1274 10
                        $objWriter->startElement('a:solidFill');
1275
                        $this->writeColor($objWriter, $element->getFont()->getColor());
1276
                        $objWriter->endElement();
1277 10
1278 10
                        // Font - a:latin
1279
                        $objWriter->startElement('a:latin');
1280
                        $objWriter->writeAttribute('typeface', $element->getFont()->getName());
1281 10
                        $objWriter->endElement();
1282
1283
                        // a:hlinkClick
1284 10
                        $this->writeHyperlink($objWriter, $element);
1285 10
1286
                        $objWriter->endElement();
1287 10
                    }
1288 10
1289
                    // t
1290
                    $objWriter->startElement('a:t');
1291 10
                    $objWriter->writeCData(Text::controlCharacterPHP2OOXML($element->getText()));
1292 10
                    $objWriter->endElement();
1293
1294 10
                    $objWriter->endElement();
1295
                }
1296
            }
1297 10
1298
            $objWriter->endElement();
1299
        }
1300 10
    }
1301 10
1302 10
    /**
1303 2
     * Write Line Shape
1304 2
     *
1305
     * @param  \PhpOffice\Common\XMLWriter $objWriter XML Writer
1306
     * @param \PhpOffice\PhpPresentation\Shape\Line $shape
1307 10
     * @param  int $shapeId
1308
     */
1309 10
    protected function writeShapeLine(XMLWriter $objWriter, Line $shape, $shapeId)
1310 1
    {
1311 1
        // p:sp
1312 10
        $objWriter->startElement('p:cxnSp');
1313 1
1314 1
        // p:nvSpPr
1315 1
        $objWriter->startElement('p:nvCxnSpPr');
1316
1317
        // p:cNvPr
1318 10
        $objWriter->startElement('p:cNvPr');
1319 1
        $objWriter->writeAttribute('id', $shapeId);
1320 1
        $objWriter->writeAttribute('name', '');
1321 10
1322 1
        $objWriter->endElement();
1323 1
1324 1
        // p:cNvCxnSpPr
1325
        $objWriter->writeElement('p:cNvCxnSpPr', null);
1326
1327 10
        // p:nvPr
1328
        $objWriter->startElement('p:nvPr');
1329
        if ($shape->isPlaceholder()) {
1330 10
            $objWriter->startElement('p:ph');
1331 10
            $objWriter->writeAttribute('type', $shape->getPlaceholder()->getType());
1332 10
            $objWriter->endElement();
1333
        }
1334
        $objWriter->endElement();
1335 10
1336
        $objWriter->endElement();
1337 10
1338
        // p:spPr
1339
        $objWriter->startElement('p:spPr');
1340 10
1341
        // a:xfrm
1342
        $objWriter->startElement('a:xfrm');
1343 10
1344
        if ($shape->getWidth() >= 0 && $shape->getHeight() >= 0) {
1345 10
            // a:off
1346
            $objWriter->startElement('a:off');
1347
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1348 10
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1349
            $objWriter->endElement();
1350 10
1351 10
            // a:ext
1352 10
            $objWriter->startElement('a:ext');
1353 1
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1354 1
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1355
            $objWriter->endElement();
1356
        } elseif ($shape->getWidth() < 0 && $shape->getHeight() < 0) {
1357 10
            // a:off
1358 10
            $objWriter->startElement('a:off');
1359 10
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX() + $shape->getWidth()));
1360 10
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY() + $shape->getHeight()));
1361 10
            $objWriter->endElement();
1362
1363
            // a:ext
1364 10
            $objWriter->startElement('a:ext');
1365 10
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu(-$shape->getWidth()));
1366 10
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu(-$shape->getHeight()));
1367 10
            $objWriter->endElement();
1368 10
        } elseif ($shape->getHeight() < 0) {
1369 10
            $objWriter->writeAttribute('flipV', 1);
1370
1371
            // a:off
1372 10
            $objWriter->startElement('a:off');
1373 1
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1374 1
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY() + $shape->getHeight()));
1375 10
            $objWriter->endElement();
1376 1
1377 1
            // a:ext
1378
            $objWriter->startElement('a:ext');
1379
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1380 10
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu(-$shape->getHeight()));
1381 10
            $objWriter->endElement();
1382 10
        } elseif ($shape->getWidth() < 0) {
1383 10
            $objWriter->writeAttribute('flipV', 1);
1384 10
1385 10
            // a:off
1386
            $objWriter->startElement('a:off');
1387
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX() + $shape->getWidth()));
1388 10
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1389
            $objWriter->endElement();
1390 10
1391
            // a:ext
1392 10
            $objWriter->startElement('a:ext');
1393 10
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu(-$shape->getWidth()));
1394
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1395 10
            $objWriter->endElement();
1396 10
        }
1397
1398 10
        $objWriter->endElement();
1399
1400 10
        // a:prstGeom
1401
        $objWriter->startElement('a:prstGeom');
1402 10
        $objWriter->writeAttribute('prst', 'line');
1403
        $objWriter->endElement();
1404 10
1405 10
        if ($shape->getBorder()->getLineStyle() != Border::LINE_NONE) {
1406
            $this->writeBorder($objWriter, $shape->getBorder(), '');
1407
        }
1408
1409
        $objWriter->endElement();
1410
1411
        $objWriter->endElement();
1412
    }
1413
1414
    /**
1415 35
     * Write hyperlink
1416
     *
1417
     * @param \PhpOffice\Common\XMLWriter                               $objWriter XML Writer
1418 35
     * @param \PhpOffice\PhpPresentation\AbstractShape|\PhpOffice\PhpPresentation\Shape\RichText\TextElement $shape
1419
     */
1420 35
    protected function writeHyperlink(XMLWriter $objWriter, $shape)
1421
    {
1422
        if (!$shape->hasHyperlink()) {
1423 35
            return;
1424 35
        }
1425 35
        // a:hlinkClick
1426 35
        $objWriter->startElement('a:hlinkClick');
1427 35
        $objWriter->writeAttribute('r:id', $shape->getHyperlink()->relationId);
1428 35
        $objWriter->writeAttribute('tooltip', $shape->getHyperlink()->getTooltip());
1429 35
        if ($shape->getHyperlink()->isInternal()) {
1430 35
            $objWriter->writeAttribute('action', $shape->getHyperlink()->getUrl());
1431
        }
1432 35
        $objWriter->endElement();
1433 35
    }
1434 35
1435 35
    /**
1436 35
     * Write Note Slide
1437
     * @param Note $pNote
1438
     * @throws \Exception
1439 35
     * @return  string
1440
     */
1441
    protected function writeNote(Note $pNote)
1442 2
    {
1443 2
        // Create XML writer
1444 2
        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
1445 2
1446 2
        // XML header
1447
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
1448
1449 2
        // p:notes
1450 2
        $objWriter->startElement('p:notes');
1451 2
        $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
1452
        $objWriter->writeAttribute('xmlns:p', 'http://schemas.openxmlformats.org/presentationml/2006/main');
1453 2
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1454
1455 1
        // p:notes/p:cSld
1456 1
        $objWriter->startElement('p:cSld');
1457 1
1458 2
        // p:notes/p:cSld/p:spTree
1459
        $objWriter->startElement('p:spTree');
1460 1
1461 1
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr
1462 1
        $objWriter->startElement('p:nvGrpSpPr');
1463 1
1464 1
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr/p:cNvPr
1465 1
        $objWriter->startElement('p:cNvPr');
1466 1
        $objWriter->writeAttribute('id', '1');
1467 2
        $objWriter->writeAttribute('name', '');
1468
        $objWriter->endElement();
1469 35
1470 35
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr/p:cNvGrpSpPr
1471
        $objWriter->writeElement('p:cNvGrpSpPr', null);
1472
1473 35
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr/p:nvPr
1474 35
        $objWriter->writeElement('p:nvPr', null);
1475 30
1476
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr
1477 1
        $objWriter->endElement();
1478 30
1479
        // p:notes/p:cSld/p:spTree/p:grpSpPr
1480 29
        $objWriter->startElement('p:grpSpPr');
1481
1482
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm
1483 29
        $objWriter->startElement('a:xfrm');
1484
1485 29
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:off
1486
        $objWriter->startElement('a:off');
1487
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pNote->getOffsetX()));
1488 29
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pNote->getOffsetY()));
1489
        $objWriter->endElement(); // a:off
1490 29
1491 29
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:ext
1492 29
        $objWriter->startElement('a:ext');
1493
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pNote->getExtentX()));
1494
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pNote->getExtentY()));
1495 29
        $objWriter->endElement(); // a:ext
1496
1497
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:chOff
1498 29
        $objWriter->startElement('a:chOff');
1499
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pNote->getOffsetX()));
1500
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pNote->getOffsetY()));
1501 29
        $objWriter->endElement(); // a:chOff
1502
1503
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:chExt
1504 29
        $objWriter->startElement('a:chExt');
1505 29
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pNote->getExtentX()));
1506
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pNote->getExtentY()));
1507
        $objWriter->endElement(); // a:chExt
1508 29
1509 29
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm
1510 29
        $objWriter->endElement();
1511
1512
        // p:notes/p:cSld/p:spTree/p:grpSpPr
1513 29
        $objWriter->endElement();
1514 29
1515 29
        // p:notes/p:cSld/p:spTree/p:sp[1]
1516
        $objWriter->startElement('p:sp');
1517
1518 29
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr
1519
        $objWriter->startElement('p:nvSpPr');
1520 29
1521 29
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvPr
1522
        $objWriter->startElement('p:cNvPr');
1523
        $objWriter->writeAttribute('id', '2');
1524 29
        $objWriter->writeAttribute('name', 'Slide Image Placeholder 1');
1525 29
        $objWriter->endElement();
1526 29
1527
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvSpPr
1528 29
        $objWriter->startElement('p:cNvSpPr');
1529 29
1530 35
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvSpPr/a:spLocks
1531
        $objWriter->startElement('a:spLocks');
1532 35
        $objWriter->writeAttribute('noGrp', '1');
1533 35
        $objWriter->writeAttribute('noRot', '1');
1534 35
        $objWriter->writeAttribute('noChangeAspect', '1');
1535
        $objWriter->endElement();
1536
1537
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvSpPr
1538
        $objWriter->endElement();
1539
1540
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:nvPr
1541
        $objWriter->startElement('p:nvPr');
1542
1543 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:nvPr/p:ph
1544
        $objWriter->startElement('p:ph');
1545
        $objWriter->writeAttribute('type', 'sldImg');
1546 1
        $objWriter->endElement();
1547
1548
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:nvPr
1549 1
        $objWriter->endElement();
1550
1551
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr
1552 1
        $objWriter->endElement();
1553 1
1554 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr
1555
        $objWriter->startElement('p:spPr');
1556 1
1557
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm
1558
        $objWriter->startElement('a:xfrm');
1559 1
1560
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm/a:off
1561
        $objWriter->startElement('a:off');
1562 1
        $objWriter->writeAttribute('x', 0);
1563 1
        $objWriter->writeAttribute('y', 0);
1564
        $objWriter->endElement();
1565
1566
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm/a:ext
1567
        $objWriter->startElement('a:ext');
1568 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu(round($pNote->getExtentX() / 2)));
1569
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu(round($pNote->getExtentY() / 2)));
1570 1
        $objWriter->endElement();
1571
1572
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm
1573 1
        $objWriter->endElement();
1574
1575
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:prstGeom
1576 1
        $objWriter->startElement('a:prstGeom');
1577
        $objWriter->writeAttribute('prst', 'rect');
1578 1
1579
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:prstGeom/a:avLst
1580 1
        $objWriter->writeElement('a:avLst', null);
1581 1
1582 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:prstGeom
1583 1
        $objWriter->endElement();
1584
1585
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:noFill
1586 1
        $objWriter->writeElement('a:noFill', null);
1587 1
1588 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln
1589 1
        $objWriter->startElement('a:ln');
1590 1
        $objWriter->writeAttribute('w', '12700');
1591
1592 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:solidFill
1593 1
        $objWriter->startElement('a:solidFill');
1594 1
1595 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:solidFill/a:prstClr
1596
        $objWriter->startElement('a:prstClr');
1597
        $objWriter->writeAttribute('val', 'black');
1598 1
        $objWriter->endElement();
1599 1
1600 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:solidFill
1601 1
        $objWriter->endElement();
1602 1
1603 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln
1604
        $objWriter->endElement();
1605
1606 1
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr
1607 1
        $objWriter->endElement();
1608 1
1609 1
        // p:notes/p:cSld/p:spTree/p:sp[1]
1610
        $objWriter->endElement();
1611
1612 1
        // p:notes/p:cSld/p:spTree/p:sp[2]
1613 1
        $objWriter->startElement('p:sp');
1614 1
1615 1
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr
1616 1
        $objWriter->startElement('p:nvSpPr');
1617 1
1618
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvPr
1619
        $objWriter->startElement('p:cNvPr');
1620 1
        $objWriter->writeAttribute('id', '3');
1621 1
        $objWriter->writeAttribute('name', 'Notes Placeholder');
1622 1
        $objWriter->endElement();
1623 1
1624
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvSpPr
1625
        $objWriter->startElement('p:cNvSpPr');
1626 1
1627 1
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvSpPr/a:spLocks
1628 1
        $objWriter->startElement('a:spLocks');
1629 1
        $objWriter->writeAttribute('noGrp', '1');
1630 1
        $objWriter->endElement();
1631
1632 1
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvSpPr
1633
        $objWriter->endElement();
1634
1635 1
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:nvPr
1636 1
        $objWriter->startElement('p:nvPr');
1637 1
1638
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:nvPr/p:ph
1639 1
        $objWriter->startElement('p:ph');
1640 1
        $objWriter->writeAttribute('type', 'body');
1641 1
        $objWriter->writeAttribute('idx', '1');
1642
        $objWriter->endElement();
1643 1
1644
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:nvPr
1645 1
        $objWriter->endElement();
1646 1
1647
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr
1648
        $objWriter->endElement();
1649
1650
        // START notes print below rectangle section
1651
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr
1652
        $objWriter->startElement('p:spPr');
1653
1654 31
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm
1655
        $objWriter->startElement('a:xfrm');
1656 31
1657 26
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm/a:off
1658
        $objWriter->startElement('a:off');
1659
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pNote->getOffsetX()));
1660 5
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu(round($pNote->getExtentY() / 2) + $pNote->getOffsetY()));
1661 5
        $objWriter->endElement();
1662 5
1663 5
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm/a:ext
1664 1
        $objWriter->startElement('a:ext');
1665 1
        $objWriter->writeAttribute('cx', '5486400');
1666 5
        $objWriter->writeAttribute('cy', '3600450');
1667 5
        $objWriter->endElement();
1668
1669
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm
1670
        $objWriter->endElement();
1671
1672
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:prstGeom
1673
        $objWriter->startElement('a:prstGeom');
1674
        $objWriter->writeAttribute('prst', 'rect');
1675 1
1676
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:prstGeom/a:avLst
1677
        $objWriter->writeElement('a:avLst', null);
1678 1
1679
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:prstGeom
1680
        $objWriter->endElement();
1681 1
1682
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr
1683
        $objWriter->endElement();
1684 1
1685 1
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody
1686 1
        $objWriter->startElement('p:txBody');
1687 1
1688
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody/a:bodyPr
1689
        $objWriter->writeElement('a:bodyPr', null);
1690 1
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody/a:lstStyle
1691
        $objWriter->writeElement('a:lstStyle', null);
1692
1693 1
        // Loop shapes
1694
        $shapes  = $pNote->getShapeCollection();
1695
        foreach ($shapes as $shape) {
1696 1
            // Check type
1697
            if ($shape instanceof RichText) {
1698
                $paragraphs = $shape->getParagraphs();
1699 1
                $this->writeParagraphs($objWriter, $paragraphs);
1700 1
            }
1701 1
        }
1702 1
1703
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody
1704
        $objWriter->endElement();
1705 1
1706
        // p:notes/p:cSld/p:spTree/p:sp[2]
1707
        $objWriter->endElement();
1708 1
1709
        // p:notes/p:cSld/p:spTree
1710
        $objWriter->endElement();
1711 1
1712
        // p:notes/p:cSld
1713
        $objWriter->endElement();
1714 1
1715
        // p:notes
1716
        $objWriter->endElement();
1717 1
1718
        // Return
1719
        return $objWriter->getData();
1720 1
    }
1721
}
1722