Completed
Pull Request — develop (#230)
by Franck
07:45
created

PptSlides   F

Complexity

Total Complexity 218

Size/Duplication

Total Lines 2208
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 31

Test Coverage

Coverage 91.62%

Importance

Changes 18
Bugs 1 Features 4
Metric Value
wmc 218
c 18
b 1
f 4
lcom 1
cbo 31
dl 0
loc 2208
ccs 1213
cts 1324
cp 0.9162
rs 0.5217

15 Methods

Rating   Name   Duplication   Size   Complexity  
A render() 0 20 4
A writeShapeChart() 0 61 1
D writeSlideRelationships() 0 285 60
C writeSlide() 0 166 11
D writeSlideAnimations() 0 243 9
C writeShapeGroup() 0 80 8
B writeShapeDrawing() 0 113 3
F writeShapeText() 0 137 15
F writeShapeTable() 0 211 18
D writeParagraphs() 0 115 20
C writeShapeLine() 0 98 8
B writeShadow() 0 27 3
A writeHyperlink() 0 11 2
B writeNote() 0 280 3
D writeSlideTransition() 0 247 53

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\AbstractDrawing;
9
use PhpOffice\PhpPresentation\Shape\Chart as ShapeChart;
10
use PhpOffice\PhpPresentation\Shape\Comment;
11
use PhpOffice\PhpPresentation\Shape\Drawing as ShapeDrawing;
12
use PhpOffice\PhpPresentation\Shape\Group;
13
use PhpOffice\PhpPresentation\Shape\Line;
14
use PhpOffice\PhpPresentation\Shape\Media;
15
use PhpOffice\PhpPresentation\Shape\RichText;
16
use PhpOffice\PhpPresentation\Shape\RichText\BreakElement;
17
use PhpOffice\PhpPresentation\Shape\RichText\Run;
18
use PhpOffice\PhpPresentation\Shape\RichText\TextElement;
19
use PhpOffice\PhpPresentation\Shape\Table as ShapeTable;
20
use PhpOffice\PhpPresentation\Slide;
21
use PhpOffice\PhpPresentation\Slide\Background\Image;
22
use PhpOffice\PhpPresentation\Slide\Note;
23
use PhpOffice\PhpPresentation\Slide\Transition;
24
use PhpOffice\PhpPresentation\Style\Alignment;
25
use PhpOffice\PhpPresentation\Style\Bullet;
26
use PhpOffice\PhpPresentation\Style\Border;
27
use PhpOffice\PhpPresentation\Style\Shadow;
28
use PhpOffice\PhpPresentation\Writer\PowerPoint2007\LayoutPack\PackDefault;
29
30
class PptSlides extends AbstractDecoratorWriter
31
{
32
    /**
33
     * Add slides (drawings, ...) and slide relationships (drawings, ...)
34
     * @return \PhpOffice\Common\Adapter\Zip\ZipInterface
35
     */
36 95
    public function render()
37
    {
38 95
        foreach ($this->oPresentation->getAllSlides() as $idx => $oSlide) {
39 95
            $this->oZip->addFromString('ppt/slides/_rels/slide' . ($idx + 1) . '.xml.rels', $this->writeSlideRelationships($oSlide));
40 95
            $this->oZip->addFromString('ppt/slides/slide' . ($idx + 1) . '.xml', $this->writeSlide($oSlide));
41
42
            // Add note slide
43 95
            if ($oSlide->getNote()->getShapeCollection()->count() > 0) {
44 1
                $this->oZip->addFromString('ppt/notesSlides/notesSlide' . ($idx + 1) . '.xml', $this->writeNote($oSlide->getNote()));
0 ignored issues
show
Bug introduced by
It seems like $oSlide->getNote() can be null; however, writeNote() 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...
45 1
            }
46
47
            // Add background image slide
48 95
            $oBkgImage = $oSlide->getBackground();
49 95
            if ($oBkgImage instanceof Image) {
50
                $this->oZip->addFromString('ppt/media/'.$oBkgImage->getIndexedFilename($idx), file_get_contents($oBkgImage->getPath()));
51
            }
52 95
        }
53
54 95
        return $this->oZip;
55
    }
56
57
    /**
58
     * Write slide relationships to XML format
59
     *
60
     * @param  \PhpOffice\PhpPresentation\Slide $pSlide
61
     * @return string              XML Output
62
     * @throws \Exception
63
     */
64 95
    protected function writeSlideRelationships(Slide $pSlide)
65
    {
66
        //@todo Group all getShapeCollection()->getIterator
67
68
        // Create XML writer
69 95
        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
70
71
        // XML header
72 95
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
73
74
        // Relationships
75 95
        $objWriter->startElement('Relationships');
76 95
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
77
78
        // Starting relation id
79 95
        $relId = 1;
80 95
        $idxSlide = $pSlide->getParent()->getIndex($pSlide);
81
82
        // Write slideLayout relationship
83
        // $oLayoutPack  = new PackDefault();
84
        // $layoutId = $oLayoutPack->findlayoutId($pSlide->getSlideLayout(), $pSlide->getSlideMasterId());
85 95
        $layoutId = 1;
86
87 95
        $this->writeRelationship($objWriter, $relId++, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout', '../slideLayouts/slideLayout' . $layoutId . '.xml');
88
89
        // Write drawing relationships?
90 95
        if ($pSlide->getShapeCollection()->count() > 0) {
91
            // Loop trough images and write relationships
92 71
            $iterator = $pSlide->getShapeCollection()->getIterator();
93 71
            while ($iterator->valid()) {
94 71
                if ($iterator->current() instanceof Media) {
95
                    // Write relationship for image drawing
96 1
                    $this->writeRelationship($objWriter, $relId, 'http://schemas.microsoft.com/office/2007/relationships/media', '../media/' . $iterator->current()->getIndexedFilename());
97 1
                    $iterator->current()->relationId = 'rId' . $relId;
98 1
                    ++$relId;
99 71
                } elseif ($iterator->current() instanceof ShapeDrawing\AbstractDrawingAdapter) {
100
                    // Write relationship for image drawing
101 7
                    $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', '../media/' . $iterator->current()->getIndexedFilename());
102 7
                    $iterator->current()->relationId = 'rId' . $relId;
103 7
                    ++$relId;
104 70
                } elseif ($iterator->current() instanceof ShapeChart) {
105
                    // Write relationship for chart drawing
106 24
                    $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', '../charts/' . $iterator->current()->getIndexedFilename());
107
108 24
                    $iterator->current()->relationId = 'rId' . $relId;
109
110 24
                    ++$relId;
111 63
                } elseif ($iterator->current() instanceof Group) {
112 1
                    $iterator2 = $iterator->current()->getShapeCollection()->getIterator();
113 1
                    while ($iterator2->valid()) {
114 1
                        if ($iterator->current() instanceof Media) {
115
                            // Write relationship for image drawing
116
                            $this->writeRelationship($objWriter, $relId, 'http://schemas.microsoft.com/office/2007/relationships/media', '../media/' . $iterator->current()->getIndexedFilename());
117
                            $iterator->current()->relationId = 'rId' . $relId;
118
                            ++$relId;
119 1
                        } elseif ($iterator->current() instanceof ShapeDrawing\AbstractDrawingAdapter) {
120
                            // Write relationship for image drawing
121
                            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', '../media/' . $iterator2->current()->getIndexedFilename());
122
                            $iterator2->current()->relationId = 'rId' . $relId;
123
124
                            ++$relId;
125 1
                        } elseif ($iterator2->current() instanceof ShapeChart) {
126
                            // Write relationship for chart drawing
127
                            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', '../charts/' . $iterator2->current()->getIndexedFilename());
128
                            $iterator2->current()->relationId = 'rId' . $relId;
129
130
                            ++$relId;
131
                        }
132 1
                        $iterator2->next();
133 1
                    }
134 1
                }
135
136 71
                $iterator->next();
137 71
            }
138 71
        }
139
140
        // Write background relationships?
141 95
        $oBackground = $pSlide->getBackground();
142 95
        if ($oBackground instanceof Image) {
143
            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', '../media/' . $oBackground->getIndexedFilename($idxSlide));
144
            $oBackground->relationId = 'rId' . $relId;
145
            ++$relId;
146
        }
147
148
        // Write hyperlink relationships?
149 95
        if ($pSlide->getShapeCollection()->count() > 0) {
150
            // Loop trough hyperlinks and write relationships
151 71
            $iterator = $pSlide->getShapeCollection()->getIterator();
152 71
            while ($iterator->valid()) {
153
                // Hyperlink on shape
154 71
                if ($iterator->current()->hasHyperlink()) {
155
                    // Write relationship for hyperlink
156 2
                    $hyperlink               = $iterator->current()->getHyperlink();
157 2
                    $hyperlink->relationId = 'rId' . $relId;
158
159 2
                    if (!$hyperlink->isInternal()) {
160 2
                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
161 2
                    } else {
162
                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
163
                    }
164
165 2
                    ++$relId;
166 2
                }
167
168
                // Hyperlink on rich text run
169 71
                if ($iterator->current() instanceof RichText) {
170 22
                    foreach ($iterator->current()->getParagraphs() as $paragraph) {
171 22
                        foreach ($paragraph->getRichTextElements() as $element) {
172 17
                            if ($element instanceof Run || $element instanceof RunTextElement) {
0 ignored issues
show
Bug introduced by
The class PhpOffice\PhpPresentatio...oint2007\RunTextElement does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
173 16
                                if ($element->hasHyperlink()) {
174
                                    // Write relationship for hyperlink
175 2
                                    $hyperlink               = $element->getHyperlink();
176 2
                                    $hyperlink->relationId = 'rId' . $relId;
177
178 2
                                    if (!$hyperlink->isInternal()) {
179 1
                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
180 1
                                    } else {
181 1
                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
182
                                    }
183
184 2
                                    ++$relId;
185 2
                                }
186 16
                            }
187 22
                        }
188 22
                    }
189 22
                }
190
191
                // Hyperlink in table
192 71
                if ($iterator->current() instanceof ShapeTable) {
193
                    // Rows
194 9
                    $countRows = count($iterator->current()->getRows());
195 9
                    for ($row = 0; $row < $countRows; $row++) {
196
                        // Cells in rows
197 9
                        $countCells = count($iterator->current()->getRow($row)->getCells());
198 9
                        for ($cell = 0; $cell < $countCells; $cell++) {
199 9
                            $currentCell = $iterator->current()->getRow($row)->getCell($cell);
200
                            // Paragraphs in cell
201 9
                            foreach ($currentCell->getParagraphs() as $paragraph) {
202
                                // RichText in paragraph
203 9
                                foreach ($paragraph->getRichTextElements() as $element) {
204
                                    // Run or Text in RichText
205 9
                                    if ($element instanceof Run || $element instanceof TextElement) {
206 9
                                        if ($element->hasHyperlink()) {
207
                                            // Write relationship for hyperlink
208 1
                                            $hyperlink               = $element->getHyperlink();
209 1
                                            $hyperlink->relationId = 'rId' . $relId;
210
211 1
                                            if (!$hyperlink->isInternal()) {
212 1
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
213 1
                                            } else {
214
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
215
                                            }
216
217 1
                                            ++$relId;
218 1
                                        }
219 9
                                    }
220 9
                                }
221 9
                            }
222 9
                        }
223 9
                    }
224 9
                }
225
226 71
                if ($iterator->current() instanceof Group) {
227 1
                    $iterator2 = $pSlide->getShapeCollection()->getIterator();
228 1
                    while ($iterator2->valid()) {
229
                        // Hyperlink on shape
230 1
                        if ($iterator2->current()->hasHyperlink()) {
231
                            // Write relationship for hyperlink
232
                            $hyperlink             = $iterator2->current()->getHyperlink();
233
                            $hyperlink->relationId = 'rId' . $relId;
234
235
                            if (!$hyperlink->isInternal()) {
236
                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
237
                            } else {
238
                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
239
                            }
240
241
                            ++$relId;
242
                        }
243
244
                        // Hyperlink on rich text run
245 1
                        if ($iterator2->current() instanceof RichText) {
246
                            foreach ($iterator2->current()->getParagraphs() as $paragraph) {
247
                                foreach ($paragraph->getRichTextElements() as $element) {
248
                                    if ($element instanceof Run || $element instanceof TextElement) {
249
                                        if ($element->hasHyperlink()) {
250
                                            // Write relationship for hyperlink
251
                                            $hyperlink              = $element->getHyperlink();
252
                                            $hyperlink->relationId = 'rId' . $relId;
253
254
                                            if (!$hyperlink->isInternal()) {
255
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
256
                                            } else {
257
                                                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
258
                                            }
259
260
                                            ++$relId;
261
                                        }
262
                                    }
263
                                }
264
                            }
265
                        }
266
267
                        // Hyperlink in table
268 1
                        if ($iterator2->current() instanceof ShapeTable) {
269
                            // Rows
270
                            $countRows = count($iterator2->current()->getRows());
271
                            for ($row = 0; $row < $countRows; $row++) {
272
                                // Cells in rows
273
                                $countCells = count($iterator2->current()->getRow($row)->getCells());
274
                                for ($cell = 0; $cell < $countCells; $cell++) {
275
                                    $currentCell = $iterator2->current()->getRow($row)->getCell($cell);
276
                                    // Paragraphs in cell
277
                                    foreach ($currentCell->getParagraphs() as $paragraph) {
278
                                        // RichText in paragraph
279
                                        foreach ($paragraph->getRichTextElements() as $element) {
280
                                            // Run or Text in RichText
281
                                            if ($element instanceof Run || $element instanceof TextElement) {
282
                                                if ($element->hasHyperlink()) {
283
                                                    // Write relationship for hyperlink
284
                                                    $hyperlink               = $element->getHyperlink();
285
                                                    $hyperlink->relationId = 'rId' . $relId;
286
287
                                                    if (!$hyperlink->isInternal()) {
288
                                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', $hyperlink->getUrl(), 'External');
289
                                                    } else {
290
                                                        $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide', 'slide' . $hyperlink->getSlideNumber() . '.xml');
291
                                                    }
292
293
                                                    ++$relId;
294
                                                }
295
                                            }
296
                                        }
297
                                    }
298
                                }
299
                            }
300
                        }
301
302 1
                        $iterator2->next();
303 1
                    }
304 1
                }
305
306 71
                $iterator->next();
307 71
            }
308 71
        }
309
310
        // Write comment relationships
311 95
        if ($pSlide->getShapeCollection()->count() > 0) {
312 71
            $hasSlideComment = false;
313
314
            // Loop trough images and write relationships
315 71
            $iterator = $pSlide->getShapeCollection()->getIterator();
316 71
            while ($iterator->valid()) {
317 71
                if ($iterator->current() instanceof Comment) {
318 6
                    $hasSlideComment = true;
319 6
                    break;
320 65
                } elseif ($iterator->current() instanceof Group) {
321 1
                    $iterator2 = $iterator->current()->getShapeCollection()->getIterator();
322 1
                    while ($iterator2->valid()) {
323 1
                        if ($iterator2->current() instanceof Comment) {
324 1
                            $hasSlideComment = true;
325 1
                            break 2;
326
                        }
327
                        $iterator2->next();
328
                    }
329
                }
330
331 64
                $iterator->next();
332 64
            }
333
334 71
            if ($hasSlideComment) {
335 7
                $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments', '../comments/comment'.($idxSlide + 1).'.xml');
336 7
                ++$relId;
337 7
            }
338 71
        }
339
340 95
        if ($pSlide->getNote()->getShapeCollection()->count() > 0) {
341 1
            $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide', '../notesSlides/notesSlide'.($idxSlide + 1).'.xml');
342 1
        }
343
344 95
        $objWriter->endElement();
345
346
        // Return
347 95
        return $objWriter->getData();
348
    }
349
350
    /**
351
     * Write slide to XML format
352
     *
353
     * @param  \PhpOffice\PhpPresentation\Slide $pSlide
354
     * @return string              XML Output
355
     * @throws \Exception
356
     */
357 95
    public function writeSlide(Slide $pSlide)
358
    {
359
        // Create XML writer
360 95
        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
361
362
        // XML header
363 95
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
364
365
        // p:sld
366 95
        $objWriter->startElement('p:sld');
367 95
        $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
368 95
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
369 95
        $objWriter->writeAttribute('xmlns:p', 'http://schemas.openxmlformats.org/presentationml/2006/main');
370 95
        $objWriter->writeAttributeIf(!$pSlide->isVisible(), 'show', 0);
371
372
        // p:sld/p:cSld
373 95
        $objWriter->startElement('p:cSld');
374
375
        // Background
376 95
        if ($pSlide->getBackground() instanceof Slide\AbstractBackground) {
377
            $oBackground = $pSlide->getBackground();
378
            // p:bg
379
            $objWriter->startElement('p:bg');
380
381
            // p:bgPr
382
            $objWriter->startElement('p:bgPr');
383
384
            if ($oBackground instanceof Slide\Background\Color) {
385
                // a:solidFill
386
                $objWriter->startElement('a:solidFill');
387
388
                $this->writeColor($objWriter, $oBackground->getColor());
389
390
                // > a:solidFill
391
                $objWriter->endElement();
392
            }
393
394
            if ($oBackground instanceof Slide\Background\Image) {
395
                // a:blipFill
396
                $objWriter->startElement('a:blipFill');
397
398
                // a:blip
399
                $objWriter->startElement('a:blip');
400
                $objWriter->writeAttribute('r:embed', $oBackground->relationId);
401
402
                // > a:blipFill
403
                $objWriter->endElement();
404
405
                // a:stretch
406
                $objWriter->startElement('a:stretch');
407
408
                // a:fillRect
409
                $objWriter->writeElement('a:fillRect');
410
411
                // > a:stretch
412
                $objWriter->endElement();
413
414
                // > a:blipFill
415
                $objWriter->endElement();
416
            }
417
418
            // > p:bgPr
419
            $objWriter->endElement();
420
421
            // > p:bg
422
            $objWriter->endElement();
423
        }
424
425
        // p:spTree
426 95
        $objWriter->startElement('p:spTree');
427
428
        // p:nvGrpSpPr
429 95
        $objWriter->startElement('p:nvGrpSpPr');
430
431
        // p:cNvPr
432 95
        $objWriter->startElement('p:cNvPr');
433 95
        $objWriter->writeAttribute('id', '1');
434 95
        $objWriter->writeAttribute('name', '');
435 95
        $objWriter->endElement();
436
437
        // p:cNvGrpSpPr
438 95
        $objWriter->writeElement('p:cNvGrpSpPr', null);
439
440
        // p:nvPr
441 95
        $objWriter->writeElement('p:nvPr', null);
442
443 95
        $objWriter->endElement();
444
445
        // p:grpSpPr
446 95
        $objWriter->startElement('p:grpSpPr');
447
448
        // a:xfrm
449 95
        $objWriter->startElement('a:xfrm');
450
451
        // a:off
452 95
        $objWriter->startElement('a:off');
453 95
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pSlide->getOffsetX()));
454 95
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pSlide->getOffsetY()));
455 95
        $objWriter->endElement(); // a:off
456
457
        // a:ext
458 95
        $objWriter->startElement('a:ext');
459 95
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pSlide->getExtentX()));
460 95
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pSlide->getExtentY()));
461 95
        $objWriter->endElement(); // a:ext
462
463
        // a:chOff
464 95
        $objWriter->startElement('a:chOff');
465 95
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pSlide->getOffsetX()));
466 95
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pSlide->getOffsetY()));
467 95
        $objWriter->endElement(); // a:chOff
468
469
        // a:chExt
470 95
        $objWriter->startElement('a:chExt');
471 95
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pSlide->getExtentX()));
472 95
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pSlide->getExtentY()));
473 95
        $objWriter->endElement(); // a:chExt
474
475 95
        $objWriter->endElement();
476
477 95
        $objWriter->endElement();
478
479
        // Loop shapes
480 95
        $shapeId = 0;
481 95
        $shapes  = $pSlide->getShapeCollection();
482 95
        foreach ($shapes as $shape) {
483
            // Increment $shapeId
484 71
            ++$shapeId;
485
486
            // Check type
487 71
            if ($shape instanceof RichText) {
488 22
                $this->writeShapeText($objWriter, $shape, $shapeId);
489 71
            } elseif ($shape instanceof ShapeTable) {
490 9
                $this->writeShapeTable($objWriter, $shape, $shapeId);
491 49
            } elseif ($shape instanceof Line) {
492 1
                $this->writeShapeLine($objWriter, $shape, $shapeId);
493 40
            } elseif ($shape instanceof ShapeChart) {
494 24
                $this->writeShapeChart($objWriter, $shape, $shapeId);
495 39
            } elseif ($shape instanceof ShapeDrawing\AbstractDrawingAdapter) {
496 8
                $this->writeShapeDrawing($objWriter, $shape, $shapeId);
497 15
            } elseif ($shape instanceof Group) {
498 1
                $this->writeShapeGroup($objWriter, $shape, $shapeId);
499 1
            }
500 95
        }
501
502
        // TODO
503 95
        $objWriter->endElement();
504
505 95
        $objWriter->endElement();
506
507
        // p:clrMapOvr
508 95
        $objWriter->startElement('p:clrMapOvr');
509
        // p:clrMapOvr\a:masterClrMapping
510 95
        $objWriter->writeElement('a:masterClrMapping', null);
511
        // ##p:clrMapOvr
512 95
        $objWriter->endElement();
513
514 95
        $this->writeSlideTransition($objWriter, $pSlide->getTransition());
515
516 95
        $this->writeSlideAnimations($objWriter, $pSlide);
517
518 95
        $objWriter->endElement();
519
520
        // Return
521 95
        return $objWriter->getData();
522
    }
523
524
    /**
525
     * @param XMLWriter $objWriter
526
     * @param Slide $oSlide
527
     */
528 95
    protected function writeSlideAnimations(XMLWriter $objWriter, Slide $oSlide)
529
    {
530 95
        $arrayAnimations = $oSlide->getAnimations();
531 95
        if (count($arrayAnimations) <= 0) {
532 94
            return;
533
        }
534
535
        // Variables
536 1
        $shapeId = 1;
537 1
        $idCount = 1;
538 1
        $hashToIdMap = array();
539 1
        $arrayAnimationIds = array();
540
541 1
        foreach ($oSlide->getShapeCollection() as $shape) {
542 1
            $hashToIdMap[$shape->getHashCode()] = ++$shapeId;
543 1
        }
544 1
        foreach ($arrayAnimations as $oAnimation) {
545 1
            foreach ($oAnimation->getShapeCollection() as $oShape) {
546 1
                $arrayAnimationIds[] = $hashToIdMap[$oShape->getHashCode()];
547 1
            }
548 1
        }
549
550
        // p:timing
551 1
        $objWriter->startElement('p:timing');
552
        // p:timing/p:tnLst
553 1
        $objWriter->startElement('p:tnLst');
554
        // p:timing/p:tnLst/p:par
555 1
        $objWriter->startElement('p:par');
556
        // p:timing/p:tnLst/p:par/p:cTn
557 1
        $objWriter->startElement('p:cTn');
558 1
        $objWriter->writeAttribute('id', $idCount++);
559 1
        $objWriter->writeAttribute('dur', 'indefinite');
560 1
        $objWriter->writeAttribute('restart', 'never');
561 1
        $objWriter->writeAttribute('nodeType', 'tmRoot');
562
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst
563 1
        $objWriter->startElement('p:childTnLst');
564
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq
565 1
        $objWriter->startElement('p:seq');
566 1
        $objWriter->writeAttribute('concurrent', '1');
567 1
        $objWriter->writeAttribute('nextAc', 'seek');
568
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn
569 1
        $objWriter->startElement('p:cTn');
570 1
        $objWriter->writeAttribute('id', $idCount++);
571 1
        $objWriter->writeAttribute('dur', 'indefinite');
572 1
        $objWriter->writeAttribute('nodeType', 'mainSeq');
573
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst
574 1
        $objWriter->startElement('p:childTnLst');
575
576
        // Each animation has multiple shapes
577 1
        foreach ($arrayAnimations as $oAnimation) {
578
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par
579 1
            $objWriter->startElement('p:par');
580
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn
581 1
            $objWriter->startElement('p:cTn');
582 1
            $objWriter->writeAttribute('id', $idCount++);
583 1
            $objWriter->writeAttribute('fill', 'hold');
584
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:stCondLst
585 1
            $objWriter->startElement('p:stCondLst');
586
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:stCondLst/p:cond
587 1
            $objWriter->startElement('p:cond');
588 1
            $objWriter->writeAttribute('delay', 'indefinite');
589 1
            $objWriter->endElement();
590
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn\##p:stCondLst
591 1
            $objWriter->endElement();
592
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst
593 1
            $objWriter->startElement('p:childTnLst');
594
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst/p:par
595 1
            $objWriter->startElement('p:par');
596
            // 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
597 1
            $objWriter->startElement('p:cTn');
598 1
            $objWriter->writeAttribute('id', $idCount++);
599 1
            $objWriter->writeAttribute('fill', 'hold');
600
            // 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
601 1
            $objWriter->startElement('p:stCondLst');
602
            // 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
603 1
            $objWriter->startElement('p:cond');
604 1
            $objWriter->writeAttribute('delay', '0');
605 1
            $objWriter->endElement();
606
            // 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
607 1
            $objWriter->endElement();
608
            // 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
609 1
            $objWriter->startElement('p:childTnLst');
610
611 1
            $firstAnimation = true;
612 1
            foreach ($oAnimation->getShapeCollection() as $oShape) {
613 1
                $nodeType = $firstAnimation ? 'clickEffect' : 'withEffect';
614 1
                $shapeId = $hashToIdMap[$oShape->getHashCode()];
615
616
                // p:par
617 1
                $objWriter->startElement('p:par');
618
                // p:par/p:cTn
619 1
                $objWriter->startElement('p:cTn');
620 1
                $objWriter->writeAttribute('id', $idCount++);
621 1
                $objWriter->writeAttribute('presetID', '1');
622 1
                $objWriter->writeAttribute('presetClass', 'entr');
623 1
                $objWriter->writeAttribute('fill', 'hold');
624 1
                $objWriter->writeAttribute('presetSubtype', '0');
625 1
                $objWriter->writeAttribute('grpId', '0');
626 1
                $objWriter->writeAttribute('nodeType', $nodeType);
627
                // p:par/p:cTn/p:stCondLst
628 1
                $objWriter->startElement('p:stCondLst');
629
                // p:par/p:cTn/p:stCondLst/p:cond
630 1
                $objWriter->startElement('p:cond');
631 1
                $objWriter->writeAttribute('delay', '0');
632 1
                $objWriter->endElement();
633
                // p:par/p:cTn\##p:stCondLst
634 1
                $objWriter->endElement();
635
                // p:par/p:cTn/p:childTnLst
636 1
                $objWriter->startElement('p:childTnLst');
637
                // p:par/p:cTn/p:childTnLst/p:set
638 1
                $objWriter->startElement('p:set');
639
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr
640 1
                $objWriter->startElement('p:cBhvr');
641
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn
642 1
                $objWriter->startElement('p:cTn');
643 1
                $objWriter->writeAttribute('id', $idCount++);
644 1
                $objWriter->writeAttribute('dur', '1');
645 1
                $objWriter->writeAttribute('fill', 'hold');
646
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn/p:stCondLst
647 1
                $objWriter->startElement('p:stCondLst');
648
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn/p:stCondLst/p:cond
649 1
                $objWriter->startElement('p:cond');
650 1
                $objWriter->writeAttribute('delay', '0');
651 1
                $objWriter->endElement();
652
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:cTn\##p:stCondLst
653 1
                $objWriter->endElement();
654
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr\##p:cTn
655 1
                $objWriter->endElement();
656
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:tgtEl
657 1
                $objWriter->startElement('p:tgtEl');
658
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:tgtEl/p:spTgt
659 1
                $objWriter->startElement('p:spTgt');
660 1
                $objWriter->writeAttribute('spid', $shapeId);
661 1
                $objWriter->endElement();
662
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr\##p:tgtEl
663 1
                $objWriter->endElement();
664
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:attrNameLst
665 1
                $objWriter->startElement('p:attrNameLst');
666
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr/p:attrNameLst/p:attrName
667 1
                $objWriter->writeElement('p:attrName', 'style.visibility');
668
                // p:par/p:cTn/p:childTnLst/p:set/p:cBhvr\##p:attrNameLst
669 1
                $objWriter->endElement();
670
                // p:par/p:cTn/p:childTnLst/p:set\##p:cBhvr
671 1
                $objWriter->endElement();
672
                // p:par/p:cTn/p:childTnLst/p:set/p:to
673 1
                $objWriter->startElement('p:to');
674
                // p:par/p:cTn/p:childTnLst/p:set/p:to/p:strVal
675 1
                $objWriter->startElement('p:strVal');
676 1
                $objWriter->writeAttribute('val', 'visible');
677 1
                $objWriter->endElement();
678
                // p:par/p:cTn/p:childTnLst/p:set\##p:to
679 1
                $objWriter->endElement();
680
                // p:par/p:cTn/p:childTnLst\##p:set
681 1
                $objWriter->endElement();
682
                // p:par/p:cTn\##p:childTnLst
683 1
                $objWriter->endElement();
684
                // p:par\##p:cTn
685 1
                $objWriter->endElement();
686
                // ##p:par
687 1
                $objWriter->endElement();
688
689 1
                $firstAnimation = false;
690 1
            }
691
692
            // 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
693 1
            $objWriter->endElement();
694
            // 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
695 1
            $objWriter->endElement();
696
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn/p:childTnLst\##p:par
697 1
            $objWriter->endElement();
698
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par/p:cTn\##p:childTnLst
699 1
            $objWriter->endElement();
700
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst/p:par\##p:cTn
701 1
            $objWriter->endElement();
702
            // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn/p:childTnLst\##p:par
703 1
            $objWriter->endElement();
704 1
        }
705
706
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:cTn\##p:childTnLst
707 1
        $objWriter->endElement();
708
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq\##p:cTn
709 1
        $objWriter->endElement();
710
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst
711 1
        $objWriter->startElement('p:prevCondLst');
712
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond
713 1
        $objWriter->startElement('p:cond');
714 1
        $objWriter->writeAttribute('evt', 'onPrev');
715 1
        $objWriter->writeAttribute('delay', '0');
716
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond/p:tgtEl
717 1
        $objWriter->startElement('p:tgtEl');
718
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond/p:tgtEl/p:sldTgt
719 1
        $objWriter->writeElement('p:sldTgt', null);
720
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst/p:cond\##p:tgtEl
721 1
        $objWriter->endElement();
722
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:prevCondLst\##p:cond
723 1
        $objWriter->endElement();
724
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq\##p:prevCondLst
725 1
        $objWriter->endElement();
726
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst
727 1
        $objWriter->startElement('p:nextCondLst');
728
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond
729 1
        $objWriter->startElement('p:cond');
730 1
        $objWriter->writeAttribute('evt', 'onNext');
731 1
        $objWriter->writeAttribute('delay', '0');
732
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond/p:tgtEl
733 1
        $objWriter->startElement('p:tgtEl');
734
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond/p:tgtEl/p:sldTgt
735 1
        $objWriter->writeElement('p:sldTgt', null);
736
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst/p:cond\##p:tgtEl
737 1
        $objWriter->endElement();
738
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq/p:nextCondLst\##p:cond
739 1
        $objWriter->endElement();
740
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst/p:seq\##p:nextCondLst
741 1
        $objWriter->endElement();
742
        // p:timing/p:tnLst/p:par/p:cTn/p:childTnLst\##p:seq
743 1
        $objWriter->endElement();
744
        // p:timing/p:tnLst/p:par/p:cTn\##p:childTnLst
745 1
        $objWriter->endElement();
746
        // p:timing/p:tnLst/p:par\##p:cTn
747 1
        $objWriter->endElement();
748
        // p:timing/p:tnLst\##p:par
749 1
        $objWriter->endElement();
750
        // p:timing\##p:tnLst
751 1
        $objWriter->endElement();
752
753
        // p:timing/p:bldLst
754 1
        $objWriter->startElement('p:bldLst');
755
756
        // Add in ids of all shapes in this slides animations
757 1
        foreach ($arrayAnimationIds as $id) {
758
            // p:timing/p:bldLst/p:bldP
759 1
            $objWriter->startElement('p:bldP');
760 1
            $objWriter->writeAttribute('spid', $id);
761 1
            $objWriter->writeAttribute('grpId', 0);
762 1
            $objWriter->endELement();
763 1
        }
764
765
        // p:timing\##p:bldLst
766 1
        $objWriter->endElement();
767
768
        // ##p:timing
769 1
        $objWriter->endElement();
770 1
    }
771
772
    /**
773
     * Write group
774
     *
775
     * @param \PhpOffice\Common\XMLWriter $objWriter XML Writer
776
     * @param \PhpOffice\PhpPresentation\Shape\Group $group
777
     * @param  int $shapeId
778
     */
779 1
    protected function writeShapeGroup(XMLWriter $objWriter, Group $group, &$shapeId)
780
    {
781
        // p:grpSp
782 1
        $objWriter->startElement('p:grpSp');
783
784
        // p:nvGrpSpPr
785 1
        $objWriter->startElement('p:nvGrpSpPr');
786
787
        // p:cNvPr
788 1
        $objWriter->startElement('p:cNvPr');
789 1
        $objWriter->writeAttribute('name', 'Group '.$shapeId++);
790 1
        $objWriter->writeAttribute('id', $shapeId);
791 1
        $objWriter->endElement(); // p:cNvPr
792
        // NOTE: Re: $shapeId This seems to be how PowerPoint 2010 does business.
793
794
        // p:cNvGrpSpPr
795 1
        $objWriter->writeElement('p:cNvGrpSpPr', null);
796
797
        // p:nvPr
798 1
        $objWriter->writeElement('p:nvPr', null);
799
800 1
        $objWriter->endElement(); // p:nvGrpSpPr
801
802
        // p:grpSpPr
803 1
        $objWriter->startElement('p:grpSpPr');
804
805
        // a:xfrm
806 1
        $objWriter->startElement('a:xfrm');
807
808
        // a:off
809 1
        $objWriter->startElement('a:off');
810 1
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($group->getOffsetX()));
811 1
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($group->getOffsetY()));
812 1
        $objWriter->endElement(); // a:off
813
814
        // a:ext
815 1
        $objWriter->startElement('a:ext');
816 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($group->getExtentX()));
817 1
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($group->getExtentY()));
818 1
        $objWriter->endElement(); // a:ext
819
820
        // a:chOff
821 1
        $objWriter->startElement('a:chOff');
822 1
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($group->getOffsetX()));
823 1
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($group->getOffsetY()));
824 1
        $objWriter->endElement(); // a:chOff
825
826
        // a:chExt
827 1
        $objWriter->startElement('a:chExt');
828 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($group->getExtentX()));
829 1
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($group->getExtentY()));
830 1
        $objWriter->endElement(); // a:chExt
831
832 1
        $objWriter->endElement(); // a:xfrm
833
834 1
        $objWriter->endElement(); // p:grpSpPr
835
836 1
        $shapes  = $group->getShapeCollection();
837 1
        foreach ($shapes as $shape) {
838
            // Increment $shapeId
839 1
            ++$shapeId;
840
841
            // Check type
842 1
            if ($shape instanceof RichText) {
843
                $this->writeShapeText($objWriter, $shape, $shapeId);
844 1
            } elseif ($shape instanceof ShapeTable) {
845
                $this->writeShapeTable($objWriter, $shape, $shapeId);
846 1
            } elseif ($shape instanceof Line) {
847
                $this->writeShapeLine($objWriter, $shape, $shapeId);
848 1
            } elseif ($shape instanceof ShapeChart) {
849
                $this->writeShapeChart($objWriter, $shape, $shapeId);
850 1
            } elseif ($shape instanceof ShapeDrawing\AbstractDrawingAdapter) {
851
                $this->writeShapeDrawing($objWriter, $shape, $shapeId);
852 1
            } elseif ($shape instanceof Group) {
853
                $this->writeShapeGroup($objWriter, $shape, $shapeId);
854
            }
855 1
        }
856
857 1
        $objWriter->endElement(); // p:grpSp
858 1
    }
859
860
    /**
861
     * Write chart
862
     *
863
     * @param \PhpOffice\Common\XMLWriter $objWriter XML Writer
864
     * @param \PhpOffice\PhpPresentation\Shape\Chart $shape
865
     * @param  int $shapeId
866
     */
867 24
    protected function writeShapeChart(XMLWriter $objWriter, ShapeChart $shape, $shapeId)
868
    {
869
        // p:graphicFrame
870 24
        $objWriter->startElement('p:graphicFrame');
871
872
        // p:nvGraphicFramePr
873 24
        $objWriter->startElement('p:nvGraphicFramePr');
874
875
        // p:cNvPr
876 24
        $objWriter->startElement('p:cNvPr');
877 24
        $objWriter->writeAttribute('id', $shapeId);
878 24
        $objWriter->writeAttribute('name', $shape->getName());
879 24
        $objWriter->writeAttribute('descr', $shape->getDescription());
880 24
        $objWriter->endElement();
881
882
        // p:cNvGraphicFramePr
883 24
        $objWriter->writeElement('p:cNvGraphicFramePr', null);
884
885
        // p:nvPr
886 24
        $objWriter->writeElement('p:nvPr', null);
887
888 24
        $objWriter->endElement();
889
890
        // p:xfrm
891 24
        $objWriter->startElement('p:xfrm');
892 24
        $objWriter->writeAttribute('rot', CommonDrawing::degreesToAngle($shape->getRotation()));
893
894
        // a:off
895 24
        $objWriter->startElement('a:off');
896 24
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
897 24
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
898 24
        $objWriter->endElement();
899
900
        // a:ext
901 24
        $objWriter->startElement('a:ext');
902 24
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
903 24
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
904 24
        $objWriter->endElement();
905
906 24
        $objWriter->endElement();
907
908
        // a:graphic
909 24
        $objWriter->startElement('a:graphic');
910
911
        // a:graphicData
912 24
        $objWriter->startElement('a:graphicData');
913 24
        $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
914
915
        // c:chart
916 24
        $objWriter->startElement('c:chart');
917 24
        $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart');
918 24
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
919 24
        $objWriter->writeAttribute('r:id', $shape->relationId);
920 24
        $objWriter->endElement();
921
922 24
        $objWriter->endElement();
923
924 24
        $objWriter->endElement();
925
926 24
        $objWriter->endElement();
927 24
    }
928
929
    /**
930
     * Write pic
931
     *
932
     * @param  \PhpOffice\Common\XMLWriter  $objWriter XML Writer
933
     * @param  \PhpOffice\PhpPresentation\Shape\Drawing\AbstractDrawingAdapter $shape
934
     * @param  int $shapeId
935
     * @throws \Exception
936
     */
937 8
    protected function writeShapeDrawing(XMLWriter $objWriter, ShapeDrawing\AbstractDrawingAdapter $shape, $shapeId)
938
    {
939
        // p:pic
940 8
        $objWriter->startElement('p:pic');
941
942
        // p:nvPicPr
943 8
        $objWriter->startElement('p:nvPicPr');
944
945
        // p:cNvPr
946 8
        $objWriter->startElement('p:cNvPr');
947 8
        $objWriter->writeAttribute('id', $shapeId);
948 8
        $objWriter->writeAttribute('name', $shape->getName());
949 8
        $objWriter->writeAttribute('descr', $shape->getDescription());
950
951
        // a:hlinkClick
952 8
        if ($shape->hasHyperlink()) {
953 1
            $this->writeHyperlink($objWriter, $shape);
954 1
        }
955
956 8
        $objWriter->endElement();
957
958
        // p:cNvPicPr
959 8
        $objWriter->startElement('p:cNvPicPr');
960
961
        // a:picLocks
962 8
        $objWriter->startElement('a:picLocks');
963 8
        $objWriter->writeAttribute('noChangeAspect', '1');
964 8
        $objWriter->endElement();
965
966 8
        $objWriter->endElement();
967
968
        // p:nvPr
969 8
        $objWriter->startElement('p:nvPr');
970
        /**
971
         * @link : https://github.com/stefslon/exportToPPTX/blob/master/exportToPPTX.m#L2128
972
         */
973 8
        if ($shape instanceof Media) {
974
            // p:nvPr > a:videoFile
975 1
            $objWriter->startElement('a:videoFile');
976 1
            $objWriter->writeAttribute('r:link', $shape->relationId);
977 1
            $objWriter->endElement();
978
            // p:nvPr > p:extLst
979 1
            $objWriter->startElement('p:extLst');
980
            // p:nvPr > p:extLst > p:ext
981 1
            $objWriter->startElement('p:ext');
982 1
            $objWriter->writeAttribute('uri', '{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}');
983
            // p:nvPr > p:extLst > p:ext > p14:media
984 1
            $objWriter->startElement('p14:media');
985 1
            $objWriter->writeAttribute('r:embed', $shape->relationId);
986 1
            $objWriter->writeAttribute('xmlns:p14', 'http://schemas.microsoft.com/office/powerpoint/2010/main');
987
            // p:nvPr > p:extLst > p:ext > ##p14:media
988 1
            $objWriter->endElement();
989
            // p:nvPr > p:extLst > ##p:ext
990 1
            $objWriter->endElement();
991
            // p:nvPr > ##p:extLst
992 1
            $objWriter->endElement();
993 1
        }
994
        // ##p:nvPr
995 8
        $objWriter->endElement();
996 8
        $objWriter->endElement();
997
998
        // p:blipFill
999 8
        $objWriter->startElement('p:blipFill');
1000
1001
        // a:blip
1002 8
        $objWriter->startElement('a:blip');
1003 8
        $objWriter->writeAttribute('r:embed', $shape->relationId);
1004 8
        $objWriter->endElement();
1005
1006
        // a:stretch
1007 8
        $objWriter->startElement('a:stretch');
1008 8
        $objWriter->writeElement('a:fillRect', null);
1009 8
        $objWriter->endElement();
1010
1011 8
        $objWriter->endElement();
1012
1013
        // p:spPr
1014 8
        $objWriter->startElement('p:spPr');
1015
        // a:xfrm
1016 8
        $objWriter->startElement('a:xfrm');
1017 8
        $objWriter->writeAttribute('rot', CommonDrawing::degreesToAngle($shape->getRotation()));
1018
1019
        // a:off
1020 8
        $objWriter->startElement('a:off');
1021 8
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1022 8
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1023 8
        $objWriter->endElement();
1024
1025
        // a:ext
1026 8
        $objWriter->startElement('a:ext');
1027 8
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1028 8
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1029 8
        $objWriter->endElement();
1030
1031 8
        $objWriter->endElement();
1032
1033
        // a:prstGeom
1034 8
        $objWriter->startElement('a:prstGeom');
1035 8
        $objWriter->writeAttribute('prst', 'rect');
1036
1037
        // a:avLst
1038 8
        $objWriter->writeElement('a:avLst', null);
1039
1040 8
        $objWriter->endElement();
1041
1042 8
        $this->writeBorder($objWriter, $shape->getBorder(), '');
1043
1044 8
        $this->writeShadow($objWriter, $shape->getShadow());
1045
1046 8
        $objWriter->endElement();
1047
1048 8
        $objWriter->endElement();
1049 8
    }
1050
1051
    /**
1052
     * Write txt
1053
     *
1054
     * @param  \PhpOffice\Common\XMLWriter $objWriter XML Writer
1055
     * @param  \PhpOffice\PhpPresentation\Shape\RichText   $shape
1056
     * @param  int                            $shapeId
1057
     * @throws \Exception
1058
     */
1059 22
    protected function writeShapeText(XMLWriter $objWriter, RichText $shape, $shapeId)
1060
    {
1061
        // p:sp
1062 22
        $objWriter->startElement('p:sp');
1063
1064
        // p:sp/p:nvSpPr
1065 22
        $objWriter->startElement('p:nvSpPr');
1066
1067
        // p:sp/p:nvSpPr/p:cNvPr
1068 22
        $objWriter->startElement('p:cNvPr');
1069 22
        $objWriter->writeAttribute('id', $shapeId);
1070 22
        $objWriter->writeAttribute('name', '');
1071
1072
        // Hyperlink
1073 22
        if ($shape->hasHyperlink()) {
1074 1
            $this->writeHyperlink($objWriter, $shape);
1075 1
        }
1076
        // > p:sp/p:nvSpPr
1077 22
        $objWriter->endElement();
1078
1079
        // p:sp/p:cNvSpPr
1080 22
        $objWriter->startElement('p:cNvSpPr');
1081 22
        $objWriter->writeAttribute('txBox', '1');
1082 22
        $objWriter->endElement();
1083
        // p:sp/p:cNvSpPr/p:nvPr
1084 22
        if ($shape->isPlaceholder()) {
1085
            $objWriter->startElement('p:nvPr');
1086
            $objWriter->startElement('p:ph');
1087
            $objWriter->writeAttribute('type', $shape->getPlaceholder()->getType());
1088
            $objWriter->endElement();
1089
            $objWriter->endElement();
1090
        } else {
1091 22
            $objWriter->writeElement('p:nvPr', null);
1092
        }
1093
1094
        // > p:sp/p:cNvSpPr
1095 22
        $objWriter->endElement();
1096
1097
        // p:sp/p:spPr
1098 22
        $objWriter->startElement('p:spPr');
1099
1100
        // p:sp/p:spPr\a:xfrm
1101 22
        $objWriter->startElement('a:xfrm');
1102 22
        $objWriter->writeAttribute('rot', CommonDrawing::degreesToAngle($shape->getRotation()));
1103
1104
        // p:sp/p:spPr\a:xfrm\a:off
1105 22
        $objWriter->startElement('a:off');
1106 22
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1107 22
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1108 22
        $objWriter->endElement();
1109
1110
        // p:sp/p:spPr\a:xfrm\a:ext
1111 22
        $objWriter->startElement('a:ext');
1112 22
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1113 22
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1114 22
        $objWriter->endElement();
1115
1116
        // > p:sp/p:spPr\a:xfrm
1117 22
        $objWriter->endElement();
1118
1119
        // p:sp/p:spPr\a:prstGeom
1120 22
        $objWriter->startElement('a:prstGeom');
1121 22
        $objWriter->writeAttribute('prst', 'rect');
1122 22
        $objWriter->endElement();
1123
1124 22
        if ($shape->getFill()) {
1125 22
            $this->writeFill($objWriter, $shape->getFill());
1126 22
        }
1127 22
        $this->writeBorder($objWriter, $shape->getBorder(), '');
1128 22
        $this->writeShadow($objWriter, $shape->getShadow());
1129
1130
        // > p:sp/p:spPr
1131 22
        $objWriter->endElement();
1132
1133
        // p:txBody
1134 22
        $objWriter->startElement('p:txBody');
1135
1136
        // a:bodyPr
1137
        //@link :http://msdn.microsoft.com/en-us/library/documentformat.openxml.drawing.bodyproperties%28v=office.14%29.aspx
1138 22
        $objWriter->startElement('a:bodyPr');
1139 22
        $verticalAlign = $shape->getActiveParagraph()->getAlignment()->getVertical();
1140 22
        if ($verticalAlign != Alignment::VERTICAL_BASE && $verticalAlign != Alignment::VERTICAL_AUTO) {
1141 3
            $objWriter->writeAttribute('anchor', $verticalAlign);
1142 3
        }
1143 22
        if ($shape->getWrap() != RichText::WRAP_SQUARE) {
1144
            $objWriter->writeAttribute('wrap', $shape->getWrap());
1145
        }
1146 22
        $objWriter->writeAttribute('rtlCol', '0');
1147
1148 22
        if ($shape->getHorizontalOverflow() != RichText::OVERFLOW_OVERFLOW) {
1149
            $objWriter->writeAttribute('horzOverflow', $shape->getHorizontalOverflow());
1150
        }
1151 22
        if ($shape->getVerticalOverflow() != RichText::OVERFLOW_OVERFLOW) {
1152
            $objWriter->writeAttribute('vertOverflow', $shape->getVerticalOverflow());
1153
        }
1154
1155 22
        if ($shape->isUpright()) {
1156 1
            $objWriter->writeAttribute('upright', '1');
1157 1
        }
1158 22
        if ($shape->isVertical()) {
1159 1
            $objWriter->writeAttribute('vert', 'vert');
1160 1
        }
1161
1162 22
        $objWriter->writeAttribute('bIns', CommonDrawing::pixelsToEmu($shape->getInsetBottom()));
1163 22
        $objWriter->writeAttribute('lIns', CommonDrawing::pixelsToEmu($shape->getInsetLeft()));
1164 22
        $objWriter->writeAttribute('rIns', CommonDrawing::pixelsToEmu($shape->getInsetRight()));
1165 22
        $objWriter->writeAttribute('tIns', CommonDrawing::pixelsToEmu($shape->getInsetTop()));
1166
1167 22
        if ($shape->getColumns() <> 1) {
1168
            $objWriter->writeAttribute('numCol', $shape->getColumns());
1169
        }
1170
1171
        // a:spAutoFit
1172 22
        $objWriter->startElement('a:' . $shape->getAutoFit());
1173 22
        if ($shape->getAutoFit() == RichText::AUTOFIT_NORMAL) {
1174 1
            if (!is_null($shape->getFontScale())) {
1175 1
                $objWriter->writeAttribute('fontScale', (int)($shape->getFontScale() * 1000));
1176 1
            }
1177 1
            if (!is_null($shape->getLineSpaceReduction())) {
1178 1
                $objWriter->writeAttribute('lnSpcReduction', (int)($shape->getLineSpaceReduction() * 1000));
1179 1
            }
1180 1
        }
1181
1182 22
        $objWriter->endElement();
1183
1184 22
        $objWriter->endElement();
1185
1186
        // a:lstStyle
1187 22
        $objWriter->writeElement('a:lstStyle', null);
1188
1189
        // Write paragraphs
1190 22
        $this->writeParagraphs($objWriter, $shape->getParagraphs());
1191
1192 22
        $objWriter->endElement();
1193
1194 22
        $objWriter->endElement();
1195 22
    }
1196
1197
    /**
1198
     * Write table
1199
     *
1200
     * @param  \PhpOffice\Common\XMLWriter $objWriter XML Writer
1201
     * @param  \PhpOffice\PhpPresentation\Shape\Table      $shape
1202
     * @param  int                            $shapeId
1203
     * @throws \Exception
1204
     */
1205 9
    protected function writeShapeTable(XMLWriter $objWriter, ShapeTable $shape, $shapeId)
1206
    {
1207
        // p:graphicFrame
1208 9
        $objWriter->startElement('p:graphicFrame');
1209
1210
        // p:nvGraphicFramePr
1211 9
        $objWriter->startElement('p:nvGraphicFramePr');
1212
1213
        // p:cNvPr
1214 9
        $objWriter->startElement('p:cNvPr');
1215 9
        $objWriter->writeAttribute('id', $shapeId);
1216 9
        $objWriter->writeAttribute('name', $shape->getName());
1217 9
        $objWriter->writeAttribute('descr', $shape->getDescription());
1218
1219 9
        $objWriter->endElement();
1220
1221
        // p:cNvGraphicFramePr
1222 9
        $objWriter->startElement('p:cNvGraphicFramePr');
1223
1224
        // a:graphicFrameLocks
1225 9
        $objWriter->startElement('a:graphicFrameLocks');
1226 9
        $objWriter->writeAttribute('noGrp', '1');
1227 9
        $objWriter->endElement();
1228
1229 9
        $objWriter->endElement();
1230
1231
        // p:nvPr
1232 9
        $objWriter->writeElement('p:nvPr', null);
1233
1234 9
        $objWriter->endElement();
1235
1236
        // p:xfrm
1237 9
        $objWriter->startElement('p:xfrm');
1238
1239
        // a:off
1240 9
        $objWriter->startElement('a:off');
1241 9
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1242 9
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1243 9
        $objWriter->endElement();
1244
1245
        // a:ext
1246 9
        $objWriter->startElement('a:ext');
1247 9
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1248 9
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1249 9
        $objWriter->endElement();
1250
1251 9
        $objWriter->endElement();
1252
1253
        // a:graphic
1254 9
        $objWriter->startElement('a:graphic');
1255
1256
        // a:graphicData
1257 9
        $objWriter->startElement('a:graphicData');
1258 9
        $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/table');
1259
1260
        // a:tbl
1261 9
        $objWriter->startElement('a:tbl');
1262
1263
        // a:tblPr
1264 9
        $objWriter->startElement('a:tblPr');
1265 9
        $objWriter->writeAttribute('firstRow', '1');
1266 9
        $objWriter->writeAttribute('bandRow', '1');
1267
1268 9
        $objWriter->endElement();
1269
1270
        // a:tblGrid
1271 9
        $objWriter->startElement('a:tblGrid');
1272
1273
        // Write cell widths
1274 9
        $countCells = count($shape->getRow(0)->getCells());
1275 9
        for ($cell = 0; $cell < $countCells; $cell++) {
1276
            // a:gridCol
1277 9
            $objWriter->startElement('a:gridCol');
1278
1279
            // Calculate column width
1280 9
            $width = $shape->getRow(0)->getCell($cell)->getWidth();
1281 9
            if ($width == 0) {
1282 9
                $colCount   = count($shape->getRow(0)->getCells());
1283 9
                $totalWidth = $shape->getWidth();
1284 9
                $width      = $totalWidth / $colCount;
1285 9
            }
1286
1287 9
            $objWriter->writeAttribute('w', CommonDrawing::pixelsToEmu($width));
1288 9
            $objWriter->endElement();
1289 9
        }
1290
1291 9
        $objWriter->endElement();
1292
1293
        // Colspan / rowspan containers
1294 9
        $colSpan = array();
1295 9
        $rowSpan = array();
1296
1297
        // Default border style
1298 9
        $defaultBorder = new Border();
1299
1300
        // Write rows
1301 9
        $countRows = count($shape->getRows());
1302 9
        for ($row = 0; $row < $countRows; $row++) {
1303
            // a:tr
1304 9
            $objWriter->startElement('a:tr');
1305 9
            $objWriter->writeAttribute('h', CommonDrawing::pixelsToEmu($shape->getRow($row)->getHeight()));
1306
1307
            // Write cells
1308 9
            $countCells = count($shape->getRow($row)->getCells());
1309 9
            for ($cell = 0; $cell < $countCells; $cell++) {
1310
                // Current cell
1311 9
                $currentCell = $shape->getRow($row)->getCell($cell);
1312
1313
                // Next cell right
1314 9
                $nextCellRight = $shape->getRow($row)->getCell($cell + 1, true);
1315
1316
                // Next cell below
1317 9
                $nextRowBelow  = $shape->getRow($row + 1, true);
1318 9
                $nextCellBelow = null;
1319 9
                if ($nextRowBelow != null) {
1320 2
                    $nextCellBelow = $nextRowBelow->getCell($cell, true);
1321 2
                }
1322
1323
                // a:tc
1324 9
                $objWriter->startElement('a:tc');
1325
                // Colspan
1326 9
                if ($currentCell->getColSpan() > 1) {
1327 1
                    $objWriter->writeAttribute('gridSpan', $currentCell->getColSpan());
1328 1
                    $colSpan[$row] = $currentCell->getColSpan() - 1;
1329 9
                } elseif (isset($colSpan[$row]) && $colSpan[$row] > 0) {
1330 1
                    $colSpan[$row]--;
1331 1
                    $objWriter->writeAttribute('hMerge', '1');
1332 1
                }
1333
1334
                // Rowspan
1335 9
                if ($currentCell->getRowSpan() > 1) {
1336 1
                    $objWriter->writeAttribute('rowSpan', $currentCell->getRowSpan());
1337 1
                    $rowSpan[$cell] = $currentCell->getRowSpan() - 1;
1338 9
                } elseif (isset($rowSpan[$cell]) && $rowSpan[$cell] > 0) {
1339 1
                    $rowSpan[$cell]--;
1340 1
                    $objWriter->writeAttribute('vMerge', '1');
1341 1
                }
1342
1343
                // a:txBody
1344 9
                $objWriter->startElement('a:txBody');
1345
1346
                // a:bodyPr
1347 9
                $objWriter->startElement('a:bodyPr');
1348 9
                $objWriter->writeAttribute('wrap', 'square');
1349 9
                $objWriter->writeAttribute('rtlCol', '0');
1350
1351
                // a:spAutoFit
1352 9
                $objWriter->writeElement('a:spAutoFit', null);
1353
1354 9
                $objWriter->endElement();
1355
1356
                // a:lstStyle
1357 9
                $objWriter->writeElement('a:lstStyle', null);
1358
1359
                // Write paragraphs
1360 9
                $this->writeParagraphs($objWriter, $currentCell->getParagraphs());
1361
1362 9
                $objWriter->endElement();
1363
1364
                // a:tcPr
1365 9
                $objWriter->startElement('a:tcPr');
1366
                // Alignment (horizontal)
1367 9
                $firstParagraph  = $currentCell->getParagraph(0);
1368 9
                $verticalAlign = $firstParagraph->getAlignment()->getVertical();
1369 9
                if ($verticalAlign != Alignment::VERTICAL_BASE && $verticalAlign != Alignment::VERTICAL_AUTO) {
1370 1
                    $objWriter->writeAttribute('anchor', $verticalAlign);
1371 1
                }
1372
1373
                // Determine borders
1374 9
                $borderLeft         = $currentCell->getBorders()->getLeft();
1375 9
                $borderRight        = $currentCell->getBorders()->getRight();
1376 9
                $borderTop          = $currentCell->getBorders()->getTop();
1377 9
                $borderBottom       = $currentCell->getBorders()->getBottom();
1378 9
                $borderDiagonalDown = $currentCell->getBorders()->getDiagonalDown();
1379 9
                $borderDiagonalUp   = $currentCell->getBorders()->getDiagonalUp();
1380
1381
                // Fix PowerPoint implementation
1382 9
                if (!is_null($nextCellRight) && $nextCellRight->getBorders()->getRight()->getHashCode() != $defaultBorder->getHashCode()) {
1383 1
                    $borderRight = $nextCellRight->getBorders()->getLeft();
1384 1
                }
1385 9
                if (!is_null($nextCellBelow) && $nextCellBelow->getBorders()->getBottom()->getHashCode() != $defaultBorder->getHashCode()) {
1386 1
                    $borderBottom = $nextCellBelow->getBorders()->getTop();
1387 1
                }
1388
1389
                // Write borders
1390 9
                $this->writeBorder($objWriter, $borderLeft, 'L');
1391 9
                $this->writeBorder($objWriter, $borderRight, 'R');
1392 9
                $this->writeBorder($objWriter, $borderTop, 'T');
1393 9
                $this->writeBorder($objWriter, $borderBottom, 'B');
1394 9
                $this->writeBorder($objWriter, $borderDiagonalDown, 'TlToBr');
1395 9
                $this->writeBorder($objWriter, $borderDiagonalUp, 'BlToTr');
1396
1397
                // Fill
1398 9
                $this->writeFill($objWriter, $currentCell->getFill());
1399
1400 9
                $objWriter->endElement();
1401
1402 9
                $objWriter->endElement();
1403 9
            }
1404
1405 9
            $objWriter->endElement();
1406 9
        }
1407
1408 9
        $objWriter->endElement();
1409
1410 9
        $objWriter->endElement();
1411
1412 9
        $objWriter->endElement();
1413
1414 9
        $objWriter->endElement();
1415 9
    }
1416
1417
    /**
1418
     * Write paragraphs
1419
     *
1420
     * @param  \PhpOffice\Common\XMLWriter           $objWriter  XML Writer
1421
     * @param  \PhpOffice\PhpPresentation\Shape\RichText\Paragraph[] $paragraphs
1422
     * @throws \Exception
1423
     */
1424 32
    protected function writeParagraphs(XMLWriter $objWriter, $paragraphs)
1425
    {
1426
        // Loop trough paragraphs
1427 32
        foreach ($paragraphs as $paragraph) {
1428
            // a:p
1429 32
            $objWriter->startElement('a:p');
1430
1431
            // a:pPr
1432 32
            $objWriter->startElement('a:pPr');
1433 32
            $objWriter->writeAttribute('algn', $paragraph->getAlignment()->getHorizontal());
1434 32
            $objWriter->writeAttribute('fontAlgn', $paragraph->getAlignment()->getVertical());
1435 32
            $objWriter->writeAttribute('marL', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginLeft()));
1436 32
            $objWriter->writeAttribute('marR', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getMarginRight()));
1437 32
            $objWriter->writeAttribute('indent', CommonDrawing::pixelsToEmu($paragraph->getAlignment()->getIndent()));
1438 32
            $objWriter->writeAttribute('lvl', $paragraph->getAlignment()->getLevel());
1439
1440
            // Bullet type specified?
1441 32
            if ($paragraph->getBulletStyle()->getBulletType() != Bullet::TYPE_NONE) {
1442
                // a:buFont
1443 2
                $objWriter->startElement('a:buFont');
1444 2
                $objWriter->writeAttribute('typeface', $paragraph->getBulletStyle()->getBulletFont());
1445 2
                $objWriter->endElement();
1446
1447 2
                if ($paragraph->getBulletStyle()->getBulletType() == Bullet::TYPE_BULLET) {
1448
                    // a:buChar
1449 1
                    $objWriter->startElement('a:buChar');
1450 1
                    $objWriter->writeAttribute('char', $paragraph->getBulletStyle()->getBulletChar());
1451 1
                    $objWriter->endElement();
1452 2
                } elseif ($paragraph->getBulletStyle()->getBulletType() == Bullet::TYPE_NUMERIC) {
1453
                    // a:buAutoNum
1454 1
                    $objWriter->startElement('a:buAutoNum');
1455 1
                    $objWriter->writeAttribute('type', $paragraph->getBulletStyle()->getBulletNumericStyle());
1456 1
                    if ($paragraph->getBulletStyle()->getBulletNumericStartAt() != 1) {
1457 1
                        $objWriter->writeAttribute('startAt', $paragraph->getBulletStyle()->getBulletNumericStartAt());
1458 1
                    }
1459 1
                    $objWriter->endElement();
1460 1
                }
1461 2
            }
1462
1463 32
            $objWriter->endElement();
1464
1465
            // Loop trough rich text elements
1466 32
            $elements = $paragraph->getRichTextElements();
1467 32
            foreach ($elements as $element) {
1468 27
                if ($element instanceof BreakElement) {
1469
                    // a:br
1470 1
                    $objWriter->writeElement('a:br', null);
1471 27
                } elseif ($element instanceof Run || $element instanceof TextElement) {
1472
                    // a:r
1473 26
                    $objWriter->startElement('a:r');
1474
1475
                    // a:rPr
1476 26
                    if ($element instanceof Run) {
1477
                        // a:rPr
1478 26
                        $objWriter->startElement('a:rPr');
1479
1480
                        // Lang
1481 26
                        $objWriter->writeAttribute('lang', ($element->getLanguage() ? $element->getLanguage() : 'en-US'));
1482
1483
                        // Bold
1484 26
                        $objWriter->writeAttribute('b', ($element->getFont()->isBold() ? '1' : '0'));
1485
1486
                        // Italic
1487 26
                        $objWriter->writeAttribute('i', ($element->getFont()->isItalic() ? '1' : '0'));
1488
1489
                        // Strikethrough
1490 26
                        $objWriter->writeAttribute('strike', ($element->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike'));
1491
1492
                        // Size
1493 26
                        $objWriter->writeAttribute('sz', ($element->getFont()->getSize() * 100));
1494
1495
                        // Underline
1496 26
                        $objWriter->writeAttribute('u', $element->getFont()->getUnderline());
1497
1498
                        // Superscript / subscript
1499 26
                        if ($element->getFont()->isSuperScript() || $element->getFont()->isSubScript()) {
1500 2
                            if ($element->getFont()->isSuperScript()) {
1501 1
                                $objWriter->writeAttribute('baseline', '30000');
1502 2
                            } elseif ($element->getFont()->isSubScript()) {
1503 1
                                $objWriter->writeAttribute('baseline', '-25000');
1504 1
                            }
1505 2
                        }
1506
1507
                        // Color - a:solidFill
1508 26
                        $objWriter->startElement('a:solidFill');
1509
1510 26
                        $this->writeColor($objWriter, $element->getFont()->getColor());
1511
1512 26
                        $objWriter->endElement();
1513
1514
                        // Font - a:latin
1515 26
                        $objWriter->startElement('a:latin');
1516 26
                        $objWriter->writeAttribute('typeface', $element->getFont()->getName());
1517 26
                        $objWriter->endElement();
1518
1519
                        // a:hlinkClick
1520 26
                        if ($element->hasHyperlink()) {
1521 3
                            $this->writeHyperlink($objWriter, $element);
1522 3
                        }
1523
1524 26
                        $objWriter->endElement();
1525 26
                    }
1526
1527
                    // t
1528 26
                    $objWriter->startElement('a:t');
1529 26
                    $objWriter->writeCData(Text::controlCharacterPHP2OOXML($element->getText()));
1530 26
                    $objWriter->endElement();
1531
1532 26
                    $objWriter->endElement();
1533 26
                }
1534 32
            }
1535
1536 32
            $objWriter->endElement();
1537 32
        }
1538 32
    }
1539
1540
    /**
1541
     * Write Line Shape
1542
     *
1543
     * @param  \PhpOffice\Common\XMLWriter $objWriter XML Writer
1544
     * @param \PhpOffice\PhpPresentation\Shape\Line $shape
1545
     * @param  int $shapeId
1546
     */
1547 1
    protected function writeShapeLine(XMLWriter $objWriter, Line $shape, $shapeId)
1548
    {
1549
        // p:sp
1550 1
        $objWriter->startElement('p:cxnSp');
1551
1552
        // p:nvSpPr
1553 1
        $objWriter->startElement('p:nvCxnSpPr');
1554
1555
        // p:cNvPr
1556 1
        $objWriter->startElement('p:cNvPr');
1557 1
        $objWriter->writeAttribute('id', $shapeId);
1558 1
        $objWriter->writeAttribute('name', '');
1559
1560 1
        $objWriter->endElement();
1561
1562
        // p:cNvCxnSpPr
1563 1
        $objWriter->writeElement('p:cNvCxnSpPr', null);
1564
1565
        // p:nvPr
1566 1
        $objWriter->writeElement('p:nvPr', null);
1567
1568 1
        $objWriter->endElement();
1569
1570
        // p:spPr
1571 1
        $objWriter->startElement('p:spPr');
1572
1573
        // a:xfrm
1574 1
        $objWriter->startElement('a:xfrm');
1575
1576 1
        if ($shape->getWidth() >= 0 && $shape->getHeight() >= 0) {
1577
            // a:off
1578 1
            $objWriter->startElement('a:off');
1579 1
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1580 1
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1581 1
            $objWriter->endElement();
1582
1583
            // a:ext
1584 1
            $objWriter->startElement('a:ext');
1585 1
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1586 1
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1587 1
            $objWriter->endElement();
1588 1
        } elseif ($shape->getWidth() < 0 && $shape->getHeight() < 0) {
1589
            // a:off
1590 1
            $objWriter->startElement('a:off');
1591 1
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX() + $shape->getWidth()));
1592 1
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY() + $shape->getHeight()));
1593 1
            $objWriter->endElement();
1594
1595
            // a:ext
1596 1
            $objWriter->startElement('a:ext');
1597 1
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu(-$shape->getWidth()));
1598 1
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu(-$shape->getHeight()));
1599 1
            $objWriter->endElement();
1600 1
        } elseif ($shape->getHeight() < 0) {
1601 1
            $objWriter->writeAttribute('flipV', 1);
1602
1603
            // a:off
1604 1
            $objWriter->startElement('a:off');
1605 1
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX()));
1606 1
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY() + $shape->getHeight()));
1607 1
            $objWriter->endElement();
1608
1609
            // a:ext
1610 1
            $objWriter->startElement('a:ext');
1611 1
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($shape->getWidth()));
1612 1
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu(-$shape->getHeight()));
1613 1
            $objWriter->endElement();
1614 1
        } elseif ($shape->getWidth() < 0) {
1615 1
            $objWriter->writeAttribute('flipV', 1);
1616
1617
            // a:off
1618 1
            $objWriter->startElement('a:off');
1619 1
            $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($shape->getOffsetX() + $shape->getWidth()));
1620 1
            $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($shape->getOffsetY()));
1621 1
            $objWriter->endElement();
1622
1623
            // a:ext
1624 1
            $objWriter->startElement('a:ext');
1625 1
            $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu(-$shape->getWidth()));
1626 1
            $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($shape->getHeight()));
1627 1
            $objWriter->endElement();
1628 1
        }
1629
1630 1
        $objWriter->endElement();
1631
1632
        // a:prstGeom
1633 1
        $objWriter->startElement('a:prstGeom');
1634 1
        $objWriter->writeAttribute('prst', 'line');
1635 1
        $objWriter->endElement();
1636
1637 1
        if ($shape->getBorder()->getLineStyle() != Border::LINE_NONE) {
1638 1
            $this->writeBorder($objWriter, $shape->getBorder(), '');
1639 1
        }
1640
1641 1
        $objWriter->endElement();
1642
1643 1
        $objWriter->endElement();
1644 1
    }
1645
1646
    /**
1647
     * Write Shadow
1648
     * @param XMLWriter $objWriter
1649
     * @param Shadow $oShadow
1650
     */
1651 30
    protected function writeShadow(XMLWriter $objWriter, $oShadow)
1652
    {
1653 30
        if (!($oShadow instanceof Shadow)) {
1654
            return;
1655
        }
1656
1657 30
        if (!$oShadow->isVisible()) {
1658 28
            return;
1659
        }
1660
1661
        // a:effectLst
1662 2
        $objWriter->startElement('a:effectLst');
1663
1664
        // a:outerShdw
1665 2
        $objWriter->startElement('a:outerShdw');
1666 2
        $objWriter->writeAttribute('blurRad', CommonDrawing::pixelsToEmu($oShadow->getBlurRadius()));
1667 2
        $objWriter->writeAttribute('dist', CommonDrawing::pixelsToEmu($oShadow->getDistance()));
1668 2
        $objWriter->writeAttribute('dir', CommonDrawing::degreesToAngle($oShadow->getDirection()));
1669 2
        $objWriter->writeAttribute('algn', $oShadow->getAlignment());
1670 2
        $objWriter->writeAttribute('rotWithShape', '0');
1671
1672 2
        $this->writeColor($objWriter, $oShadow->getColor(), $oShadow->getAlpha());
1673
1674 2
        $objWriter->endElement();
1675
1676 2
        $objWriter->endElement();
1677 2
    }
1678
1679
    /**
1680
     * Write hyperlink
1681
     *
1682
     * @param \PhpOffice\Common\XMLWriter                               $objWriter XML Writer
1683
     * @param \PhpOffice\PhpPresentation\AbstractShape|\PhpOffice\PhpPresentation\Shape\RichText\TextElement $shape
1684
     */
1685 5
    protected function writeHyperlink(XMLWriter $objWriter, $shape)
1686
    {
1687
        // a:hlinkClick
1688 5
        $objWriter->startElement('a:hlinkClick');
1689 5
        $objWriter->writeAttribute('r:id', $shape->getHyperlink()->relationId);
1690 5
        $objWriter->writeAttribute('tooltip', $shape->getHyperlink()->getTooltip());
1691 5
        if ($shape->getHyperlink()->isInternal()) {
1692 1
            $objWriter->writeAttribute('action', $shape->getHyperlink()->getUrl());
1693 1
        }
1694 5
        $objWriter->endElement();
1695 5
    }
1696
1697
    /**
1698
     * Write Note Slide
1699
     * @param Note $pNote
1700
     * @throws \Exception
1701
     * @return  string
1702
     */
1703 1
    protected function writeNote(Note $pNote)
1704
    {
1705
        // Create XML writer
1706 1
        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
1707
1708
        // XML header
1709 1
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
1710
1711
        // p:notes
1712 1
        $objWriter->startElement('p:notes');
1713 1
        $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main');
1714 1
        $objWriter->writeAttribute('xmlns:p', 'http://schemas.openxmlformats.org/presentationml/2006/main');
1715 1
        $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships');
1716
1717
        // p:notes/p:cSld
1718 1
        $objWriter->startElement('p:cSld');
1719
1720
        // p:notes/p:cSld/p:spTree
1721 1
        $objWriter->startElement('p:spTree');
1722
1723
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr
1724 1
        $objWriter->startElement('p:nvGrpSpPr');
1725
1726
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr/p:cNvPr
1727 1
        $objWriter->startElement('p:cNvPr');
1728 1
        $objWriter->writeAttribute('id', '1');
1729 1
        $objWriter->writeAttribute('name', '');
1730 1
        $objWriter->endElement();
1731
1732
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr/p:cNvGrpSpPr
1733 1
        $objWriter->writeElement('p:cNvGrpSpPr', null);
1734
1735
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr/p:nvPr
1736 1
        $objWriter->writeElement('p:nvPr', null);
1737
1738
        // p:notes/p:cSld/p:spTree/p:nvGrpSpPr
1739 1
        $objWriter->endElement();
1740
1741
        // p:notes/p:cSld/p:spTree/p:grpSpPr
1742 1
        $objWriter->startElement('p:grpSpPr');
1743
1744
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm
1745 1
        $objWriter->startElement('a:xfrm');
1746
1747
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:off
1748 1
        $objWriter->startElement('a:off');
1749 1
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pNote->getOffsetX()));
1750 1
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pNote->getOffsetY()));
1751 1
        $objWriter->endElement(); // a:off
1752
1753
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:ext
1754 1
        $objWriter->startElement('a:ext');
1755 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pNote->getExtentX()));
1756 1
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pNote->getExtentY()));
1757 1
        $objWriter->endElement(); // a:ext
1758
1759
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:chOff
1760 1
        $objWriter->startElement('a:chOff');
1761 1
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pNote->getOffsetX()));
1762 1
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu($pNote->getOffsetY()));
1763 1
        $objWriter->endElement(); // a:chOff
1764
1765
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm/a:chExt
1766 1
        $objWriter->startElement('a:chExt');
1767 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu($pNote->getExtentX()));
1768 1
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu($pNote->getExtentY()));
1769 1
        $objWriter->endElement(); // a:chExt
1770
1771
        // p:notes/p:cSld/p:spTree/p:grpSpPr/a:xfrm
1772 1
        $objWriter->endElement();
1773
1774
        // p:notes/p:cSld/p:spTree/p:grpSpPr
1775 1
        $objWriter->endElement();
1776
1777
        // p:notes/p:cSld/p:spTree/p:sp[1]
1778 1
        $objWriter->startElement('p:sp');
1779
1780
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr
1781 1
        $objWriter->startElement('p:nvSpPr');
1782
1783
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvPr
1784 1
        $objWriter->startElement('p:cNvPr');
1785 1
        $objWriter->writeAttribute('id', '2');
1786 1
        $objWriter->writeAttribute('name', 'Slide Image Placeholder 1');
1787 1
        $objWriter->endElement();
1788
1789
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvSpPr
1790 1
        $objWriter->startElement('p:cNvSpPr');
1791
1792
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvSpPr/a:spLocks
1793 1
        $objWriter->startElement('a:spLocks');
1794 1
        $objWriter->writeAttribute('noGrp', '1');
1795 1
        $objWriter->writeAttribute('noRot', '1');
1796 1
        $objWriter->writeAttribute('noChangeAspect', '1');
1797 1
        $objWriter->endElement();
1798
1799
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:cNvSpPr
1800 1
        $objWriter->endElement();
1801
1802
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:nvPr
1803 1
        $objWriter->startElement('p:nvPr');
1804
1805
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:nvPr/p:ph
1806 1
        $objWriter->startElement('p:ph');
1807 1
        $objWriter->writeAttribute('type', 'sldImg');
1808 1
        $objWriter->endElement();
1809
1810
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr/p:nvPr
1811 1
        $objWriter->endElement();
1812
1813
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:nvSpPr
1814 1
        $objWriter->endElement();
1815
1816
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr
1817 1
        $objWriter->startElement('p:spPr');
1818
1819
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm
1820 1
        $objWriter->startElement('a:xfrm');
1821
1822
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm/a:off
1823 1
        $objWriter->startElement('a:off');
1824 1
        $objWriter->writeAttribute('x', 0);
1825 1
        $objWriter->writeAttribute('y', 0);
1826 1
        $objWriter->endElement();
1827
1828
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm/a:ext
1829 1
        $objWriter->startElement('a:ext');
1830 1
        $objWriter->writeAttribute('cx', CommonDrawing::pixelsToEmu(round($pNote->getExtentX() / 2)));
1831 1
        $objWriter->writeAttribute('cy', CommonDrawing::pixelsToEmu(round($pNote->getExtentY() / 2)));
1832 1
        $objWriter->endElement();
1833
1834
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:xfrm
1835 1
        $objWriter->endElement();
1836
1837
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:prstGeom
1838 1
        $objWriter->startElement('a:prstGeom');
1839 1
        $objWriter->writeAttribute('prst', 'rect');
1840
1841
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:prstGeom/a:avLst
1842 1
        $objWriter->writeElement('a:avLst', null);
1843
1844
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:prstGeom
1845 1
        $objWriter->endElement();
1846
1847
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:noFill
1848 1
        $objWriter->writeElement('a:noFill', null);
1849
1850
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln
1851 1
        $objWriter->startElement('a:ln');
1852 1
        $objWriter->writeAttribute('w', '12700');
1853
1854
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:solidFill
1855 1
        $objWriter->startElement('a:solidFill');
1856
1857
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:solidFill/a:prstClr
1858 1
        $objWriter->startElement('a:prstClr');
1859 1
        $objWriter->writeAttribute('val', 'black');
1860 1
        $objWriter->endElement();
1861
1862
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln/a:solidFill
1863 1
        $objWriter->endElement();
1864
1865
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr/a:ln
1866 1
        $objWriter->endElement();
1867
1868
        // p:notes/p:cSld/p:spTree/p:sp[1]/p:spPr
1869 1
        $objWriter->endElement();
1870
1871
        // p:notes/p:cSld/p:spTree/p:sp[1]
1872 1
        $objWriter->endElement();
1873
1874
        // p:notes/p:cSld/p:spTree/p:sp[2]
1875 1
        $objWriter->startElement('p:sp');
1876
1877
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr
1878 1
        $objWriter->startElement('p:nvSpPr');
1879
1880
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvPr
1881 1
        $objWriter->startElement('p:cNvPr');
1882 1
        $objWriter->writeAttribute('id', '3');
1883 1
        $objWriter->writeAttribute('name', 'Notes Placeholder');
1884 1
        $objWriter->endElement();
1885
1886
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvSpPr
1887 1
        $objWriter->startElement('p:cNvSpPr');
1888
1889
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvSpPr/a:spLocks
1890 1
        $objWriter->startElement('a:spLocks');
1891 1
        $objWriter->writeAttribute('noGrp', '1');
1892 1
        $objWriter->endElement();
1893
1894
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:cNvSpPr
1895 1
        $objWriter->endElement();
1896
1897
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:nvPr
1898 1
        $objWriter->startElement('p:nvPr');
1899
1900
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:nvPr/p:ph
1901 1
        $objWriter->startElement('p:ph');
1902 1
        $objWriter->writeAttribute('type', 'body');
1903 1
        $objWriter->writeAttribute('idx', '1');
1904 1
        $objWriter->endElement();
1905
1906
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr/p:nvPr
1907 1
        $objWriter->endElement();
1908
1909
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:nvSpPr
1910 1
        $objWriter->endElement();
1911
1912
        // START notes print below rectangle section
1913
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr
1914 1
        $objWriter->startElement('p:spPr');
1915
1916
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm
1917 1
        $objWriter->startElement('a:xfrm');
1918
1919
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm/a:off
1920 1
        $objWriter->startElement('a:off');
1921 1
        $objWriter->writeAttribute('x', CommonDrawing::pixelsToEmu($pNote->getOffsetX()));
1922 1
        $objWriter->writeAttribute('y', CommonDrawing::pixelsToEmu(round($pNote->getExtentY() / 2) + $pNote->getOffsetY()));
1923 1
        $objWriter->endElement();
1924
1925
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm/a:ext
1926 1
        $objWriter->startElement('a:ext');
1927 1
        $objWriter->writeAttribute('cx', '5486400');
1928 1
        $objWriter->writeAttribute('cy', '3600450');
1929 1
        $objWriter->endElement();
1930
1931
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:xfrm
1932 1
        $objWriter->endElement();
1933
1934
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:prstGeom
1935 1
        $objWriter->startElement('a:prstGeom');
1936 1
        $objWriter->writeAttribute('prst', 'rect');
1937
1938
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:prstGeom/a:avLst
1939 1
        $objWriter->writeElement('a:avLst', null);
1940
1941
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr/a:prstGeom
1942 1
        $objWriter->endElement();
1943
1944
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:spPr
1945 1
        $objWriter->endElement();
1946
1947
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody
1948 1
        $objWriter->startElement('p:txBody');
1949
1950
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody/a:bodyPr
1951 1
        $objWriter->writeElement('a:bodyPr', null);
1952
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody/a:lstStyle
1953 1
        $objWriter->writeElement('a:lstStyle', null);
1954
1955
        // Loop shapes
1956 1
        $shapes  = $pNote->getShapeCollection();
1957 1
        foreach ($shapes as $shape) {
1958
            // Check type
1959 1
            if ($shape instanceof RichText) {
1960 1
                $paragraphs = $shape->getParagraphs();
1961 1
                $this->writeParagraphs($objWriter, $paragraphs);
1962 1
            }
1963 1
        }
1964
1965
        // p:notes/p:cSld/p:spTree/p:sp[2]/p:txBody
1966 1
        $objWriter->endElement();
1967
1968
        // p:notes/p:cSld/p:spTree/p:sp[2]
1969 1
        $objWriter->endElement();
1970
1971
        // p:notes/p:cSld/p:spTree
1972 1
        $objWriter->endElement();
1973
1974
        // p:notes/p:cSld
1975 1
        $objWriter->endElement();
1976
1977
        // p:notes
1978 1
        $objWriter->endElement();
1979
1980
        // Return
1981 1
        return $objWriter->getData();
1982
    }
1983
1984
    /**
1985
     * Write Transition Slide
1986
     * @link http://officeopenxml.com/prSlide-transitions.php
1987
     * @param XMLWriter $objWriter
1988
     * @param Transition $transition
1989
     */
1990 95
    protected function writeSlideTransition(XMLWriter $objWriter, $transition)
1991
    {
1992 95
        if (!$transition instanceof Transition) {
1993 95
            return;
1994
        }
1995 1
        $objWriter->startElement('p:transition');
1996 1
        if (!is_null($transition->getSpeed())) {
1997 1
            $objWriter->writeAttribute('spd', $transition->getSpeed());
1998 1
        }
1999 1
        $objWriter->writeAttribute('advClick', $transition->hasManualTrigger() ? '1' : '0');
2000 1
        if ($transition->hasTimeTrigger()) {
2001 1
            $objWriter->writeAttribute('advTm', $transition->getAdvanceTimeTrigger());
2002 1
        }
2003
2004 1
        switch ($transition->getTransitionType()) {
2005 1
            case Transition::TRANSITION_BLINDS_HORIZONTAL:
2006 1
                $objWriter->startElement('p:blinds');
2007 1
                $objWriter->writeAttribute('dir', 'horz');
2008 1
                $objWriter->endElement();
2009 1
                break;
2010 1
            case Transition::TRANSITION_BLINDS_VERTICAL:
2011 1
                $objWriter->startElement('p:blinds');
2012 1
                $objWriter->writeAttribute('dir', 'vert');
2013 1
                $objWriter->endElement();
2014 1
                break;
2015 1
            case Transition::TRANSITION_CHECKER_HORIZONTAL:
2016 1
                $objWriter->startElement('p:checker');
2017 1
                $objWriter->writeAttribute('dir', 'horz');
2018 1
                $objWriter->endElement();
2019 1
                break;
2020 1
            case Transition::TRANSITION_CHECKER_VERTICAL:
2021 1
                $objWriter->startElement('p:checker');
2022 1
                $objWriter->writeAttribute('dir', 'vert');
2023 1
                $objWriter->endElement();
2024 1
                break;
2025 1
            case Transition::TRANSITION_CIRCLE_HORIZONTAL:
2026 1
                $objWriter->startElement('p:circle');
2027 1
                $objWriter->writeAttribute('dir', 'horz');
2028 1
                $objWriter->endElement();
2029 1
                break;
2030 1
            case Transition::TRANSITION_CIRCLE_VERTICAL:
2031 1
                $objWriter->startElement('p:circle');
2032 1
                $objWriter->writeAttribute('dir', 'vert');
2033 1
                $objWriter->endElement();
2034 1
                break;
2035 1
            case Transition::TRANSITION_COMB_HORIZONTAL:
2036 1
                $objWriter->startElement('p:comb');
2037 1
                $objWriter->writeAttribute('dir', 'horz');
2038 1
                $objWriter->endElement();
2039 1
                break;
2040 1
            case Transition::TRANSITION_COMB_VERTICAL:
2041 1
                $objWriter->startElement('p:comb');
2042 1
                $objWriter->writeAttribute('dir', 'vert');
2043 1
                $objWriter->endElement();
2044 1
                break;
2045 1
            case Transition::TRANSITION_COVER_DOWN:
2046 1
                $objWriter->startElement('p:cover');
2047 1
                $objWriter->writeAttribute('dir', 'd');
2048 1
                $objWriter->endElement();
2049 1
                break;
2050 1
            case Transition::TRANSITION_COVER_LEFT:
2051 1
                $objWriter->startElement('p:cover');
2052 1
                $objWriter->writeAttribute('dir', 'l');
2053 1
                $objWriter->endElement();
2054 1
                break;
2055 1
            case Transition::TRANSITION_COVER_LEFT_DOWN:
2056 1
                $objWriter->startElement('p:cover');
2057 1
                $objWriter->writeAttribute('dir', 'ld');
2058 1
                $objWriter->endElement();
2059 1
                break;
2060 1
            case Transition::TRANSITION_COVER_LEFT_UP:
2061 1
                $objWriter->startElement('p:cover');
2062 1
                $objWriter->writeAttribute('dir', 'lu');
2063 1
                $objWriter->endElement();
2064 1
                break;
2065 1
            case Transition::TRANSITION_COVER_RIGHT:
2066 1
                $objWriter->startElement('p:cover');
2067 1
                $objWriter->writeAttribute('dir', 'r');
2068 1
                $objWriter->endElement();
2069 1
                break;
2070 1
            case Transition::TRANSITION_COVER_RIGHT_DOWN:
2071 1
                $objWriter->startElement('p:cover');
2072 1
                $objWriter->writeAttribute('dir', 'rd');
2073 1
                $objWriter->endElement();
2074 1
                break;
2075 1
            case Transition::TRANSITION_COVER_RIGHT_UP:
2076 1
                $objWriter->startElement('p:cover');
2077 1
                $objWriter->writeAttribute('dir', 'ru');
2078 1
                $objWriter->endElement();
2079 1
                break;
2080 1
            case Transition::TRANSITION_COVER_UP:
2081 1
                $objWriter->startElement('p:cover');
2082 1
                $objWriter->writeAttribute('dir', 'u');
2083 1
                $objWriter->endElement();
2084 1
                break;
2085 1
            case Transition::TRANSITION_CUT:
2086 1
                $objWriter->writeElement('p:cut');
2087 1
                break;
2088 1
            case Transition::TRANSITION_DIAMOND:
2089 1
                $objWriter->writeElement('p:diamond');
2090 1
                break;
2091 1
            case Transition::TRANSITION_DISSOLVE:
2092 1
                $objWriter->writeElement('p:dissolve');
2093 1
                break;
2094 1
            case Transition::TRANSITION_FADE:
2095 1
                $objWriter->writeElement('p:fade');
2096 1
                break;
2097 1
            case Transition::TRANSITION_NEWSFLASH:
2098 1
                $objWriter->writeElement('p:newsflash');
2099 1
                break;
2100 1
            case Transition::TRANSITION_PLUS:
2101 1
                $objWriter->writeElement('p:plus');
2102 1
                break;
2103 1
            case Transition::TRANSITION_PULL_DOWN:
2104 1
                $objWriter->startElement('p:pull');
2105 1
                $objWriter->writeAttribute('dir', 'd');
2106 1
                $objWriter->endElement();
2107 1
                break;
2108 1
            case Transition::TRANSITION_PULL_LEFT:
2109 1
                $objWriter->startElement('p:pull');
2110 1
                $objWriter->writeAttribute('dir', 'l');
2111 1
                $objWriter->endElement();
2112 1
                break;
2113 1
            case Transition::TRANSITION_PULL_RIGHT:
2114 1
                $objWriter->startElement('p:pull');
2115 1
                $objWriter->writeAttribute('dir', 'r');
2116 1
                $objWriter->endElement();
2117 1
                break;
2118 1
            case Transition::TRANSITION_PULL_UP:
2119 1
                $objWriter->startElement('p:pull');
2120 1
                $objWriter->writeAttribute('dir', 'u');
2121 1
                $objWriter->endElement();
2122 1
                break;
2123 1
            case Transition::TRANSITION_PUSH_DOWN:
2124 1
                $objWriter->startElement('p:push');
2125 1
                $objWriter->writeAttribute('dir', 'd');
2126 1
                $objWriter->endElement();
2127 1
                break;
2128 1
            case Transition::TRANSITION_PUSH_LEFT:
2129 1
                $objWriter->startElement('p:push');
2130 1
                $objWriter->writeAttribute('dir', 'l');
2131 1
                $objWriter->endElement();
2132 1
                break;
2133 1
            case Transition::TRANSITION_PUSH_RIGHT:
2134 1
                $objWriter->startElement('p:push');
2135 1
                $objWriter->writeAttribute('dir', 'r');
2136 1
                $objWriter->endElement();
2137 1
                break;
2138 1
            case Transition::TRANSITION_PUSH_UP:
2139 1
                $objWriter->startElement('p:push');
2140 1
                $objWriter->writeAttribute('dir', 'u');
2141 1
                $objWriter->endElement();
2142 1
                break;
2143 1
            case Transition::TRANSITION_RANDOM:
2144 1
                $objWriter->writeElement('p:random');
2145 1
                break;
2146 1
            case Transition::TRANSITION_RANDOMBAR_HORIZONTAL:
2147 1
                $objWriter->startElement('p:randomBar');
2148 1
                $objWriter->writeAttribute('dir', 'horz');
2149 1
                $objWriter->endElement();
2150 1
                break;
2151 1
            case Transition::TRANSITION_RANDOMBAR_VERTICAL:
2152 1
                $objWriter->startElement('p:randomBar');
2153 1
                $objWriter->writeAttribute('dir', 'vert');
2154 1
                $objWriter->endElement();
2155 1
                break;
2156 1
            case Transition::TRANSITION_SPLIT_IN_HORIZONTAL:
2157 1
                $objWriter->startElement('p:split');
2158 1
                $objWriter->writeAttribute('dir', 'in');
2159 1
                $objWriter->writeAttribute('orient', 'horz');
2160 1
                $objWriter->endElement();
2161 1
                break;
2162 1
            case Transition::TRANSITION_SPLIT_OUT_HORIZONTAL:
2163 1
                $objWriter->startElement('p:split');
2164 1
                $objWriter->writeAttribute('dir', 'out');
2165 1
                $objWriter->writeAttribute('orient', 'horz');
2166 1
                $objWriter->endElement();
2167 1
                break;
2168 1
            case Transition::TRANSITION_SPLIT_IN_VERTICAL:
2169 1
                $objWriter->startElement('p:split');
2170 1
                $objWriter->writeAttribute('dir', 'in');
2171 1
                $objWriter->writeAttribute('orient', 'vert');
2172 1
                $objWriter->endElement();
2173 1
                break;
2174 1
            case Transition::TRANSITION_SPLIT_OUT_VERTICAL:
2175 1
                $objWriter->startElement('p:split');
2176 1
                $objWriter->writeAttribute('dir', 'out');
2177 1
                $objWriter->writeAttribute('orient', 'vert');
2178 1
                $objWriter->endElement();
2179 1
                break;
2180 1
            case Transition::TRANSITION_STRIPS_LEFT_DOWN:
2181 1
                $objWriter->startElement('p:strips');
2182 1
                $objWriter->writeAttribute('dir', 'ld');
2183 1
                $objWriter->endElement();
2184 1
                break;
2185 1
            case Transition::TRANSITION_STRIPS_LEFT_UP:
2186 1
                $objWriter->startElement('p:strips');
2187 1
                $objWriter->writeAttribute('dir', 'lu');
2188 1
                $objWriter->endElement();
2189 1
                break;
2190 1
            case Transition::TRANSITION_STRIPS_RIGHT_DOWN:
2191 1
                $objWriter->startElement('p:strips');
2192 1
                $objWriter->writeAttribute('dir', 'rd');
2193 1
                $objWriter->endElement();
2194 1
                break;
2195 1
            case Transition::TRANSITION_STRIPS_RIGHT_UP:
2196 1
                $objWriter->startElement('p:strips');
2197 1
                $objWriter->writeAttribute('dir', 'ru');
2198 1
                $objWriter->endElement();
2199 1
                break;
2200 1
            case Transition::TRANSITION_WEDGE:
2201 1
                $objWriter->writeElement('p:wedge');
2202 1
                break;
2203 1
            case Transition::TRANSITION_WIPE_DOWN:
2204 1
                $objWriter->startElement('p:wipe');
2205 1
                $objWriter->writeAttribute('dir', 'd');
2206 1
                $objWriter->endElement();
2207 1
                break;
2208 1
            case Transition::TRANSITION_WIPE_LEFT:
2209 1
                $objWriter->startElement('p:wipe');
2210 1
                $objWriter->writeAttribute('dir', 'l');
2211 1
                $objWriter->endElement();
2212 1
                break;
2213 1
            case Transition::TRANSITION_WIPE_RIGHT:
2214 1
                $objWriter->startElement('p:wipe');
2215 1
                $objWriter->writeAttribute('dir', 'r');
2216 1
                $objWriter->endElement();
2217 1
                break;
2218 1
            case Transition::TRANSITION_WIPE_UP:
2219 1
                $objWriter->startElement('p:wipe');
2220 1
                $objWriter->writeAttribute('dir', 'u');
2221 1
                $objWriter->endElement();
2222 1
                break;
2223 1
            case Transition::TRANSITION_ZOOM_IN:
2224 1
                $objWriter->startElement('p:zoom');
2225 1
                $objWriter->writeAttribute('dir', 'in');
2226 1
                $objWriter->endElement();
2227 1
                break;
2228 1
            case Transition::TRANSITION_ZOOM_OUT:
2229 1
                $objWriter->startElement('p:zoom');
2230 1
                $objWriter->writeAttribute('dir', 'out');
2231 1
                $objWriter->endElement();
2232 1
                break;
2233 1
        }
2234
2235 1
        $objWriter->endElement();
2236 1
    }
2237
}
2238