These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of PHPPresentation - A pure PHP library for reading and writing |
||
4 | * presentations documents. |
||
5 | * |
||
6 | * PHPPresentation is free software distributed under the terms of the GNU Lesser |
||
7 | * General Public License version 3 as published by the Free Software Foundation. |
||
8 | * |
||
9 | * For the full copyright and license information, please read the LICENSE |
||
10 | * file that was distributed with this source code. For the full list of |
||
11 | * contributors, visit https://github.com/PHPOffice/PHPPresentation/contributors. |
||
12 | * |
||
13 | * @link https://github.com/PHPOffice/PHPPresentation |
||
14 | * @copyright 2009-2015 PHPPresentation contributors |
||
15 | * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 |
||
16 | */ |
||
17 | |||
18 | namespace PhpOffice\PhpPresentation\Reader; |
||
19 | |||
20 | use PhpOffice\PhpPresentation\DocumentLayout; |
||
21 | use PhpOffice\PhpPresentation\PhpPresentation; |
||
22 | use PhpOffice\PhpPresentation\Shape\Placeholder; |
||
23 | use PhpOffice\PhpPresentation\Shape\RichText; |
||
24 | use PhpOffice\PhpPresentation\Shape\RichText\Paragraph; |
||
25 | use PhpOffice\PhpPresentation\Shape\Table\Cell; |
||
26 | use PhpOffice\PhpPresentation\Slide; |
||
27 | use PhpOffice\PhpPresentation\Slide\AbstractSlide; |
||
28 | use PhpOffice\PhpPresentation\Slide\SlideLayout; |
||
29 | use PhpOffice\PhpPresentation\Slide\SlideMaster; |
||
30 | use PhpOffice\PhpPresentation\Shape\Drawing\Gd; |
||
31 | use PhpOffice\PhpPresentation\Style\Bullet; |
||
32 | use PhpOffice\PhpPresentation\Style\Border; |
||
33 | use PhpOffice\PhpPresentation\Style\Borders; |
||
34 | use PhpOffice\PhpPresentation\Style\Color; |
||
35 | use PhpOffice\PhpPresentation\Style\Fill; |
||
36 | use PhpOffice\PhpPresentation\Style\SchemeColor; |
||
37 | use PhpOffice\PhpPresentation\Style\TextStyle; |
||
38 | use PhpOffice\Common\XMLReader; |
||
39 | use PhpOffice\Common\Drawing as CommonDrawing; |
||
40 | use ZipArchive; |
||
41 | |||
42 | /** |
||
43 | * Serialized format reader |
||
44 | */ |
||
45 | class PowerPoint2007 implements ReaderInterface |
||
46 | { |
||
47 | /** |
||
48 | * Output Object |
||
49 | * @var PhpPresentation |
||
50 | */ |
||
51 | protected $oPhpPresentation; |
||
52 | /** |
||
53 | * Output Object |
||
54 | * @var \ZipArchive |
||
55 | */ |
||
56 | protected $oZip; |
||
57 | /** |
||
58 | * @var array[] |
||
59 | */ |
||
60 | protected $arrayRels = array(); |
||
61 | /** |
||
62 | * @var SlideLayout[] |
||
63 | */ |
||
64 | protected $arraySlideLayouts = array(); |
||
65 | /* |
||
66 | * @var string |
||
67 | */ |
||
68 | protected $filename; |
||
69 | /* |
||
70 | * @var string |
||
71 | */ |
||
72 | protected $fileRels; |
||
73 | |||
74 | /** |
||
75 | * Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file? |
||
76 | * |
||
77 | * @param string $pFilename |
||
78 | * @throws \Exception |
||
79 | * @return boolean |
||
80 | */ |
||
81 | 2 | public function canRead($pFilename) |
|
82 | { |
||
83 | 2 | return $this->fileSupportsUnserializePhpPresentation($pFilename); |
|
84 | } |
||
85 | |||
86 | /** |
||
87 | * Does a file support UnserializePhpPresentation ? |
||
88 | * |
||
89 | * @param string $pFilename |
||
90 | * @throws \Exception |
||
91 | * @return boolean |
||
92 | */ |
||
93 | 9 | public function fileSupportsUnserializePhpPresentation($pFilename = '') |
|
94 | { |
||
95 | // Check if file exists |
||
96 | 9 | if (!file_exists($pFilename)) { |
|
97 | 2 | throw new \Exception("Could not open " . $pFilename . " for reading! File does not exist."); |
|
98 | } |
||
99 | |||
100 | 7 | $oZip = new ZipArchive(); |
|
101 | // Is it a zip ? |
||
102 | 7 | if ($oZip->open($pFilename) === true) { |
|
103 | // Is it an OpenXML Document ? |
||
104 | // Is it a Presentation ? |
||
105 | 5 | if (is_array($oZip->statName('[Content_Types].xml')) && is_array($oZip->statName('ppt/presentation.xml'))) { |
|
106 | 5 | return true; |
|
107 | } |
||
108 | } |
||
109 | 3 | return false; |
|
110 | } |
||
111 | |||
112 | /** |
||
113 | * Loads PhpPresentation Serialized file |
||
114 | * |
||
115 | * @param string $pFilename |
||
116 | * @return \PhpOffice\PhpPresentation\PhpPresentation |
||
117 | * @throws \Exception |
||
118 | */ |
||
119 | 6 | public function load($pFilename) |
|
120 | { |
||
121 | // Unserialize... First make sure the file supports it! |
||
122 | 6 | if (!$this->fileSupportsUnserializePhpPresentation($pFilename)) { |
|
123 | 1 | throw new \Exception("Invalid file format for PhpOffice\PhpPresentation\Reader\PowerPoint2007: " . $pFilename . "."); |
|
124 | } |
||
125 | |||
126 | 4 | return $this->loadFile($pFilename); |
|
127 | } |
||
128 | |||
129 | /** |
||
130 | * Load PhpPresentation Serialized file |
||
131 | * |
||
132 | * @param string $pFilename |
||
133 | * @return \PhpOffice\PhpPresentation\PhpPresentation |
||
134 | */ |
||
135 | 4 | protected function loadFile($pFilename) |
|
136 | { |
||
137 | 4 | $this->oPhpPresentation = new PhpPresentation(); |
|
138 | 4 | $this->oPhpPresentation->removeSlideByIndex(); |
|
139 | 4 | $this->oPhpPresentation->setAllMasterSlides(array()); |
|
140 | 4 | $this->filename = $pFilename; |
|
141 | |||
142 | 4 | $this->oZip = new ZipArchive(); |
|
143 | 4 | $this->oZip->open($this->filename); |
|
144 | 4 | $docPropsCore = $this->oZip->getFromName('docProps/core.xml'); |
|
145 | 4 | if ($docPropsCore !== false) { |
|
146 | 4 | $this->loadDocumentProperties($docPropsCore); |
|
147 | } |
||
148 | |||
149 | 4 | $docPropsCustom = $this->oZip->getFromName('docProps/custom.xml'); |
|
150 | 4 | if ($docPropsCustom !== false) { |
|
151 | 1 | $this->loadCustomProperties($docPropsCustom); |
|
152 | } |
||
153 | |||
154 | 4 | $pptViewProps = $this->oZip->getFromName('ppt/viewProps.xml'); |
|
155 | 4 | if ($pptViewProps !== false) { |
|
156 | 4 | $this->loadViewProperties($pptViewProps); |
|
157 | } |
||
158 | |||
159 | 4 | $pptPresentation = $this->oZip->getFromName('ppt/presentation.xml'); |
|
160 | 4 | if ($pptPresentation !== false) { |
|
161 | 4 | $this->loadDocumentLayout($pptPresentation); |
|
162 | 4 | $this->loadSlides($pptPresentation); |
|
163 | } |
||
164 | |||
165 | 4 | return $this->oPhpPresentation; |
|
166 | } |
||
167 | |||
168 | /** |
||
169 | * Read Document Layout |
||
170 | * @param $sPart |
||
171 | */ |
||
172 | 4 | protected function loadDocumentLayout($sPart) |
|
173 | { |
||
174 | 4 | $xmlReader = new XMLReader(); |
|
175 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
176 | 4 | foreach ($xmlReader->getElements('/p:presentation/p:sldSz') as $oElement) { |
|
177 | 4 | if (!($oElement instanceof \DOMElement)) { |
|
178 | continue; |
||
179 | } |
||
180 | 4 | $type = $oElement->getAttribute('type'); |
|
181 | 4 | $oLayout = $this->oPhpPresentation->getLayout(); |
|
182 | 4 | if ($type == DocumentLayout::LAYOUT_CUSTOM) { |
|
183 | $oLayout->setCX($oElement->getAttribute('cx')); |
||
184 | $oLayout->setCY($oElement->getAttribute('cy')); |
||
185 | } else { |
||
186 | 4 | $oLayout->setDocumentLayout($type, true); |
|
187 | 4 | if ($oElement->getAttribute('cx') < $oElement->getAttribute('cy')) { |
|
188 | 4 | $oLayout->setDocumentLayout($type, false); |
|
189 | } |
||
190 | } |
||
191 | } |
||
192 | } |
||
193 | 4 | } |
|
194 | |||
195 | /** |
||
196 | * Read Document Properties |
||
197 | * @param string $sPart |
||
198 | */ |
||
199 | 4 | protected function loadDocumentProperties($sPart) |
|
200 | { |
||
201 | 4 | $xmlReader = new XMLReader(); |
|
202 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
203 | $arrayProperties = array( |
||
204 | 4 | '/cp:coreProperties/dc:creator' => 'setCreator', |
|
205 | '/cp:coreProperties/cp:lastModifiedBy' => 'setLastModifiedBy', |
||
206 | '/cp:coreProperties/dc:title' => 'setTitle', |
||
207 | '/cp:coreProperties/dc:description' => 'setDescription', |
||
208 | '/cp:coreProperties/dc:subject' => 'setSubject', |
||
209 | '/cp:coreProperties/cp:keywords' => 'setKeywords', |
||
210 | '/cp:coreProperties/cp:category' => 'setCategory', |
||
211 | '/cp:coreProperties/dcterms:created' => 'setCreated', |
||
212 | '/cp:coreProperties/dcterms:modified' => 'setModified', |
||
213 | ); |
||
214 | 4 | $oProperties = $this->oPhpPresentation->getDocumentProperties(); |
|
215 | 4 | foreach ($arrayProperties as $path => $property) { |
|
216 | 4 | $oElement = $xmlReader->getElement($path); |
|
217 | 4 | if ($oElement instanceof \DOMElement) { |
|
218 | 4 | if ($oElement->hasAttribute('xsi:type') && $oElement->getAttribute('xsi:type') == 'dcterms:W3CDTF') { |
|
219 | 4 | $oDateTime = new \DateTime(); |
|
220 | 4 | $oDateTime->createFromFormat(\DateTime::W3C, $oElement->nodeValue); |
|
221 | 4 | $oProperties->{$property}($oDateTime->getTimestamp()); |
|
222 | } else { |
||
223 | 4 | $oProperties->{$property}($oElement->nodeValue); |
|
224 | } |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | 4 | } |
|
229 | |||
230 | /** |
||
231 | * Read Custom Properties |
||
232 | * @param string $sPart |
||
233 | */ |
||
234 | 1 | protected function loadCustomProperties($sPart) |
|
235 | { |
||
236 | 1 | $xmlReader = new XMLReader(); |
|
237 | 1 | $sPart = str_replace(' xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"', '', $sPart); |
|
238 | 1 | if ($xmlReader->getDomFromString($sPart)) { |
|
239 | 1 | $pathMarkAsFinal = '/Properties/property[@pid="2"][@fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"][@name="_MarkAsFinal"]/vt:bool'; |
|
240 | 1 | if (is_object($oElement = $xmlReader->getElement($pathMarkAsFinal))) { |
|
241 | 1 | if ($oElement->nodeValue == 'true') { |
|
242 | 1 | $this->oPhpPresentation->getPresentationProperties()->markAsFinal(true); |
|
243 | } |
||
244 | } |
||
245 | } |
||
246 | 1 | } |
|
247 | |||
248 | /** |
||
249 | * Read View Properties |
||
250 | * @param string $sPart |
||
251 | */ |
||
252 | 4 | protected function loadViewProperties($sPart) |
|
253 | { |
||
254 | 4 | $xmlReader = new XMLReader(); |
|
255 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
256 | 4 | $pathZoom = '/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx'; |
|
257 | 4 | $oElement = $xmlReader->getElement($pathZoom); |
|
258 | 4 | if ($oElement instanceof \DOMElement) { |
|
259 | 3 | if ($oElement->hasAttribute('d') && $oElement->hasAttribute('n')) { |
|
260 | 3 | $this->oPhpPresentation->getPresentationProperties()->setZoom($oElement->getAttribute('n') / $oElement->getAttribute('d')); |
|
261 | } |
||
262 | } |
||
263 | } |
||
264 | 4 | } |
|
265 | |||
266 | /** |
||
267 | * Extract all slides |
||
268 | */ |
||
269 | 4 | protected function loadSlides($sPart) |
|
270 | { |
||
271 | 4 | $xmlReader = new XMLReader(); |
|
272 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
273 | 4 | $fileRels = 'ppt/_rels/presentation.xml.rels'; |
|
274 | 4 | $this->loadRels($fileRels); |
|
275 | // Load the Masterslides |
||
276 | 4 | $this->loadMasterSlides($xmlReader, $fileRels); |
|
277 | // Continue with loading the slides |
||
278 | 4 | foreach ($xmlReader->getElements('/p:presentation/p:sldIdLst/p:sldId') as $oElement) { |
|
279 | 4 | if (!($oElement instanceof \DOMElement)) { |
|
280 | continue; |
||
281 | } |
||
282 | 4 | $rId = $oElement->getAttribute('r:id'); |
|
283 | 4 | $pathSlide = isset($this->arrayRels[$fileRels][$rId]) ? $this->arrayRels[$fileRels][$rId]['Target'] : ''; |
|
284 | 4 | if (!empty($pathSlide)) { |
|
285 | 4 | $pptSlide = $this->oZip->getFromName('ppt/' . $pathSlide); |
|
286 | 4 | if ($pptSlide !== false) { |
|
287 | 4 | $slideRels = 'ppt/slides/_rels/' . basename($pathSlide) . '.rels'; |
|
288 | 4 | $this->loadRels($slideRels); |
|
289 | 4 | $this->loadSlide($pptSlide, basename($pathSlide)); |
|
290 | 4 | foreach ($this->arrayRels[$slideRels] as $rel) { |
|
291 | 4 | if ($rel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide') { |
|
292 | 4 | $this->loadSlideNote(basename($rel['Target']), $this->oPhpPresentation->getActiveSlide()); |
|
293 | } |
||
294 | } |
||
295 | } |
||
296 | } |
||
297 | } |
||
298 | } |
||
299 | 4 | } |
|
300 | |||
301 | /** |
||
302 | * Extract all MasterSlides |
||
303 | * @param XMLReader $xmlReader |
||
304 | * @param string $fileRels |
||
305 | */ |
||
306 | 4 | protected function loadMasterSlides(XMLReader $xmlReader, $fileRels) |
|
307 | { |
||
308 | // Get all the MasterSlide Id's from the presentation.xml file |
||
309 | 4 | foreach ($xmlReader->getElements('/p:presentation/p:sldMasterIdLst/p:sldMasterId') as $oElement) { |
|
310 | 4 | if (!($oElement instanceof \DOMElement)) { |
|
311 | continue; |
||
312 | } |
||
313 | 4 | $rId = $oElement->getAttribute('r:id'); |
|
314 | // Get the path to the masterslide from the array with _rels files |
||
315 | 4 | $pathMasterSlide = isset($this->arrayRels[$fileRels][$rId]) ? |
|
316 | 4 | $this->arrayRels[$fileRels][$rId]['Target'] : ''; |
|
317 | 4 | if (!empty($pathMasterSlide)) { |
|
318 | 4 | $pptMasterSlide = $this->oZip->getFromName('ppt/' . $pathMasterSlide); |
|
319 | 4 | if ($pptMasterSlide !== false) { |
|
320 | 4 | $this->loadRels('ppt/slideMasters/_rels/' . basename($pathMasterSlide) . '.rels'); |
|
321 | 4 | $this->loadMasterSlide($pptMasterSlide, basename($pathMasterSlide)); |
|
322 | } |
||
323 | } |
||
324 | } |
||
325 | 4 | } |
|
326 | |||
327 | /** |
||
328 | * Extract data from slide |
||
329 | * @param string $sPart |
||
330 | * @param string $baseFile |
||
331 | */ |
||
332 | 4 | protected function loadSlide($sPart, $baseFile) |
|
333 | { |
||
334 | 4 | $xmlReader = new XMLReader(); |
|
335 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
336 | // Core |
||
337 | 4 | $oSlide = $this->oPhpPresentation->createSlide(); |
|
338 | 4 | $this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1); |
|
339 | 4 | $oSlide->setRelsIndex('ppt/slides/_rels/' . $baseFile . '.rels'); |
|
340 | |||
341 | // Background |
||
342 | 4 | $oElement = $xmlReader->getElement('/p:sld/p:cSld/p:bg/p:bgPr'); |
|
343 | 4 | if ($oElement instanceof \DOMElement) { |
|
344 | $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement); |
||
345 | if ($oElementColor instanceof \DOMElement) { |
||
346 | // Color |
||
347 | $oColor = new Color(); |
||
348 | $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null); |
||
349 | // Background |
||
350 | $oBackground = new Slide\Background\Color(); |
||
351 | $oBackground->setColor($oColor); |
||
352 | // Slide Background |
||
353 | $oSlide = $this->oPhpPresentation->getActiveSlide(); |
||
354 | $oSlide->setBackground($oBackground); |
||
355 | } |
||
356 | $oElementImage = $xmlReader->getElement('a:blipFill/a:blip', $oElement); |
||
357 | if ($oElementImage instanceof \DOMElement) { |
||
358 | $relImg = $this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'][$oElementImage->getAttribute('r:embed')]; |
||
359 | if (is_array($relImg)) { |
||
360 | // File |
||
361 | $pathImage = 'ppt/slides/' . $relImg['Target']; |
||
362 | $pathImage = explode('/', $pathImage); |
||
363 | foreach ($pathImage as $key => $partPath) { |
||
364 | if ($partPath == '..') { |
||
365 | unset($pathImage[$key - 1]); |
||
366 | unset($pathImage[$key]); |
||
367 | } |
||
368 | } |
||
369 | $pathImage = implode('/', $pathImage); |
||
370 | $contentImg = $this->oZip->getFromName($pathImage); |
||
371 | |||
372 | $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg'); |
||
373 | file_put_contents($tmpBkgImg, $contentImg); |
||
374 | // Background |
||
375 | $oBackground = new Slide\Background\Image(); |
||
376 | $oBackground->setPath($tmpBkgImg); |
||
377 | // Slide Background |
||
378 | $oSlide = $this->oPhpPresentation->getActiveSlide(); |
||
379 | $oSlide->setBackground($oBackground); |
||
380 | } |
||
381 | } |
||
382 | } |
||
383 | |||
384 | // Shapes |
||
385 | 4 | $arrayElements = $xmlReader->getElements('/p:sld/p:cSld/p:spTree/*'); |
|
386 | 4 | if ($arrayElements) { |
|
387 | 4 | $this->loadSlideShapes($oSlide, $arrayElements, $xmlReader); |
|
388 | } |
||
389 | |||
390 | // Layout |
||
391 | 4 | $oSlide = $this->oPhpPresentation->getActiveSlide(); |
|
392 | 4 | foreach ($this->arrayRels['ppt/slides/_rels/' . $baseFile . '.rels'] as $valueRel) { |
|
393 | 4 | if ($valueRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout') { |
|
394 | 4 | $layoutBasename = basename($valueRel['Target']); |
|
395 | 4 | if (array_key_exists($layoutBasename, $this->arraySlideLayouts)) { |
|
396 | 4 | $oSlide->setSlideLayout($this->arraySlideLayouts[$layoutBasename]); |
|
397 | } |
||
398 | 4 | break; |
|
399 | } |
||
400 | } |
||
401 | } |
||
402 | 4 | } |
|
403 | |||
404 | /** |
||
405 | * @param string $sPart |
||
406 | * @param string $baseFile |
||
407 | */ |
||
408 | 4 | protected function loadMasterSlide($sPart, $baseFile) |
|
409 | { |
||
410 | 4 | $xmlReader = new XMLReader(); |
|
411 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
412 | // Core |
||
413 | 4 | $oSlideMaster = $this->oPhpPresentation->createMasterSlide(); |
|
414 | 4 | $oSlideMaster->setTextStyles(new TextStyle(false)); |
|
415 | 4 | $oSlideMaster->setRelsIndex('ppt/slideMasters/_rels/' . $baseFile . '.rels'); |
|
416 | |||
417 | // Background |
||
418 | 4 | $oElement = $xmlReader->getElement('/p:sldMaster/p:cSld/p:bg'); |
|
419 | 4 | if ($oElement instanceof \DOMElement) { |
|
420 | 4 | $this->loadSlideBackground($xmlReader, $oElement, $oSlideMaster); |
|
421 | } |
||
422 | |||
423 | // Shapes |
||
424 | 4 | $arrayElements = $xmlReader->getElements('/p:sldMaster/p:cSld/p:spTree/*'); |
|
425 | 4 | if ($arrayElements) { |
|
426 | 4 | $this->loadSlideShapes($oSlideMaster, $arrayElements, $xmlReader); |
|
427 | } |
||
428 | // Header & Footer |
||
429 | |||
430 | // ColorMapping |
||
431 | 4 | $colorMap = array(); |
|
432 | 4 | $oElement = $xmlReader->getElement('/p:sldMaster/p:clrMap'); |
|
433 | 4 | if ($oElement->hasAttributes()) { |
|
434 | 4 | foreach ($oElement->attributes as $attr) { |
|
435 | 4 | $colorMap[$attr->nodeName] = $attr->nodeValue; |
|
436 | } |
||
437 | 4 | $oSlideMaster->colorMap->setMapping($colorMap); |
|
438 | } |
||
439 | |||
440 | // TextStyles |
||
441 | 4 | $arrayElementTxStyles = $xmlReader->getElements('/p:sldMaster/p:txStyles/*'); |
|
442 | 4 | if ($arrayElementTxStyles) { |
|
443 | 4 | foreach ($arrayElementTxStyles as $oElementTxStyle) { |
|
444 | 4 | $arrayElementsLvl = $xmlReader->getElements('/p:sldMaster/p:txStyles/' . $oElementTxStyle->nodeName . '/*'); |
|
445 | 4 | foreach ($arrayElementsLvl as $oElementLvl) { |
|
446 | 4 | if (!($oElementLvl instanceof \DOMElement) || $oElementLvl->nodeName == 'a:extLst') { |
|
447 | 1 | continue; |
|
448 | } |
||
449 | 4 | $oRTParagraph = new Paragraph(); |
|
450 | |||
451 | 4 | if ($oElementLvl->nodeName == 'a:defPPr') { |
|
452 | 3 | $level = 0; |
|
453 | } else { |
||
454 | 4 | $level = str_replace('a:lvl', '', $oElementLvl->nodeName); |
|
455 | 4 | $level = str_replace('pPr', '', $level); |
|
456 | } |
||
457 | |||
458 | 4 | if ($oElementLvl->hasAttribute('algn')) { |
|
459 | 4 | $oRTParagraph->getAlignment()->setHorizontal($oElementLvl->getAttribute('algn')); |
|
460 | } |
||
461 | 4 | if ($oElementLvl->hasAttribute('marL')) { |
|
462 | 4 | $val = $oElementLvl->getAttribute('marL'); |
|
463 | 4 | $val = CommonDrawing::emuToPixels($val); |
|
464 | 4 | $oRTParagraph->getAlignment()->setMarginLeft($val); |
|
465 | } |
||
466 | 4 | if ($oElementLvl->hasAttribute('marR')) { |
|
467 | $val = $oElementLvl->getAttribute('marR'); |
||
468 | $val = CommonDrawing::emuToPixels($val); |
||
469 | $oRTParagraph->getAlignment()->setMarginRight($val); |
||
470 | } |
||
471 | 4 | if ($oElementLvl->hasAttribute('indent')) { |
|
472 | 4 | $val = $oElementLvl->getAttribute('indent'); |
|
473 | 4 | $val = CommonDrawing::emuToPixels($val); |
|
474 | 4 | $oRTParagraph->getAlignment()->setIndent($val); |
|
475 | } |
||
476 | 4 | $oElementLvlDefRPR = $xmlReader->getElement('a:defRPr', $oElementLvl); |
|
477 | 4 | if ($oElementLvlDefRPR instanceof \DOMElement) { |
|
478 | 4 | if ($oElementLvlDefRPR->hasAttribute('sz')) { |
|
479 | 4 | $oRTParagraph->getFont()->setSize($oElementLvlDefRPR->getAttribute('sz') / 100); |
|
480 | } |
||
481 | 4 | if ($oElementLvlDefRPR->hasAttribute('b') && $oElementLvlDefRPR->getAttribute('b') == 1) { |
|
482 | 1 | $oRTParagraph->getFont()->setBold(true); |
|
483 | } |
||
484 | 4 | if ($oElementLvlDefRPR->hasAttribute('i') && $oElementLvlDefRPR->getAttribute('i') == 1) { |
|
485 | $oRTParagraph->getFont()->setItalic(true); |
||
486 | } |
||
487 | } |
||
488 | 4 | $oElementSchemeColor = $xmlReader->getElement('a:defRPr/a:solidFill/a:schemeClr', $oElementLvl); |
|
489 | 4 | if ($oElementSchemeColor instanceof \DOMElement) { |
|
490 | 4 | if ($oElementSchemeColor->hasAttribute('val')) { |
|
491 | 4 | $oSchemeColor = new SchemeColor(); |
|
492 | 4 | $oSchemeColor->setValue($oElementSchemeColor->getAttribute('val')); |
|
493 | 4 | $oRTParagraph->getFont()->setColor($oSchemeColor); |
|
494 | } |
||
495 | } |
||
496 | |||
497 | 4 | switch ($oElementTxStyle->nodeName) { |
|
498 | 4 | case 'p:bodyStyle': |
|
499 | 4 | $oSlideMaster->getTextStyles()->setBodyStyleAtLvl($oRTParagraph, $level); |
|
500 | 4 | break; |
|
501 | 4 | case 'p:otherStyle': |
|
502 | 4 | $oSlideMaster->getTextStyles()->setOtherStyleAtLvl($oRTParagraph, $level); |
|
503 | 4 | break; |
|
504 | 4 | case 'p:titleStyle': |
|
505 | 4 | $oSlideMaster->getTextStyles()->setTitleStyleAtLvl($oRTParagraph, $level); |
|
506 | 4 | break; |
|
507 | } |
||
508 | } |
||
509 | } |
||
510 | } |
||
511 | |||
512 | // Load the theme |
||
513 | 4 | foreach ($this->arrayRels[$oSlideMaster->getRelsIndex()] as $arrayRel) { |
|
514 | 4 | if ($arrayRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme') { |
|
515 | 4 | $pptTheme = $this->oZip->getFromName('ppt/' . substr($arrayRel['Target'], strrpos($arrayRel['Target'], '../') + 3)); |
|
516 | 4 | if ($pptTheme !== false) { |
|
517 | 4 | $this->loadTheme($pptTheme, $oSlideMaster); |
|
518 | } |
||
519 | 4 | break; |
|
520 | } |
||
521 | } |
||
522 | |||
523 | // Load the Layoutslide |
||
524 | 4 | foreach ($xmlReader->getElements('/p:sldMaster/p:sldLayoutIdLst/p:sldLayoutId') as $oElement) { |
|
525 | 4 | if (!($oElement instanceof \DOMElement)) { |
|
526 | continue; |
||
527 | } |
||
528 | 4 | $rId = $oElement->getAttribute('r:id'); |
|
529 | // Get the path to the masterslide from the array with _rels files |
||
530 | 4 | $pathLayoutSlide = isset($this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]) ? |
|
531 | 4 | $this->arrayRels[$oSlideMaster->getRelsIndex()][$rId]['Target'] : ''; |
|
532 | 4 | if (!empty($pathLayoutSlide)) { |
|
533 | 4 | $pptLayoutSlide = $this->oZip->getFromName('ppt/' . substr($pathLayoutSlide, strrpos($pathLayoutSlide, '../') + 3)); |
|
534 | 4 | if ($pptLayoutSlide !== false) { |
|
535 | 4 | $this->loadRels('ppt/slideLayouts/_rels/' . basename($pathLayoutSlide) . '.rels'); |
|
536 | 4 | $oSlideMaster->addSlideLayout( |
|
537 | 4 | $this->loadLayoutSlide($pptLayoutSlide, basename($pathLayoutSlide), $oSlideMaster) |
|
538 | ); |
||
539 | } |
||
540 | } |
||
541 | } |
||
542 | } |
||
543 | 4 | } |
|
544 | |||
545 | /** |
||
546 | * @param string $sPart |
||
547 | * @param string $baseFile |
||
548 | * @param SlideMaster $oSlideMaster |
||
549 | * @return SlideLayout|null |
||
550 | */ |
||
551 | 4 | protected function loadLayoutSlide($sPart, $baseFile, SlideMaster $oSlideMaster) |
|
552 | { |
||
553 | 4 | $xmlReader = new XMLReader(); |
|
554 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
555 | // Core |
||
556 | 4 | $oSlideLayout = new SlideLayout($oSlideMaster); |
|
557 | 4 | $oSlideLayout->setRelsIndex('ppt/slideLayouts/_rels/' . $baseFile . '.rels'); |
|
558 | |||
559 | // Name |
||
560 | 4 | $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld'); |
|
561 | 4 | if ($oElement instanceof \DOMElement && $oElement->hasAttribute('name')) { |
|
562 | 4 | $oSlideLayout->setLayoutName($oElement->getAttribute('name')); |
|
563 | } |
||
564 | |||
565 | // Background |
||
566 | 4 | $oElement = $xmlReader->getElement('/p:sldLayout/p:cSld/p:bg'); |
|
567 | 4 | if ($oElement instanceof \DOMElement) { |
|
568 | 1 | $this->loadSlideBackground($xmlReader, $oElement, $oSlideLayout); |
|
569 | } |
||
570 | |||
571 | // ColorMapping |
||
572 | 4 | $oElement = $xmlReader->getElement('/p:sldLayout/p:clrMapOvr/a:overrideClrMapping'); |
|
573 | 4 | if ($oElement instanceof \DOMElement && $oElement->hasAttributes()) { |
|
574 | 1 | $colorMap = array(); |
|
575 | 1 | foreach ($oElement->attributes as $attr) { |
|
576 | 1 | $colorMap[$attr->nodeName] = $attr->nodeValue; |
|
577 | } |
||
578 | 1 | $oSlideLayout->colorMap->setMapping($colorMap); |
|
579 | } |
||
580 | |||
581 | // Shapes |
||
582 | 4 | $oElements = $xmlReader->getElements('/p:sldLayout/p:cSld/p:spTree/*'); |
|
583 | 4 | if ($oElements) { |
|
584 | 4 | $this->loadSlideShapes($oSlideLayout, $oElements, $xmlReader); |
|
585 | } |
||
586 | 4 | $this->arraySlideLayouts[$baseFile] = &$oSlideLayout; |
|
587 | 4 | return $oSlideLayout; |
|
588 | } |
||
589 | return null; |
||
590 | } |
||
591 | |||
592 | /** |
||
593 | * @param string $sPart |
||
594 | * @param SlideMaster $oSlideMaster |
||
595 | */ |
||
596 | 4 | protected function loadTheme($sPart, SlideMaster $oSlideMaster) |
|
597 | { |
||
598 | 4 | $xmlReader = new XMLReader(); |
|
599 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
600 | 4 | $oElements = $xmlReader->getElements('/a:theme/a:themeElements/a:clrScheme/*'); |
|
601 | 4 | if ($oElements) { |
|
602 | 4 | foreach ($oElements as $oElement) { |
|
603 | 4 | $oSchemeColor = new SchemeColor(); |
|
604 | 4 | $oSchemeColor->setValue(str_replace('a:', '', $oElement->tagName)); |
|
605 | 4 | $colorElement = $xmlReader->getElement('*', $oElement); |
|
606 | 4 | if ($colorElement instanceof \DOMElement) { |
|
607 | 4 | if ($colorElement->hasAttribute('lastClr')) { |
|
608 | 4 | $oSchemeColor->setRGB($colorElement->getAttribute('lastClr')); |
|
609 | 4 | } elseif ($colorElement->hasAttribute('val')) { |
|
610 | 4 | $oSchemeColor->setRGB($colorElement->getAttribute('val')); |
|
611 | } |
||
612 | } |
||
613 | 4 | $oSlideMaster->addSchemeColor($oSchemeColor); |
|
614 | } |
||
615 | } |
||
616 | } |
||
617 | 4 | } |
|
618 | |||
619 | /** |
||
620 | * @param XMLReader $xmlReader |
||
621 | * @param \DOMElement $oElement |
||
622 | * @param AbstractSlide $oSlide |
||
623 | */ |
||
624 | 4 | protected function loadSlideBackground(XMLReader $xmlReader, \DOMElement $oElement, AbstractSlide $oSlide) |
|
625 | { |
||
626 | // Background color |
||
627 | 4 | $oElementColor = $xmlReader->getElement('p:bgPr/a:solidFill/a:srgbClr', $oElement); |
|
628 | 4 | if ($oElementColor instanceof \DOMElement) { |
|
629 | // Color |
||
630 | $oColor = new Color(); |
||
631 | $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null); |
||
632 | // Background |
||
633 | $oBackground = new Slide\Background\Color(); |
||
634 | $oBackground->setColor($oColor); |
||
635 | // Slide Background |
||
636 | $oSlide->setBackground($oBackground); |
||
637 | } |
||
638 | |||
639 | // Background scheme color |
||
640 | 4 | $oElementSchemeColor = $xmlReader->getElement('p:bgRef/a:schemeClr', $oElement); |
|
641 | 4 | if ($oElementSchemeColor instanceof \DOMElement) { |
|
642 | // Color |
||
643 | 4 | $oColor = new SchemeColor(); |
|
644 | 4 | $oColor->setValue($oElementSchemeColor->hasAttribute('val') ? $oElementSchemeColor->getAttribute('val') : null); |
|
645 | // Background |
||
646 | 4 | $oBackground = new Slide\Background\SchemeColor(); |
|
647 | 4 | $oBackground->setSchemeColor($oColor); |
|
648 | // Slide Background |
||
649 | 4 | $oSlide->setBackground($oBackground); |
|
650 | } |
||
651 | |||
652 | // Background image |
||
653 | 4 | $oElementImage = $xmlReader->getElement('p:bgPr/a:blipFill/a:blip', $oElement); |
|
654 | 4 | if ($oElementImage instanceof \DOMElement) { |
|
655 | $relImg = $this->arrayRels[$oSlide->getRelsIndex()][$oElementImage->getAttribute('r:embed')]; |
||
656 | if (is_array($relImg)) { |
||
657 | // File |
||
658 | $pathImage = 'ppt/slides/' . $relImg['Target']; |
||
659 | $pathImage = explode('/', $pathImage); |
||
660 | foreach ($pathImage as $key => $partPath) { |
||
661 | if ($partPath == '..') { |
||
662 | unset($pathImage[$key - 1]); |
||
663 | unset($pathImage[$key]); |
||
664 | } |
||
665 | } |
||
666 | $pathImage = implode('/', $pathImage); |
||
667 | $contentImg = $this->oZip->getFromName($pathImage); |
||
668 | |||
669 | $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg'); |
||
670 | file_put_contents($tmpBkgImg, $contentImg); |
||
671 | // Background |
||
672 | $oBackground = new Slide\Background\Image(); |
||
673 | $oBackground->setPath($tmpBkgImg); |
||
674 | // Slide Background |
||
675 | $oSlide->setBackground($oBackground); |
||
676 | } |
||
677 | } |
||
678 | 4 | } |
|
679 | |||
680 | /** |
||
681 | * @param string $baseFile |
||
682 | * @param Slide $oSlide |
||
683 | */ |
||
684 | protected function loadSlideNote($baseFile, Slide $oSlide) |
||
685 | { |
||
686 | $sPart = $this->oZip->getFromName('ppt/notesSlides/' . $baseFile); |
||
687 | $xmlReader = new XMLReader(); |
||
688 | if ($xmlReader->getDomFromString($sPart)) { |
||
689 | $oNote = $oSlide->getNote(); |
||
690 | |||
691 | $arrayElements = $xmlReader->getElements('/p:notes/p:cSld/p:spTree/*'); |
||
692 | if ($arrayElements) { |
||
693 | $this->loadSlideShapes($oNote, $arrayElements, $xmlReader); |
||
694 | } |
||
695 | } |
||
696 | } |
||
697 | |||
698 | /** |
||
699 | * @param XMLReader $document |
||
700 | * @param \DOMElement $node |
||
701 | * @param AbstractSlide $oSlide |
||
702 | */ |
||
703 | 3 | protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide) |
|
704 | { |
||
705 | // Core |
||
706 | 3 | $oShape = new Gd(); |
|
707 | 3 | $oShape->getShadow()->setVisible(false); |
|
708 | // Variables |
||
709 | 3 | $fileRels = $oSlide->getRelsIndex(); |
|
710 | |||
711 | 3 | $oElement = $document->getElement('p:nvPicPr/p:cNvPr', $node); |
|
712 | 3 | if ($oElement instanceof \DOMElement) { |
|
713 | 3 | $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : ''); |
|
714 | 3 | $oShape->setDescription($oElement->hasAttribute('descr') ? $oElement->getAttribute('descr') : ''); |
|
715 | } |
||
716 | |||
717 | 3 | $oElement = $document->getElement('p:blipFill/a:blip', $node); |
|
718 | 3 | if ($oElement instanceof \DOMElement) { |
|
719 | 3 | if ($oElement->hasAttribute('r:embed') && isset($this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'])) { |
|
720 | 3 | $pathImage = 'ppt/slides/' . $this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target']; |
|
721 | 3 | $pathImage = explode('/', $pathImage); |
|
722 | 3 | foreach ($pathImage as $key => $partPath) { |
|
723 | 3 | if ($partPath == '..') { |
|
724 | 3 | unset($pathImage[$key - 1]); |
|
725 | 3 | unset($pathImage[$key]); |
|
726 | } |
||
727 | } |
||
728 | 3 | $pathImage = implode('/', $pathImage); |
|
729 | 3 | $imageFile = $this->oZip->getFromName($pathImage); |
|
730 | 3 | if (!empty($imageFile)) { |
|
731 | 3 | $oShape->setImageResource(imagecreatefromstring($imageFile)); |
|
732 | } |
||
733 | } |
||
734 | } |
||
735 | |||
736 | 3 | $oElement = $document->getElement('p:spPr/a:xfrm', $node); |
|
737 | 3 | if ($oElement instanceof \DOMElement) { |
|
738 | 3 | if ($oElement->hasAttribute('rot')) { |
|
739 | 3 | $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot'))); |
|
740 | } |
||
741 | } |
||
742 | |||
743 | 3 | $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node); |
|
744 | 3 | if ($oElement instanceof \DOMElement) { |
|
745 | 3 | if ($oElement->hasAttribute('x')) { |
|
746 | 3 | $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x'))); |
|
747 | } |
||
748 | 3 | if ($oElement->hasAttribute('y')) { |
|
749 | 3 | $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y'))); |
|
750 | } |
||
751 | } |
||
752 | |||
753 | 3 | $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node); |
|
754 | 3 | if ($oElement instanceof \DOMElement) { |
|
755 | 3 | if ($oElement->hasAttribute('cx')) { |
|
756 | 3 | $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx'))); |
|
757 | } |
||
758 | 3 | if ($oElement->hasAttribute('cy')) { |
|
759 | 3 | $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy'))); |
|
760 | } |
||
761 | } |
||
762 | |||
763 | 3 | $oElement = $document->getElement('p:spPr/a:effectLst', $node); |
|
764 | 3 | if ($oElement instanceof \DOMElement) { |
|
765 | 3 | $oShape->getShadow()->setVisible(true); |
|
766 | |||
767 | 3 | $oSubElement = $document->getElement('a:outerShdw', $oElement); |
|
768 | 3 | if ($oSubElement instanceof \DOMElement) { |
|
769 | 3 | if ($oSubElement->hasAttribute('blurRad')) { |
|
770 | 3 | $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels($oSubElement->getAttribute('blurRad'))); |
|
771 | } |
||
772 | 3 | if ($oSubElement->hasAttribute('dist')) { |
|
773 | 3 | $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels($oSubElement->getAttribute('dist'))); |
|
774 | } |
||
775 | 3 | if ($oSubElement->hasAttribute('dir')) { |
|
776 | 3 | $oShape->getShadow()->setDirection(CommonDrawing::angleToDegrees($oSubElement->getAttribute('dir'))); |
|
777 | } |
||
778 | 3 | if ($oSubElement->hasAttribute('algn')) { |
|
779 | 3 | $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn')); |
|
780 | } |
||
781 | } |
||
782 | |||
783 | 3 | $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement); |
|
784 | 3 | if ($oSubElement instanceof \DOMElement) { |
|
785 | 3 | if ($oSubElement->hasAttribute('val')) { |
|
786 | 3 | $oColor = new Color(); |
|
787 | 3 | $oColor->setRGB($oSubElement->getAttribute('val')); |
|
788 | 3 | $oShape->getShadow()->setColor($oColor); |
|
789 | } |
||
790 | } |
||
791 | |||
792 | 3 | $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement); |
|
793 | 3 | if ($oSubElement instanceof \DOMElement) { |
|
794 | 3 | if ($oSubElement->hasAttribute('val')) { |
|
795 | 3 | $oShape->getShadow()->setAlpha((int)$oSubElement->getAttribute('val') / 1000); |
|
796 | } |
||
797 | } |
||
798 | } |
||
799 | |||
800 | 3 | $oSlide->addShape($oShape); |
|
801 | 3 | } |
|
802 | |||
803 | /** |
||
804 | * @param XMLReader $document |
||
805 | * @param \DOMElement $node |
||
806 | * @param AbstractSlide $oSlide |
||
807 | * @throws \Exception |
||
808 | */ |
||
809 | 4 | protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $oSlide) |
|
810 | { |
||
811 | 4 | if (!$document->elementExists('p:txBody/a:p/a:r', $node)) { |
|
812 | 4 | return; |
|
813 | } |
||
814 | // Core |
||
815 | 4 | $oShape = $oSlide->createRichTextShape(); |
|
816 | 4 | $oShape->setParagraphs(array()); |
|
817 | // Variables |
||
818 | 4 | if ($oSlide instanceof AbstractSlide) { |
|
819 | 4 | $this->fileRels = $oSlide->getRelsIndex(); |
|
820 | } |
||
821 | |||
822 | 4 | $oElement = $document->getElement('p:spPr/a:xfrm', $node); |
|
823 | 4 | if ($oElement instanceof \DOMElement && $oElement->hasAttribute('rot')) { |
|
824 | 4 | $oShape->setRotation(CommonDrawing::angleToDegrees($oElement->getAttribute('rot'))); |
|
825 | } |
||
826 | |||
827 | 4 | $oElement = $document->getElement('p:spPr/a:xfrm/a:off', $node); |
|
828 | 4 | if ($oElement instanceof \DOMElement) { |
|
829 | 4 | if ($oElement->hasAttribute('x')) { |
|
830 | 4 | $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x'))); |
|
831 | } |
||
832 | 4 | if ($oElement->hasAttribute('y')) { |
|
833 | 4 | $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y'))); |
|
834 | } |
||
835 | } |
||
836 | |||
837 | 4 | $oElement = $document->getElement('p:spPr/a:xfrm/a:ext', $node); |
|
838 | 4 | if ($oElement instanceof \DOMElement) { |
|
839 | 4 | if ($oElement->hasAttribute('cx')) { |
|
840 | 4 | $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx'))); |
|
841 | } |
||
842 | 4 | if ($oElement->hasAttribute('cy')) { |
|
843 | 4 | $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy'))); |
|
844 | } |
||
845 | } |
||
846 | |||
847 | 4 | $oElement = $document->getElement('p:nvSpPr/p:nvPr/p:ph', $node); |
|
848 | 4 | if ($oElement instanceof \DOMElement) { |
|
849 | 4 | if ($oElement->hasAttribute('type')) { |
|
850 | 4 | $placeholder = new Placeholder($oElement->getAttribute('type')); |
|
851 | 4 | $oShape->setPlaceHolder($placeholder); |
|
852 | } |
||
853 | } |
||
854 | |||
855 | 4 | $arrayElements = $document->getElements('p:txBody/a:p', $node); |
|
856 | 4 | foreach ($arrayElements as $oElement) { |
|
857 | 4 | $this->loadParagraph($document, $oElement, $oShape); |
|
858 | } |
||
859 | |||
860 | 4 | if (count($oShape->getParagraphs()) > 0) { |
|
861 | 4 | $oShape->setActiveParagraph(0); |
|
862 | } |
||
863 | 4 | } |
|
864 | |||
865 | /** |
||
866 | * @param XMLReader $document |
||
867 | * @param \DOMElement $node |
||
868 | * @param AbstractSlide $oSlide |
||
869 | * @throws \Exception |
||
870 | */ |
||
871 | protected function loadShapeTable(XMLReader $document, \DOMElement $node, AbstractSlide $oSlide) |
||
872 | { |
||
873 | $this->fileRels = $oSlide->getRelsIndex(); |
||
874 | |||
875 | $oShape = $oSlide->createTableShape(); |
||
876 | |||
877 | $oElement = $document->getElement('p:cNvPr', $node); |
||
878 | if ($oElement instanceof \DOMElement) { |
||
879 | if ($oElement->hasAttribute('name')) { |
||
880 | $oShape->setName($oElement->getAttribute('name')); |
||
881 | } |
||
882 | if ($oElement->hasAttribute('descr')) { |
||
883 | $oShape->setDescription($oElement->getAttribute('descr')); |
||
884 | } |
||
885 | } |
||
886 | |||
887 | $oElement = $document->getElement('p:xfrm/a:off', $node); |
||
888 | if ($oElement instanceof \DOMElement) { |
||
889 | if ($oElement->hasAttribute('x')) { |
||
890 | $oShape->setOffsetX(CommonDrawing::emuToPixels($oElement->getAttribute('x'))); |
||
891 | } |
||
892 | if ($oElement->hasAttribute('y')) { |
||
893 | $oShape->setOffsetY(CommonDrawing::emuToPixels($oElement->getAttribute('y'))); |
||
894 | } |
||
895 | } |
||
896 | |||
897 | $oElement = $document->getElement('p:xfrm/a:ext', $node); |
||
898 | if ($oElement instanceof \DOMElement) { |
||
899 | if ($oElement->hasAttribute('cx')) { |
||
900 | $oShape->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('cx'))); |
||
901 | } |
||
902 | if ($oElement->hasAttribute('cy')) { |
||
903 | $oShape->setHeight(CommonDrawing::emuToPixels($oElement->getAttribute('cy'))); |
||
904 | } |
||
905 | } |
||
906 | |||
907 | $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tblGrid/a:gridCol', $node); |
||
908 | $oShape->setNumColumns($arrayElements->length); |
||
909 | $oShape->createRow(); |
||
910 | foreach ($arrayElements as $key => $oElement) { |
||
911 | if ($oElement instanceof \DOMElement && $oElement->getAttribute('w')) { |
||
912 | $oShape->getRow(0)->getCell($key)->setWidth(CommonDrawing::emuToPixels($oElement->getAttribute('w'))); |
||
913 | } |
||
914 | } |
||
915 | |||
916 | $arrayElements = $document->getElements('a:graphic/a:graphicData/a:tbl/a:tr', $node); |
||
917 | foreach ($arrayElements as $keyRow => $oElementRow) { |
||
918 | if (!($oElementRow instanceof \DOMElement)) { |
||
919 | continue; |
||
920 | } |
||
921 | $oRow = $oShape->getRow($keyRow, true); |
||
922 | if (is_null($oRow)) { |
||
923 | $oRow = $oShape->createRow(); |
||
924 | } |
||
925 | if ($oElementRow->hasAttribute('h')) { |
||
926 | $oRow->setHeight(CommonDrawing::emuToPixels($oElementRow->getAttribute('h'))); |
||
927 | } |
||
928 | $arrayElementsCell = $document->getElements('a:tc', $oElementRow); |
||
929 | foreach ($arrayElementsCell as $keyCell => $oElementCell) { |
||
930 | if (!($oElementCell instanceof \DOMElement)) { |
||
931 | continue; |
||
932 | } |
||
933 | $oCell = $oRow->getCell($keyCell); |
||
934 | $oCell->setParagraphs(array()); |
||
935 | if ($oElementCell->hasAttribute('gridSpan')) { |
||
936 | $oCell->setColSpan($oElementCell->getAttribute('gridSpan')); |
||
937 | } |
||
938 | if ($oElementCell->hasAttribute('rowSpan')) { |
||
939 | $oCell->setRowSpan($oElementCell->getAttribute('rowSpan')); |
||
940 | } |
||
941 | |||
942 | foreach ($document->getElements('a:txBody/a:p', $oElementCell) as $oElementPara) { |
||
943 | $this->loadParagraph($document, $oElementPara, $oCell); |
||
944 | } |
||
945 | |||
946 | $oElementTcPr = $document->getElement('a:tcPr', $oElementCell); |
||
947 | if ($oElementTcPr instanceof \DOMElement) { |
||
948 | $numParagraphs = count($oCell->getParagraphs()); |
||
949 | if ($numParagraphs > 0) { |
||
950 | if ($oElementTcPr->hasAttribute('vert')) { |
||
951 | $oCell->getParagraph(0)->getAlignment()->setTextDirection($oElementTcPr->getAttribute('vert')); |
||
952 | } |
||
953 | if ($oElementTcPr->hasAttribute('anchor')) { |
||
954 | $oCell->getParagraph(0)->getAlignment()->setVertical($oElementTcPr->getAttribute('anchor')); |
||
955 | } |
||
956 | if ($oElementTcPr->hasAttribute('marB')) { |
||
957 | $oCell->getParagraph(0)->getAlignment()->setMarginBottom($oElementTcPr->getAttribute('marB')); |
||
958 | } |
||
959 | if ($oElementTcPr->hasAttribute('marL')) { |
||
960 | $oCell->getParagraph(0)->getAlignment()->setMarginLeft($oElementTcPr->getAttribute('marL')); |
||
961 | } |
||
962 | if ($oElementTcPr->hasAttribute('marR')) { |
||
963 | $oCell->getParagraph(0)->getAlignment()->setMarginRight($oElementTcPr->getAttribute('marR')); |
||
964 | } |
||
965 | if ($oElementTcPr->hasAttribute('marT')) { |
||
966 | $oCell->getParagraph(0)->getAlignment()->setMarginTop($oElementTcPr->getAttribute('marT')); |
||
967 | } |
||
968 | } |
||
969 | |||
970 | $oFill = $this->loadStyleFill($document, $oElementTcPr); |
||
971 | if ($oFill instanceof Fill) { |
||
972 | $oCell->setFill($oFill); |
||
973 | } |
||
974 | |||
975 | $oBorders = new Borders(); |
||
976 | $oElementBorderL = $document->getElement('a:lnL', $oElementTcPr); |
||
977 | if ($oElementBorderL instanceof \DOMElement) { |
||
978 | $this->loadStyleBorder($document, $oElementBorderL, $oBorders->getLeft()); |
||
979 | } |
||
980 | $oElementBorderR = $document->getElement('a:lnR', $oElementTcPr); |
||
981 | if ($oElementBorderR instanceof \DOMElement) { |
||
982 | $this->loadStyleBorder($document, $oElementBorderR, $oBorders->getRight()); |
||
983 | } |
||
984 | $oElementBorderT = $document->getElement('a:lnT', $oElementTcPr); |
||
985 | if ($oElementBorderT instanceof \DOMElement) { |
||
986 | $this->loadStyleBorder($document, $oElementBorderT, $oBorders->getTop()); |
||
987 | } |
||
988 | $oElementBorderB = $document->getElement('a:lnB', $oElementTcPr); |
||
989 | if ($oElementBorderB instanceof \DOMElement) { |
||
990 | $this->loadStyleBorder($document, $oElementBorderB, $oBorders->getBottom()); |
||
991 | } |
||
992 | $oElementBorderDiagDown = $document->getElement('a:lnTlToBr', $oElementTcPr); |
||
993 | if ($oElementBorderDiagDown instanceof \DOMElement) { |
||
994 | $this->loadStyleBorder($document, $oElementBorderDiagDown, $oBorders->getDiagonalDown()); |
||
995 | } |
||
996 | $oElementBorderDiagUp = $document->getElement('a:lnBlToTr', $oElementTcPr); |
||
997 | if ($oElementBorderDiagUp instanceof \DOMElement) { |
||
998 | $this->loadStyleBorder($document, $oElementBorderDiagUp, $oBorders->getDiagonalUp()); |
||
999 | } |
||
1000 | $oCell->setBorders($oBorders); |
||
1001 | } |
||
1002 | } |
||
1003 | } |
||
1004 | } |
||
1005 | |||
1006 | /** |
||
1007 | * @param XMLReader $document |
||
1008 | * @param \DOMElement $oElement |
||
1009 | * @param Cell|RichText $oShape |
||
1010 | * @throws \Exception |
||
1011 | */ |
||
1012 | 4 | protected function loadParagraph(XMLReader $document, \DOMElement $oElement, $oShape) |
|
1013 | { |
||
1014 | // Core |
||
1015 | 4 | $oParagraph = $oShape->createParagraph(); |
|
1016 | 4 | $oParagraph->setRichTextElements(array()); |
|
1017 | |||
1018 | 4 | $oSubElement = $document->getElement('a:pPr', $oElement); |
|
1019 | 4 | if ($oSubElement instanceof \DOMElement) { |
|
1020 | 4 | if ($oSubElement->hasAttribute('algn')) { |
|
1021 | 3 | $oParagraph->getAlignment()->setHorizontal($oSubElement->getAttribute('algn')); |
|
1022 | } |
||
1023 | 4 | if ($oSubElement->hasAttribute('fontAlgn')) { |
|
1024 | 3 | $oParagraph->getAlignment()->setVertical($oSubElement->getAttribute('fontAlgn')); |
|
1025 | } |
||
1026 | 4 | if ($oSubElement->hasAttribute('marL')) { |
|
1027 | 3 | $oParagraph->getAlignment()->setMarginLeft(CommonDrawing::emuToPixels($oSubElement->getAttribute('marL'))); |
|
1028 | } |
||
1029 | 4 | if ($oSubElement->hasAttribute('marR')) { |
|
1030 | 3 | $oParagraph->getAlignment()->setMarginRight(CommonDrawing::emuToPixels($oSubElement->getAttribute('marR'))); |
|
1031 | } |
||
1032 | 4 | if ($oSubElement->hasAttribute('indent')) { |
|
1033 | 3 | $oParagraph->getAlignment()->setIndent(CommonDrawing::emuToPixels($oSubElement->getAttribute('indent'))); |
|
1034 | } |
||
1035 | 4 | if ($oSubElement->hasAttribute('lvl')) { |
|
1036 | 4 | $oParagraph->getAlignment()->setLevel($oSubElement->getAttribute('lvl')); |
|
1037 | } |
||
1038 | |||
1039 | 4 | $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NONE); |
|
1040 | |||
1041 | 4 | $oElementBuFont = $document->getElement('a:buFont', $oSubElement); |
|
1042 | 4 | if ($oElementBuFont instanceof \DOMElement) { |
|
1043 | 3 | if ($oElementBuFont->hasAttribute('typeface')) { |
|
1044 | 3 | $oParagraph->getBulletStyle()->setBulletFont($oElementBuFont->getAttribute('typeface')); |
|
1045 | } |
||
1046 | } |
||
1047 | 4 | $oElementBuChar = $document->getElement('a:buChar', $oSubElement); |
|
1048 | 4 | if ($oElementBuChar instanceof \DOMElement) { |
|
1049 | 3 | $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET); |
|
1050 | 3 | if ($oElementBuChar->hasAttribute('char')) { |
|
1051 | 3 | $oParagraph->getBulletStyle()->setBulletChar($oElementBuChar->getAttribute('char')); |
|
1052 | } |
||
1053 | } |
||
1054 | 4 | $oElementBuAutoNum = $document->getElement('a:buAutoNum', $oSubElement); |
|
1055 | 4 | if ($oElementBuAutoNum instanceof \DOMElement) { |
|
1056 | $oParagraph->getBulletStyle()->setBulletType(Bullet::TYPE_NUMERIC); |
||
1057 | if ($oElementBuAutoNum->hasAttribute('type')) { |
||
1058 | $oParagraph->getBulletStyle()->setBulletNumericStyle($oElementBuAutoNum->getAttribute('type')); |
||
1059 | } |
||
1060 | if ($oElementBuAutoNum->hasAttribute('startAt') && $oElementBuAutoNum->getAttribute('startAt') != 1) { |
||
1061 | $oParagraph->getBulletStyle()->setBulletNumericStartAt($oElementBuAutoNum->getAttribute('startAt')); |
||
1062 | } |
||
1063 | } |
||
1064 | 4 | $oElementBuClr = $document->getElement('a:buClr', $oSubElement); |
|
1065 | 4 | if ($oElementBuClr instanceof \DOMElement) { |
|
1066 | $oColor = new Color(); |
||
1067 | /** |
||
1068 | * @todo Create protected for reading Color |
||
1069 | */ |
||
1070 | $oElementColor = $document->getElement('a:srgbClr', $oElementBuClr); |
||
1071 | if ($oElementColor instanceof \DOMElement) { |
||
1072 | $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null); |
||
1073 | } |
||
1074 | $oParagraph->getBulletStyle()->setBulletColor($oColor); |
||
1075 | } |
||
1076 | } |
||
1077 | 4 | $arraySubElements = $document->getElements('(a:r|a:br)', $oElement); |
|
1078 | 4 | foreach ($arraySubElements as $oSubElement) { |
|
1079 | 4 | if ($oSubElement->tagName == 'a:br') { |
|
1080 | 3 | $oParagraph->createBreak(); |
|
1081 | } |
||
1082 | 4 | if ($oSubElement->tagName == 'a:r') { |
|
1083 | 4 | $oElementrPr = $document->getElement('a:rPr', $oSubElement); |
|
1084 | 4 | if (is_object($oElementrPr)) { |
|
1085 | 4 | $oText = $oParagraph->createTextRun(); |
|
1086 | |||
1087 | 4 | if ($oElementrPr->hasAttribute('b')) { |
|
1088 | 3 | $att = $oElementrPr->getAttribute('b'); |
|
1089 | 3 | $oText->getFont()->setBold($att == 'true' || $att == '1' ? true : false); |
|
1090 | } |
||
1091 | 4 | if ($oElementrPr->hasAttribute('i')) { |
|
1092 | 3 | $att = $oElementrPr->getAttribute('i'); |
|
1093 | 3 | $oText->getFont()->setItalic($att == 'true' || $att == '1' ? true : false); |
|
1094 | } |
||
1095 | 4 | if ($oElementrPr->hasAttribute('strike')) { |
|
0 ignored issues
–
show
|
|||
1096 | 3 | $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike') == 'noStrike' ? false : true); |
|
1097 | } |
||
1098 | 4 | if ($oElementrPr->hasAttribute('sz')) { |
|
1099 | 3 | $oText->getFont()->setSize((int)($oElementrPr->getAttribute('sz') / 100)); |
|
1100 | } |
||
1101 | 4 | if ($oElementrPr->hasAttribute('u')) { |
|
1102 | 3 | $oText->getFont()->setUnderline($oElementrPr->getAttribute('u')); |
|
1103 | } |
||
1104 | // Color |
||
1105 | 4 | $oElementSrgbClr = $document->getElement('a:solidFill/a:srgbClr', $oElementrPr); |
|
1106 | 4 | if (is_object($oElementSrgbClr) && $oElementSrgbClr->hasAttribute('val')) { |
|
1107 | 3 | $oColor = new Color(); |
|
1108 | 3 | $oColor->setRGB($oElementSrgbClr->getAttribute('val')); |
|
1109 | 3 | $oText->getFont()->setColor($oColor); |
|
1110 | } |
||
1111 | // Hyperlink |
||
1112 | 4 | $oElementHlinkClick = $document->getElement('a:hlinkClick', $oElementrPr); |
|
1113 | 4 | if (is_object($oElementHlinkClick)) { |
|
1114 | 3 | if ($oElementHlinkClick->hasAttribute('tooltip')) { |
|
1115 | 3 | $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip')); |
|
1116 | } |
||
1117 | 3 | if ($oElementHlinkClick->hasAttribute('r:id') && isset($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target'])) { |
|
1118 | 3 | $oText->getHyperlink()->setUrl($this->arrayRels[$this->fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']); |
|
1119 | } |
||
1120 | } |
||
1121 | //} else { |
||
1122 | // $oText = $oParagraph->createText(); |
||
1123 | |||
1124 | 4 | $oSubSubElement = $document->getElement('a:t', $oSubElement); |
|
1125 | 4 | $oText->setText($oSubSubElement->nodeValue); |
|
1126 | } |
||
1127 | } |
||
1128 | } |
||
1129 | 4 | } |
|
1130 | |||
1131 | /** |
||
1132 | * @param XMLReader $xmlReader |
||
1133 | * @param \DOMElement $oElement |
||
1134 | * @param Border $oBorder |
||
1135 | */ |
||
1136 | protected function loadStyleBorder(XMLReader $xmlReader, \DOMElement $oElement, Border $oBorder) |
||
1137 | { |
||
1138 | if ($oElement->hasAttribute('w')) { |
||
1139 | $oBorder->setLineWidth($oElement->getAttribute('w') / 12700); |
||
1140 | } |
||
1141 | if ($oElement->hasAttribute('cmpd')) { |
||
1142 | $oBorder->setLineStyle($oElement->getAttribute('cmpd')); |
||
1143 | } |
||
1144 | |||
1145 | $oElementNoFill = $xmlReader->getElement('a:noFill', $oElement); |
||
1146 | if ($oElementNoFill instanceof \DOMElement && $oBorder->getLineStyle() == Border::LINE_SINGLE) { |
||
1147 | $oBorder->setLineStyle(Border::LINE_NONE); |
||
1148 | } |
||
1149 | |||
1150 | $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement); |
||
1151 | if ($oElementColor instanceof \DOMElement) { |
||
1152 | $oBorder->setColor($this->loadStyleColor($xmlReader, $oElementColor)); |
||
1153 | } |
||
1154 | |||
1155 | $oElementDashStyle = $xmlReader->getElement('a:prstDash', $oElement); |
||
1156 | if ($oElementDashStyle instanceof \DOMElement && $oElementDashStyle->hasAttribute('val')) { |
||
1157 | $oBorder->setDashStyle($oElementDashStyle->getAttribute('val')); |
||
1158 | } |
||
1159 | } |
||
1160 | |||
1161 | /** |
||
1162 | * @param XMLReader $xmlReader |
||
1163 | * @param \DOMElement $oElement |
||
1164 | * @return Color |
||
1165 | */ |
||
1166 | protected function loadStyleColor(XMLReader $xmlReader, \DOMElement $oElement) |
||
1167 | { |
||
1168 | $oColor = new Color(); |
||
1169 | $oColor->setRGB($oElement->getAttribute('val')); |
||
1170 | $oElementAlpha = $xmlReader->getElement('a:alpha', $oElement); |
||
1171 | if ($oElementAlpha instanceof \DOMElement && $oElementAlpha->hasAttribute('val')) { |
||
1172 | $alpha = strtoupper(dechex((($oElementAlpha->getAttribute('val') / 1000) / 100) * 255)); |
||
1173 | $oColor->setRGB($oElement->getAttribute('val'), $alpha); |
||
1174 | } |
||
1175 | return $oColor; |
||
1176 | } |
||
1177 | |||
1178 | /** |
||
1179 | * @param XMLReader $xmlReader |
||
1180 | * @param \DOMElement $oElement |
||
1181 | * @return null|Fill |
||
1182 | */ |
||
1183 | protected function loadStyleFill(XMLReader $xmlReader, \DOMElement $oElement) |
||
1184 | { |
||
1185 | // Gradient fill |
||
1186 | $oElementFill = $xmlReader->getElement('a:gradFill', $oElement); |
||
1187 | if ($oElementFill instanceof \DOMElement) { |
||
1188 | $oFill = new Fill(); |
||
1189 | $oFill->setFillType(Fill::FILL_GRADIENT_LINEAR); |
||
1190 | |||
1191 | $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="0"]/a:srgbClr', $oElementFill); |
||
1192 | if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) { |
||
1193 | $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor)); |
||
1194 | } |
||
1195 | |||
1196 | $oElementColor = $xmlReader->getElement('a:gsLst/a:gs[@pos="100000"]/a:srgbClr', $oElementFill); |
||
1197 | if ($oElementColor instanceof \DOMElement && $oElementColor->hasAttribute('val')) { |
||
1198 | $oFill->setEndColor($this->loadStyleColor($xmlReader, $oElementColor)); |
||
1199 | } |
||
1200 | |||
1201 | $oRotation = $xmlReader->getElement('a:lin', $oElementFill); |
||
1202 | if ($oRotation instanceof \DOMElement && $oRotation->hasAttribute('ang')) { |
||
1203 | $oFill->setRotation(CommonDrawing::angleToDegrees($oRotation->getAttribute('ang'))); |
||
1204 | } |
||
1205 | return $oFill; |
||
1206 | } |
||
1207 | |||
1208 | // Solid fill |
||
1209 | $oElementFill = $xmlReader->getElement('a:solidFill', $oElement); |
||
1210 | if ($oElementFill instanceof \DOMElement) { |
||
1211 | $oFill = new Fill(); |
||
1212 | $oFill->setFillType(Fill::FILL_SOLID); |
||
1213 | |||
1214 | $oElementColor = $xmlReader->getElement('a:srgbClr', $oElementFill); |
||
1215 | if ($oElementColor instanceof \DOMElement) { |
||
1216 | $oFill->setStartColor($this->loadStyleColor($xmlReader, $oElementColor)); |
||
1217 | } |
||
1218 | return $oFill; |
||
1219 | } |
||
1220 | return null; |
||
1221 | } |
||
1222 | |||
1223 | /** |
||
1224 | * @param string $fileRels |
||
1225 | * @return string |
||
1226 | */ |
||
1227 | 4 | protected function loadRels($fileRels) |
|
1228 | { |
||
1229 | 4 | $sPart = $this->oZip->getFromName($fileRels); |
|
1230 | 4 | if ($sPart !== false) { |
|
1231 | 4 | $xmlReader = new XMLReader(); |
|
1232 | 4 | if ($xmlReader->getDomFromString($sPart)) { |
|
1233 | 4 | foreach ($xmlReader->getElements('*') as $oNode) { |
|
1234 | 4 | if (!($oNode instanceof \DOMElement)) { |
|
1235 | continue; |
||
1236 | } |
||
1237 | 4 | $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array( |
|
1238 | 4 | 'Target' => $oNode->getAttribute('Target'), |
|
1239 | 4 | 'Type' => $oNode->getAttribute('Type'), |
|
1240 | ); |
||
1241 | } |
||
1242 | } |
||
1243 | } |
||
1244 | 4 | } |
|
1245 | |||
1246 | /** |
||
1247 | * @param $oSlide |
||
1248 | * @param \DOMNodeList $oElements |
||
1249 | * @param XMLReader $xmlReader |
||
1250 | * @internal param $baseFile |
||
1251 | */ |
||
1252 | 4 | protected function loadSlideShapes($oSlide, $oElements, $xmlReader) |
|
1253 | { |
||
1254 | 4 | foreach ($oElements as $oNode) { |
|
1255 | 4 | switch ($oNode->tagName) { |
|
1256 | 4 | case 'p:graphicFrame': |
|
1257 | $this->loadShapeTable($xmlReader, $oNode, $oSlide); |
||
1258 | break; |
||
1259 | 4 | case 'p:pic': |
|
1260 | 3 | $this->loadShapeDrawing($xmlReader, $oNode, $oSlide); |
|
1261 | 3 | break; |
|
1262 | 4 | case 'p:sp': |
|
1263 | 4 | $this->loadShapeRichText($xmlReader, $oNode, $oSlide); |
|
1264 | 4 | break; |
|
1265 | 4 | default: |
|
1266 | //var_export($oNode->tagName); |
||
1267 | } |
||
1268 | } |
||
1269 | 4 | } |
|
1270 | } |
||
1271 |
This check marks calls to methods that do not seem to exist on an object.
This is most likely the result of a method being renamed without all references to it being renamed likewise.