Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
73 / 73
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
ContentTypes
100.00% covered (success)
100.00%
73 / 73
100.00% covered (success)
100.00%
3 / 3
15
100.00% covered (success)
100.00%
1 / 1
 render
100.00% covered (success)
100.00%
65 / 65
100.00% covered (success)
100.00%
1 / 1
13
 writeDefaultContentType
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 writeOverrideContentType
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * This file is part of PHPPresentation - A pure PHP library for reading and writing
4 * presentations documents.
5 *
6 * PHPPresentation is free software distributed under the terms of the GNU Lesser
7 * General Public License version 3 as published by the Free Software Foundation.
8 *
9 * For the full copyright and license information, please read the LICENSE
10 * file that was distributed with this source code. For the full list of
11 * contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors.
12 *
13 * @see        https://github.com/PHPOffice/PHPPresentation
14 *
15 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16 */
17
18declare(strict_types=1);
19
20namespace PhpOffice\PhpPresentation\Writer\PowerPoint2007;
21
22use PhpOffice\Common\Adapter\Zip\ZipInterface;
23use PhpOffice\Common\XMLWriter;
24use PhpOffice\PhpPresentation\Shape\Chart as ShapeChart;
25use PhpOffice\PhpPresentation\Shape\Comment;
26use PhpOffice\PhpPresentation\Shape\Drawing\AbstractDrawingAdapter;
27
28/**
29 * \PhpOffice\PhpPresentation\Writer\PowerPoint2007\ContentTypes.
30 */
31class ContentTypes extends AbstractDecoratorWriter
32{
33    public function render(): ZipInterface
34    {
35        // Create XML writer
36        $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
37
38        // XML header
39        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
40
41        // Types
42        $objWriter->startElement('Types');
43        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/content-types');
44
45        // Rels
46        $this->writeDefaultContentType($objWriter, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');
47
48        // XML
49        $this->writeDefaultContentType($objWriter, 'xml', 'application/xml');
50
51        // SVG
52        $this->writeDefaultContentType($objWriter, 'svg', 'image/svg+xml');
53
54        // Presentation
55        $this->writeOverrideContentType($objWriter, '/ppt/presentation.xml', 'application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml');
56
57        // PptProps
58        $this->writeOverrideContentType($objWriter, '/ppt/presProps.xml', 'application/vnd.openxmlformats-officedocument.presentationml.presProps+xml');
59        $this->writeOverrideContentType($objWriter, '/ppt/tableStyles.xml', 'application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml');
60        $this->writeOverrideContentType($objWriter, '/ppt/viewProps.xml', 'application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml');
61
62        // DocProps
63        $this->writeOverrideContentType($objWriter, '/docProps/app.xml', 'application/vnd.openxmlformats-officedocument.extended-properties+xml');
64        $this->writeOverrideContentType($objWriter, '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml');
65        $this->writeOverrideContentType($objWriter, '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.custom-properties+xml');
66
67        // Slide masters
68        $sldLayoutNr = 0;
69        $sldLayoutId = time() + 689016272; // requires minimum value of 2 147 483 648
70        foreach ($this->oPresentation->getAllMasterSlides() as $idx => $oSlideMaster) {
71            $oSlideMaster->setRelsIndex((string) ($idx + 1));
72            $this->writeOverrideContentType($objWriter, '/ppt/slideMasters/slideMaster' . $oSlideMaster->getRelsIndex() . '.xml', 'application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml');
73            $this->writeOverrideContentType($objWriter, '/ppt/theme/theme' . $oSlideMaster->getRelsIndex() . '.xml', 'application/vnd.openxmlformats-officedocument.theme+xml');
74            foreach ($oSlideMaster->getAllSlideLayouts() as $oSlideLayout) {
75                $oSlideLayout->layoutNr = ++$sldLayoutNr;
76                $oSlideLayout->setRelsIndex((string) $oSlideLayout->layoutNr);
77                $oSlideLayout->layoutId = ++$sldLayoutId;
78                $this->writeOverrideContentType($objWriter, '/ppt/slideLayouts/slideLayout' . $oSlideLayout->layoutNr . '.xml', 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml');
79            }
80        }
81
82        // Slides
83        $hasComments = false;
84        $slideCount = $this->oPresentation->getSlideCount();
85        for ($i = 0; $i < $slideCount; ++$i) {
86            $oSlide = $this->oPresentation->getSlide($i);
87            $this->writeOverrideContentType($objWriter, '/ppt/slides/slide' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml');
88            if (count($oSlide->getNote()->getShapeCollection()) > 0) {
89                $this->writeOverrideContentType($objWriter, '/ppt/notesSlides/notesSlide' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml');
90            }
91            foreach ($oSlide->getShapeCollection() as $oShape) {
92                if ($oShape instanceof Comment) {
93                    $this->writeOverrideContentType($objWriter, '/ppt/comments/comment' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.presentationml.comments+xml');
94                    $hasComments = true;
95
96                    break;
97                }
98            }
99        }
100
101        if ($hasComments) {
102            $this->writeOverrideContentType($objWriter, '/ppt/commentAuthors.xml', 'application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml');
103        }
104
105        // Add media content-types
106        $aMediaContentTypes = [];
107
108        // GIF, JPEG, PNG
109        $aMediaContentTypes['gif'] = 'image/gif';
110        $aMediaContentTypes['jpg'] = 'image/jpeg';
111        $aMediaContentTypes['jpeg'] = 'image/jpeg';
112        $aMediaContentTypes['png'] = 'image/png';
113        foreach ($aMediaContentTypes as $key => $value) {
114            $this->writeDefaultContentType($objWriter, $key, $value);
115        }
116
117        // XLSX
118        $this->writeDefaultContentType($objWriter, 'xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
119
120        // Other media content types
121        $mediaCount = $this->getDrawingHashTable()->count();
122        for ($i = 0; $i < $mediaCount; ++$i) {
123            $shapeIndex = $this->getDrawingHashTable()->getByIndex($i);
124            if ($shapeIndex instanceof ShapeChart) {
125                // Chart content type
126                $this->writeOverrideContentType(
127                    $objWriter,
128                    '/ppt/charts/chart' . $shapeIndex->getImageIndex() . '.xml',
129                    'application/vnd.openxmlformats-officedocument.drawingml.chart+xml'
130                );
131            } elseif ($shapeIndex instanceof AbstractDrawingAdapter) {
132                $extension = strtolower($shapeIndex->getExtension());
133                $mimeType = $shapeIndex->getMimeType();
134
135                if (!isset($aMediaContentTypes[$extension])) {
136                    $aMediaContentTypes[$extension] = $mimeType;
137
138                    $this->writeDefaultContentType($objWriter, $extension, $mimeType);
139                }
140            }
141        }
142
143        $objWriter->endElement();
144
145        $this->oZip->addFromString('[Content_Types].xml', $objWriter->getData());
146
147        return $this->oZip;
148    }
149
150    /**
151     * Write Default content type.
152     *
153     * @param XMLWriter $objWriter XML Writer
154     * @param string $pPartname Part name
155     * @param string $pContentType Content type
156     */
157    protected function writeDefaultContentType(XMLWriter $objWriter, string $pPartname, string $pContentType): void
158    {
159        // Write content type
160        $objWriter->startElement('Default');
161        $objWriter->writeAttribute('Extension', $pPartname);
162        $objWriter->writeAttribute('ContentType', $pContentType);
163        $objWriter->endElement();
164    }
165
166    /**
167     * Write Override content type.
168     *
169     * @param XMLWriter $objWriter XML Writer
170     * @param string $pPartname Part name
171     * @param string $pContentType Content type
172     */
173    protected function writeOverrideContentType(XMLWriter $objWriter, string $pPartname, string $pContentType): void
174    {
175        // Write content type
176        $objWriter->startElement('Override');
177        $objWriter->writeAttribute('PartName', $pPartname);
178        $objWriter->writeAttribute('ContentType', $pContentType);
179        $objWriter->endElement();
180    }
181}