Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 196
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
PresentationWriter
0.00% covered (danger)
0.00%
0 / 196
0.00% covered (danger)
0.00%
0 / 8
3192
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 renderHtml
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
 append
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 displayPhpPresentation
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
30
 displayShape
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
42
 displayPhpPresentationInfo
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 1
182
 displayShapeInfo
0.00% covered (danger)
0.00%
0 / 92
0.00% covered (danger)
0.00%
0 / 1
600
 getConstantName
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   phpOMS\Utils\Parser\Presentation
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace phpOMS\Utils\Parser\Presentation;
16
17use PhpOffice\PhpPresentation\AbstractShape;
18use PhpOffice\PhpPresentation\DocumentLayout;
19use PhpOffice\PhpPresentation\PhpPresentation;
20use PhpOffice\PhpPresentation\Shape\Drawing\AbstractDrawingAdapter;
21use PhpOffice\PhpPresentation\Shape\Drawing\Base64;
22use PhpOffice\PhpPresentation\Shape\Drawing\File;
23use PhpOffice\PhpPresentation\Shape\Drawing\Gd;
24use PhpOffice\PhpPresentation\Shape\Drawing\ZipFile;
25use PhpOffice\PhpPresentation\Shape\Group;
26use PhpOffice\PhpPresentation\Shape\RichText;
27use PhpOffice\PhpPresentation\Shape\RichText\BreakElement;
28use PhpOffice\PhpPresentation\Shape\RichText\TextElement;
29use PhpOffice\PhpPresentation\Slide\AbstractBackground;
30use PhpOffice\PhpPresentation\Slide\Background\Color as BackgroundColor;
31use PhpOffice\PhpPresentation\Slide\Background\Image;
32use PhpOffice\PhpPresentation\Style\Bullet;
33
34/**
35 * Presentation parser class.
36 *
37 * @package phpOMS\Utils\Parser\Presentation
38 * @license OMS License 2.0
39 * @link    https://jingga.app
40 * @since   1.0.0
41 */
42class PresentationWriter
43{
44    /**
45     * Presentation object
46     *
47     * @var PhpPresentation
48     * @since 1.0.0
49     */
50    protected PhpPresentation $oPhpPresentation;
51
52    /**
53     * Html output
54     *
55     * @var string
56     * @since 1.0.0
57     */
58    protected string $htmlOutput = '';
59
60    /**
61     * Constructor
62     *
63     * @param PhpPresentation $oPHPPpt Presentation object
64     *
65     * @since 1.0.0
66     */
67    public function __construct(PhpPresentation $oPHPPpt)
68    {
69        $this->oPhpPresentation = $oPHPPpt;
70    }
71
72    /**
73     * Render presentation
74     *
75     * @return string
76     *
77     * @since 1.0.0
78     */
79    public function renderHtml() : string
80    {
81        $this->append('<div class="container-fluid pptTree">');
82        $this->append('<div class="row">');
83        $this->append('<div class="collapse in col-md-6">');
84        $this->append('<div class="tree">');
85        $this->append('<ul>');
86        $this->displayPhpPresentation($this->oPhpPresentation);
87        $this->append('</ul>');
88        $this->append('</div>');
89        $this->append('</div>');
90        $this->append('<div class="col-md-6">');
91        $this->displayPhpPresentationInfo($this->oPhpPresentation);
92        $this->append('</div>');
93        $this->append('</div>');
94        $this->append('</div>');
95
96        return $this->htmlOutput;
97    }
98
99    /**
100     * Add html to output
101     *
102     * @param string $sHTML Html
103     *
104     * @return void
105     *
106     * @since 1.0.0
107     */
108    protected function append(string $sHTML) : void
109    {
110        $this->htmlOutput .= $sHTML;
111    }
112
113    /**
114     * Constructor
115     *
116     * @param PhpPresentation $oPHPPpt Presentation object
117     *
118     * @return void
119     *
120     * @since 1.0.0
121     */
122    protected function displayPhpPresentation(PhpPresentation $oPHPPpt) : void
123    {
124        $this->append('<li><span><i class="fa fa-folder-open"></i> PhpPresentation</span>');
125        $this->append('<ul>');
126        $this->append('<li><span class="shape" id="divPhpPresentation"><i class="fa fa-info-circle"></i> Info "PhpPresentation"</span></li>');
127
128        foreach ($oPHPPpt->getAllSlides() as $oSlide) {
129            $this->append('<li><span><i class="fa fa-minus-square"></i> Slide</span>');
130            $this->append('<ul>');
131            $this->append('<li><span class="shape" id="div' . $oSlide->getHashCode() . '"><i class="fa fa-info-circle"></i> Info "Slide"</span></li>');
132
133            foreach ($oSlide->getShapeCollection() as $oShape) {
134                if ($oShape instanceof Group) {
135                    $this->append('<li><span><i class="fa fa-minus-square"></i> Shape "Group"</span>');
136                    $this->append('<ul>');
137                    // $this->append('<li><span class="shape" id="div'.$oShape->getHashCode().'"><i class="fa fa-info-circle"></i> Info "Group"</span></li>');
138                    foreach ($oShape->getShapeCollection() as $oShapeChild) {
139                        $this->displayShape($oShapeChild);
140                    }
141                    $this->append('</ul>');
142                    $this->append('</li>');
143                } else {
144                    $this->displayShape($oShape);
145                }
146            }
147
148            $this->append('</ul>');
149            $this->append('</li>');
150        }
151
152        $this->append('</ul>');
153        $this->append('</li>');
154    }
155
156    /**
157     * Render a shape
158     *
159     * @param AbstractShape $shape Shape to render
160     *
161     * @return void
162     *
163     * @since 1.0.0
164     */
165    protected function displayShape(AbstractShape $shape) : void
166    {
167        if ($shape instanceof Gd) {
168            $this->append('<li><span class="shape" id="div' . $shape->getHashCode() . '">Shape "Drawing\Gd"</span></li>');
169        } elseif ($shape instanceof File) {
170            $this->append('<li><span class="shape" id="div' . $shape->getHashCode() . '">Shape "Drawing\File"</span></li>');
171        } elseif ($shape instanceof Base64) {
172            $this->append('<li><span class="shape" id="div' . $shape->getHashCode() . '">Shape "Drawing\Base64"</span></li>');
173        } elseif ($shape instanceof ZipFile) {
174            $this->append('<li><span class="shape" id="div' . $shape->getHashCode() . '">Shape "Drawing\Zip"</span></li>');
175        } elseif ($shape instanceof RichText) {
176            $this->append('<li><span class="shape" id="div' . $shape->getHashCode() . '">Shape "RichText"</span></li>');
177        } else {
178            \var_dump($shape);
179        }
180    }
181
182    /**
183     * Render a shape
184     *
185     * @param PhpPresentation $oPHPPpt Presentation object
186     *
187     * @return void
188     *
189     * @since 1.0.0
190     */
191    protected function displayPhpPresentationInfo(PhpPresentation $oPHPPpt) : void
192    {
193        $this->append('<div class="infoBlk" id="divPhpPresentationInfo">');
194        $this->append('<dl>');
195        $this->append('<dt>Number of slides</dt><dd>' . $oPHPPpt->getSlideCount() . '</dd>');
196        $this->append('<dt>Document Layout Name</dt><dd>' . (empty($oPHPPpt->getLayout()->getDocumentLayout()) ? 'Custom' : $oPHPPpt->getLayout()->getDocumentLayout()) . '</dd>');
197        $this->append('<dt>Document Layout Height</dt><dd>' . $oPHPPpt->getLayout()->getCY(DocumentLayout::UNIT_MILLIMETER) . ' mm</dd>');
198        $this->append('<dt>Document Layout Width</dt><dd>' . $oPHPPpt->getLayout()->getCX(DocumentLayout::UNIT_MILLIMETER) . ' mm</dd>');
199        $this->append('<dt>Properties : Category</dt><dd>' . $oPHPPpt->getDocumentProperties()->getCategory() . '</dd>');
200        $this->append('<dt>Properties : Company</dt><dd>' . $oPHPPpt->getDocumentProperties()->getCompany() . '</dd>');
201        $this->append('<dt>Properties : Created</dt><dd>' . $oPHPPpt->getDocumentProperties()->getCreated() . '</dd>');
202        $this->append('<dt>Properties : Creator</dt><dd>' . $oPHPPpt->getDocumentProperties()->getCreator() . '</dd>');
203        $this->append('<dt>Properties : Description</dt><dd>' . $oPHPPpt->getDocumentProperties()->getDescription() . '</dd>');
204        $this->append('<dt>Properties : Keywords</dt><dd>' . $oPHPPpt->getDocumentProperties()->getKeywords() . '</dd>');
205        $this->append('<dt>Properties : Last Modified By</dt><dd>' . $oPHPPpt->getDocumentProperties()->getLastModifiedBy() . '</dd>');
206        $this->append('<dt>Properties : Modified</dt><dd>' . $oPHPPpt->getDocumentProperties()->getModified() . '</dd>');
207        $this->append('<dt>Properties : Subject</dt><dd>' . $oPHPPpt->getDocumentProperties()->getSubject() . '</dd>');
208        $this->append('<dt>Properties : Title</dt><dd>' . $oPHPPpt->getDocumentProperties()->getTitle() . '</dd>');
209        $this->append('</dl>');
210        $this->append('</div>');
211
212        foreach ($oPHPPpt->getAllSlides() as $oSlide) {
213            $this->append('<div class="infoBlk" id="div' . $oSlide->getHashCode() . 'Info">');
214            $this->append('<dl>');
215            $this->append('<dt>HashCode</dt><dd>' . $oSlide->getHashCode() . '</dd>');
216
217            $this->append('<dt>Offset X</dt><dd>' . $oSlide->getOffsetX() . '</dd>');
218            $this->append('<dt>Offset Y</dt><dd>' . $oSlide->getOffsetY() . '</dd>');
219            $this->append('<dt>Extent X</dt><dd>' . $oSlide->getExtentX() . '</dd>');
220            $this->append('<dt>Extent Y</dt><dd>' . $oSlide->getExtentY() . '</dd>');
221            $oBkg = $oSlide->getBackground();
222
223            if ($oBkg instanceof AbstractBackground) {
224                if ($oBkg instanceof BackgroundColor) {
225                    $this->append('<dt>Background Color</dt><dd>#' . $oBkg->getColor()->getRGB() . '</dd>');
226                }
227                if ($oBkg instanceof Image) {
228                    $sBkgImgContents = \file_get_contents($oBkg->getPath());
229
230                    if ($sBkgImgContents !== false) {
231                        $this->append('<dt>Background Image</dt><dd><img src="data:image/png;base64,' . \base64_encode($sBkgImgContents) . '"></dd>');
232                    }
233                }
234            }
235
236            $oNote = $oSlide->getNote();
237            if ($oNote->getShapeCollection()->count() > 0) {
238                $this->append('<dt>Notes</dt>');
239                foreach ($oNote->getShapeCollection() as $oShape) {
240                    if ($oShape instanceof RichText) {
241                        $this->append('<dd>' . $oShape->getPlainText() . '</dd>');
242                    }
243                }
244            }
245
246            $this->append('</dl>');
247            $this->append('</div>');
248
249            foreach ($oSlide->getShapeCollection() as $oShape) {
250                if ($oShape instanceof Group) {
251                    foreach ($oShape->getShapeCollection() as $oShapeChild) {
252                        $this->displayShapeInfo($oShapeChild);
253                    }
254                } else {
255                    $this->displayShapeInfo($oShape);
256                }
257            }
258        }
259    }
260
261    /**
262     * Render a shape info
263     *
264     * @param AbstractShape $oShape Shape to render
265     *
266     * @return void
267     *
268     * @since 1.0.0
269     */
270    protected function displayShapeInfo(AbstractShape $oShape) : void
271    {
272        $this->append('<div class="infoBlk" id="div' . $oShape->getHashCode() . 'Info">');
273        $this->append('<dl>');
274        $this->append('<dt>HashCode</dt><dd>' . $oShape->getHashCode() . '</dd>');
275        $this->append('<dt>Offset X</dt><dd>' . $oShape->getOffsetX() . '</dd>');
276        $this->append('<dt>Offset Y</dt><dd>' . $oShape->getOffsetY() . '</dd>');
277        $this->append('<dt>Height</dt><dd>' . $oShape->getHeight() . '</dd>');
278        $this->append('<dt>Width</dt><dd>' . $oShape->getWidth() . '</dd>');
279        $this->append('<dt>Rotation</dt><dd>' . $oShape->getRotation() . '°</dd>');
280        $this->append('<dt>Hyperlink</dt><dd>' . \ucfirst(\var_export($oShape->hasHyperlink(), true)) . '</dd>');
281        $this->append('<dt>Fill</dt>');
282
283        if ($oShape->getFill() === null) {
284            $this->append('<dd>None</dd>');
285        } else {
286            switch ($oShape->getFill()->getFillType()) {
287                case \PhpOffice\PhpPresentation\Style\Fill::FILL_NONE:
288                    $this->append('<dd>None</dd>');
289                    break;
290                case \PhpOffice\PhpPresentation\Style\Fill::FILL_SOLID:
291                    $this->append('<dd>Solid (');
292                    $this->append('Color : #' . $oShape->getFill()->getStartColor()->getRGB());
293                    $this->append(' - Alpha : ' . $oShape->getFill()->getStartColor()->getAlpha() . '%');
294                    $this->append(')</dd>');
295                    break;
296            }
297        }
298
299        $this->append('<dt>Border</dt><dd>@Todo</dd>');
300        $this->append('<dt>IsPlaceholder</dt><dd>' . ($oShape->isPlaceholder() ? 'true' : 'false') . '</dd>');
301
302        if ($oShape instanceof Gd) {
303            $this->append('<dt>Name</dt><dd>' . $oShape->getName() . '</dd>');
304            $this->append('<dt>Description</dt><dd>' . $oShape->getDescription() . '</dd>');
305            \ob_start();
306            $oShape->getRenderingFunction()($oShape->getImageResource());
307            $sShapeImgContents = \ob_get_contents();
308            \ob_end_clean();
309            $this->append('<dt>Mime-Type</dt><dd>' . $oShape->getMimeType() . '</dd>');
310            $this->append('<dt>Image</dt><dd><img src="data:' . $oShape->getMimeType() . ';base64,' . \base64_encode($sShapeImgContents) . '"></dd>');
311
312            if ($oShape->hasHyperlink()) {
313                $this->append('<dt>Hyperlink URL</dt><dd>' . $oShape->getHyperlink()->getUrl() . '</dd>');
314                $this->append('<dt>Hyperlink Tooltip</dt><dd>' . $oShape->getHyperlink()->getTooltip() . '</dd>');
315            }
316        } elseif ($oShape instanceof AbstractDrawingAdapter) {
317            $this->append('<dt>Name</dt><dd>' . $oShape->getName() . '</dd>');
318            $this->append('<dt>Description</dt><dd>' . $oShape->getDescription() . '</dd>');
319        } elseif ($oShape instanceof RichText) {
320            $this->append('<dt># of paragraphs</dt><dd>' . \count($oShape->getParagraphs()) . '</dd>');
321            $this->append('<dt>Inset (T / R / B / L)</dt><dd>' . $oShape->getInsetTop() . 'px / ' . $oShape->getInsetRight() . 'px / ' . $oShape->getInsetBottom() . 'px / ' . $oShape->getInsetLeft() . 'px</dd>');
322            $this->append('<dt>Text</dt>');
323            $this->append('<dd>');
324
325            foreach ($oShape->getParagraphs() as $oParagraph) {
326                $this->append('Paragraph<dl>');
327                $this->append('<dt>Alignment Horizontal</dt><dd> Alignment::' . $this->getConstantName('\PhpOffice\PhpPresentation\Style\Alignment', $oParagraph->getAlignment()->getHorizontal()) . '</dd>');
328                $this->append('<dt>Alignment Vertical</dt><dd> Alignment::' . $this->getConstantName('\PhpOffice\PhpPresentation\Style\Alignment', $oParagraph->getAlignment()->getVertical()) . '</dd>');
329                $this->append('<dt>Alignment Margin (L / R)</dt><dd>' . $oParagraph->getAlignment()->getMarginLeft() . ' px / ' . $oParagraph->getAlignment()->getMarginRight() . 'px</dd>');
330                $this->append('<dt>Alignment Indent</dt><dd>' . $oParagraph->getAlignment()->getIndent() . ' px</dd>');
331                $this->append('<dt>Alignment Level</dt><dd>' . $oParagraph->getAlignment()->getLevel() . '</dd>');
332
333                $bulletStyle = $oParagraph->getBulletStyle();
334                if ($bulletStyle !== null) {
335                    $this->append('<dt>Bullet Style</dt><dd> Bullet::' . $this->getConstantName('\PhpOffice\PhpPresentation\Style\Bullet', $bulletStyle->getBulletType()) . '</dd>');
336
337                    if ($bulletStyle->getBulletType() != Bullet::TYPE_NONE) {
338                        $this->append('<dt>Bullet Font</dt><dd>' . $bulletStyle->getBulletFont() . '</dd>');
339                        $this->append('<dt>Bullet Color</dt><dd>' . $bulletStyle->getBulletColor()->getARGB() . '</dd>');
340                    }
341
342                    if ($bulletStyle->getBulletType() == Bullet::TYPE_BULLET) {
343                        $this->append('<dt>Bullet Char</dt><dd>' . $bulletStyle->getBulletChar() . '</dd>');
344                    }
345
346                    if ($bulletStyle->getBulletType() == Bullet::TYPE_NUMERIC) {
347                        $this->append('<dt>Bullet Start At</dt><dd>' . $bulletStyle->getBulletNumericStartAt() . '</dd>');
348                        $this->append('<dt>Bullet Style</dt><dd>' . $bulletStyle->getBulletNumericStyle() . '</dd>');
349                    }
350                }
351
352                $this->append('<dt>Line Spacing</dt><dd>' . $oParagraph->getLineSpacing() . '</dd>');
353                $this->append('<dt>RichText</dt><dd><dl>');
354
355                foreach ($oParagraph->getRichTextElements() as $oRichText) {
356                    if ($oRichText instanceof BreakElement) {
357                        $this->append('<dt><i>Break</i></dt>');
358                    } else {
359                        if ($oRichText instanceof TextElement) {
360                            $this->append('<dt><i>TextElement</i></dt>');
361                        } else {
362                            $this->append('<dt><i>Run</i></dt>');
363                        }
364
365                        $this->append('<dd>' . $oRichText->getText());
366                        $this->append('<dl>');
367                        $this->append('<dt>Font Name</dt><dd>' . $oRichText->getFont()->getName() . '</dd>');
368                        $this->append('<dt>Font Size</dt><dd>' . $oRichText->getFont()->getSize() . '</dd>');
369                        $this->append('<dt>Font Color</dt><dd>#' . $oRichText->getFont()->getColor()->getARGB() . '</dd>');
370                        $this->append('<dt>Font Transform</dt><dd>');
371                        $this->append('<abbr title="Bold">Bold</abbr> : ' . ($oRichText->getFont()->isBold() ? 'Y' : 'N') . ' - ');
372                        $this->append('<abbr title="Italic">Italic</abbr> : ' . ($oRichText->getFont()->isItalic() ? 'Y' : 'N') . ' - ');
373                        $this->append('<abbr title="Underline">Underline</abbr> : Underline::' . $this->getConstantName('\PhpOffice\PhpPresentation\Style\Font', $oRichText->getFont()->getUnderline()) . ' - ');
374                        $this->append('<abbr title="Strikethrough">Strikethrough</abbr> : ' . ($oRichText->getFont()->isStrikethrough() ? 'Y' : 'N') . ' - ');
375                        $this->append('<abbr title="SubScript">SubScript</abbr> : ' . ($oRichText->getFont()->isSubScript() ? 'Y' : 'N') . ' - ');
376                        $this->append('<abbr title="SuperScript">SuperScript</abbr> : ' . ($oRichText->getFont()->isSuperScript() ? 'Y' : 'N'));
377                        $this->append('</dd>');
378
379                        if ($oRichText instanceof TextElement && $oRichText->hasHyperlink()) {
380                            $this->append('<dt>Hyperlink URL</dt><dd>' . $oRichText->getHyperlink()->getUrl() . '</dd>');
381                            $this->append('<dt>Hyperlink Tooltip</dt><dd>' . $oRichText->getHyperlink()->getTooltip() . '</dd>');
382                        }
383
384                        $this->append('</dl>');
385                        $this->append('</dd>');
386                    }
387                }
388
389                $this->append('</dl></dd></dl>');
390            }
391
392            $this->append('</dd>');
393        }
394
395        $this->append('</dl>');
396        $this->append('</div>');
397    }
398
399    /**
400     * Find constant
401     *
402     * @param string $class     Class to search in
403     * @param string $search    Value to search for
404     * @param string $startWith Constant name it starts with
405     *
406     * @return string
407     *
408     * @since 1.0.0
409     */
410    protected function getConstantName(string $class, string $search, string $startWith = '') : string
411    {
412        $fooClass  = new \ReflectionClass($class);
413        $constants = $fooClass->getConstants();
414        $constName = '';
415
416        foreach ($constants as $key => $value) {
417            if ($value === $search) {
418                if ($startWith === '' || \str_starts_with($key, $startWith)) {
419                    $constName = $key;
420                }
421
422                break;
423            }
424        }
425
426        return $constName;
427    }
428}