diff --git a/Classes/PHPPowerPoint/Shared/Drawing.php b/Classes/PHPPowerPoint/Shared/Drawing.php index 0ebbb7163..dfc599a81 100644 --- a/Classes/PHPPowerPoint/Shared/Drawing.php +++ b/Classes/PHPPowerPoint/Shared/Drawing.php @@ -83,6 +83,30 @@ public static function pointsToPixels($pValue = 0) { } } + /** + * Convert pixels to centimeters + * + * @param int $pValue Value in pixels + * @return int Value in centimeters + */ + public static function pixelsToCentimeters($pValue = 0) { + return $pValue * 0.028; + } + + /** + * Convert centimeters width to pixels + * + * @param int $pValue Value in centimeters + * @return int Value in pixels + */ + public static function centimetersToPixels($pValue = 0) { + if ($pValue != 0) { + return $pValue * 0.028; + } else { + return 0; + } + } + /** * Convert degrees to angle * diff --git a/Classes/PHPPowerPoint/Writer/ODPresentation.php b/Classes/PHPPowerPoint/Writer/ODPresentation.php new file mode 100644 index 000000000..4514201d5 --- /dev/null +++ b/Classes/PHPPowerPoint/Writer/ODPresentation.php @@ -0,0 +1,278 @@ +setPHPPowerPoint($pPHPPowerPoint); + + // Set up disk caching location + $this->_diskCachingDirectory = './'; + + // Initialise writer parts + $this->_writerParts['content'] = new PHPPowerPoint_Writer_ODPresentation_Content(); + $this->_writerParts['manifest'] = new PHPPowerPoint_Writer_ODPresentation_Manifest(); + $this->_writerParts['meta'] = new PHPPowerPoint_Writer_ODPresentation_Meta(); + $this->_writerParts['mimetype'] = new PHPPowerPoint_Writer_ODPresentation_Mimetype(); + + $this->_writerParts['drawing'] = new PHPPowerPoint_Writer_ODPresentation_Drawing(); + + // Assign parent IWriter + foreach ($this->_writerParts as $writer) { + $writer->setParentWriter($this); + } + + // Set HashTable variables + $this->_drawingHashTable = new PHPPowerPoint_HashTable(); + } + + /** + * Save PHPPowerPoint to file + * + * @param string $pFileName + * @throws Exception + */ + public function save($pFilename = null) + { + if (!is_null($this->_presentation)) { + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam('./', 'phppttmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } + + // Create drawing dictionary + $this->_drawingHashTable->addFromSource($this->getWriterPart('Drawing')->allDrawings($this->_presentation)); + + // Create new ZIP file and open it for writing + $objZip = new ZipArchive(); + + // Try opening the ZIP file + if ($objZip->open($pFilename, ZIPARCHIVE::OVERWRITE) !== true) { + if ($objZip->open($pFilename, ZIPARCHIVE::CREATE) !== true) { + throw new Exception("Could not open " . $pFilename . " for writing."); + } + } + + // Add mimetype to ZIP file + //@todo Not in ZIPARCHIVE::CM_STORE mode + $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->writeMimetype($this->_presentation)); + + // Add content.xml to ZIP file + $objZip->addFromString('content.xml', $this->getWriterPart('content')->writeContent($this->_presentation)); + + // Add meta.xml to ZIP file + $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->writeMeta($this->_presentation)); + + // Add META-INF/manifest.xml + $objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('manifest')->writeManifest($this->_presentation)); + + // Add media + for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) { + if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPPowerPoint_Shape_Drawing) { + $imageContents = null; + $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); + + if (strpos($imagePath, 'zip://') !== false) { + $imagePath = substr($imagePath, 6); + $imagePathSplitted = explode('#', $imagePath); + + $imageZip = new ZipArchive(); + $imageZip->open($imagePathSplitted[0]); + $imageContents = $imageZip->getFromName($imagePathSplitted[1]); + $imageZip->close(); + unset($imageZip); + } else { + $imageContents = file_get_contents($imagePath); + } + + $objZip->addFromString('Pictures/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } else if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPPowerPoint_Shape_MemoryDrawing) { + ob_start(); + call_user_func( + $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(), + $this->getDrawingHashTable()->getByIndex($i)->getImageResource() + ); + $imageContents = ob_get_contents(); + ob_end_clean(); + + $objZip->addFromString('Pictures/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } + } + + // Close file + if ($objZip->close() === false) { + throw new Exception("Could not close zip file $pFilename."); + } + + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + + } else { + throw new Exception("PHPPowerPoint object unassigned."); + } + } + + /** + * Get PHPPowerPoint object + * + * @return PHPPowerPoint + * @throws Exception + */ + public function getPHPPowerPoint() { + if (!is_null($this->_presentation)) { + return $this->_presentation; + } else { + throw new Exception("No PHPPowerPoint assigned."); + } + } + + /** + * Get PHPPowerPoint object + * + * @param PHPPowerPoint $pPHPPowerPoint PHPPowerPoint object + * @throws Exception + * @return PHPPowerPoint_Writer_PowerPoint2007 + */ + public function setPHPPowerPoint(PHPPowerPoint $pPHPPowerPoint = null) { + $this->_presentation = $pPHPPowerPoint; + return $this; + } + + /** + * Get PHPPowerPoint_Worksheet_BaseDrawing HashTable + * + * @return PHPPowerPoint_HashTable + */ + public function getDrawingHashTable() { + return $this->_drawingHashTable; + } + + /** + * Get writer part + * + * @param string $pPartName Writer part name + * @return PHPPowerPoint_Writer_ODPresentation_WriterPart + */ + function getWriterPart($pPartName = '') { + if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { + return $this->_writerParts[strtolower($pPartName)]; + } else { + return null; + } + } + + /** + * Get use disk caching where possible? + * + * @return boolean + */ + public function getUseDiskCaching() { + return $this->_useDiskCaching; + } + + /** + * Set use disk caching where possible? + * + * @param boolean $pValue + * @param string $pDirectory Disk caching directory + * @throws Exception Exception when directory does not exist + * @return PHPPowerPoint_Writer_PowerPoint2007 + */ + public function setUseDiskCaching($pValue = false, $pDirectory = null) { + $this->_useDiskCaching = $pValue; + + if (!is_null($pDirectory)) { + if (is_dir($pDirectory)) { + $this->_diskCachingDirectory = $pDirectory; + } else { + throw new Exception("Directory does not exist: $pDirectory"); + } + } + + return $this; + } + + /** + * Get disk caching directory + * + * @return string + */ + public function getDiskCachingDirectory() { + return $this->_diskCachingDirectory; + } +} \ No newline at end of file diff --git a/Classes/PHPPowerPoint/Writer/ODPresentation/Content.php b/Classes/PHPPowerPoint/Writer/ODPresentation/Content.php new file mode 100644 index 000000000..07d9553d6 --- /dev/null +++ b/Classes/PHPPowerPoint/Writer/ODPresentation/Content.php @@ -0,0 +1,365 @@ +getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPPowerPoint_Shared_XMLWriter(PHPPowerPoint_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPPowerPoint_Shared_XMLWriter(PHPPowerPoint_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8'); + + // office:document-content + $objWriter->startElement('office:document-content'); + $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); + $objWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0'); + $objWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'); + $objWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0'); + $objWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0'); + $objWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0'); + $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); + $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); + $objWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0'); + $objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0'); + $objWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0'); + $objWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0'); + $objWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0'); + $objWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML'); + $objWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0'); + $objWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0'); + $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); + $objWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer'); + $objWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc'); + $objWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events'); + $objWriter->writeAttribute('xmlns:xforms', 'http://www.w3.org/2002/xforms'); + $objWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema'); + $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + $objWriter->writeAttribute('xmlns:smil', 'urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0'); + $objWriter->writeAttribute('xmlns:anim', 'urn:oasis:names:tc:opendocument:xmlns:animation:1.0'); + $objWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report'); + $objWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2'); + $objWriter->writeAttribute('xmlns:rdfa', 'http://docs.oasis-open.org/opendocument/meta/rdfa#'); + $objWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0'); + $objWriter->writeAttribute('office:version', '1.2'); + + // office:automatic-styles + $objWriter->startElement('office:automatic-styles'); + + $slideCount = $pPHPPowerPoint->getSlideCount(); + for ($i = 0; $i < $slideCount; ++$i) { + $pSlide = $pPHPPowerPoint->getSlide($i); + // Images + $shapes = $pSlide->getShapeCollection(); + $shapeId = 0; + foreach ($shapes as $shape) + { + // Increment $shapeId + ++$shapeId; + + // Check type + if ($shape instanceof PHPPowerPoint_Shape_RichText) { + + // style:style + $objWriter->startElement('style:style'); + $objWriter->writeAttribute('style:name', 'gr'.$shapeId); + $objWriter->writeAttribute('style:family', 'graphic'); + $objWriter->writeAttribute('style:parent-style-name', 'standard'); + // style:graphic-properties + $objWriter->startElement('style:graphic-properties'); + $objWriter->writeAttribute('draw:auto-grow-height', 'true'); + $objWriter->writeAttribute('fo:wrap-option', 'wrap'); + + $objWriter->endElement(); + $objWriter->endElement(); + + $paragraphs = $shape->getParagraphs(); + $paragraphId = 0; + foreach ($paragraphs as $paragraph){ + ++$paragraphId; + + // style:style + $objWriter->startElement('style:style'); + $objWriter->writeAttribute('style:name', 'P'.$shapeId.'_'.$paragraphId); + $objWriter->writeAttribute('style:family', 'paragraph'); + // style:paragraph-properties + $objWriter->startElement('style:paragraph-properties'); + switch ($paragraph->getAlignment()->getHorizontal()) { + case PHPPowerPoint_Style_Alignment::HORIZONTAL_LEFT: $objWriter->writeAttribute('fo:text-align', 'left'); break; + case PHPPowerPoint_Style_Alignment::HORIZONTAL_RIGHT: $objWriter->writeAttribute('fo:text-align', 'right'); break; + case PHPPowerPoint_Style_Alignment::HORIZONTAL_CENTER: $objWriter->writeAttribute('fo:text-align', 'center'); break; + case PHPPowerPoint_Style_Alignment::HORIZONTAL_JUSTIFY: $objWriter->writeAttribute('fo:text-align', 'justify'); break; + case PHPPowerPoint_Style_Alignment::HORIZONTAL_DISTRIBUTED: $objWriter->writeAttribute('fo:text-align', 'justify'); break; + default: $objWriter->writeAttribute('fo:text-align', 'left'); break; + } + + $objWriter->endElement(); + $objWriter->endElement(); + + $richtexts = $paragraph->getRichTextElements(); + $richtextId = 0; + foreach ($richtexts as $richtext) { + ++$richtextId; + + $elements = $paragraph->getRichTextElements(); + $elementId = 0; + foreach ($elements as $element) { + // Not a line break + if ($element instanceof PHPPowerPoint_Shape_RichText_Run) { + // style:style + $objWriter->startElement('style:style'); + $objWriter->writeAttribute('style:name', 'T'.$shapeId.'_'.$paragraphId.'_'.$richtextId.'_'.$elementId); + $objWriter->writeAttribute('style:family', 'text'); + // style:text-properties + $objWriter->startElement('style:text-properties'); + $objWriter->writeAttribute('fo:color', '#'.$element->getFont()->getColor()->getRGB()); + $objWriter->writeAttribute('fo:font-family', $element->getFont()->getName()); + $objWriter->writeAttribute('fo:font-size', $element->getFont()->getSize().'pt'); + // @todo : fo:font-style + if($element->getFont()->getBold()){ + $objWriter->writeAttribute('fo:font-weight', 'bold'); + } + // @todo : style:text-underline-style + $objWriter->endElement(); + $objWriter->endElement(); + } + } + } + } + } + if ($shape instanceof PHPPowerPoint_Shape_BaseDrawing) { + if ($shape->getShadow()->getVisible()) { + // style:style + $objWriter->startElement('style:style'); + $objWriter->writeAttribute('style:name', 'gr'.$shapeId); + $objWriter->writeAttribute('style:family', 'graphic'); + $objWriter->writeAttribute('style:parent-style-name', 'standard'); + + // style:graphic-properties + $objWriter->startElement('style:graphic-properties'); + $objWriter->writeAttribute('draw:stroke', 'none'); + $objWriter->writeAttribute('draw:fill', 'none'); + $objWriter->writeAttribute('draw:shadow', 'visible'); + $objWriter->writeAttribute('draw:shadow-color', '#'.$shape->getShadow()->getColor()->getRGB()); + if($shape->getShadow()->getDirection() == 0 || $shape->getShadow()->getDirection() == 360) { + $objWriter->writeAttribute('draw:shadow-offset-x', PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', '0cm'); + } + elseif($shape->getShadow()->getDirection() == 45) { + $objWriter->writeAttribute('draw:shadow-offset-x', PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + } + elseif($shape->getShadow()->getDirection() == 90) { + $objWriter->writeAttribute('draw:shadow-offset-x', '0cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + } + elseif($shape->getShadow()->getDirection() == 135) { + $objWriter->writeAttribute('draw:shadow-offset-x', '-'.PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + } + elseif($shape->getShadow()->getDirection() == 180) { + $objWriter->writeAttribute('draw:shadow-offset-x', '-'.PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', '0cm'); + } + elseif($shape->getShadow()->getDirection() == 225) { + $objWriter->writeAttribute('draw:shadow-offset-x', '-'.PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', '-'.PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + } + elseif($shape->getShadow()->getDirection() == 270) { + $objWriter->writeAttribute('draw:shadow-offset-x', '0cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', '-'.PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + } + elseif($shape->getShadow()->getDirection() == 315) { + $objWriter->writeAttribute('draw:shadow-offset-x', PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + $objWriter->writeAttribute('draw:shadow-offset-y', '-'.PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getShadow()->getDistance()).'cm'); + } + + $objWriter->writeAttribute('draw:shadow-opacity', (100 - $shape->getShadow()->getAlpha()).'%'); + $objWriter->writeAttribute('style:mirror', 'none'); + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + } + } + + $objWriter->endElement(); + + // office:body + $objWriter->startElement('office:body'); + // office:presentation + $objWriter->startElement('office:presentation'); + + // Write slides + $slideCount = $pPHPPowerPoint->getSlideCount(); + for ($i = 0; $i < $slideCount; ++$i) { + $pSlide = $pPHPPowerPoint->getSlide($i); + $objWriter->startElement('draw:page'); + $objWriter->writeAttribute('draw:name', 'page'.$i); + $objWriter->writeAttribute('draw:master-page-name', 'Default'); + + // Images + $shapes = $pSlide->getShapeCollection(); + $shapeId = 0; + foreach ($shapes as $shape) + { + // Increment $shapeId + ++$shapeId; + + // Check type + if ($shape instanceof PHPPowerPoint_Shape_RichText) + { + $this->_writeTxt($objWriter, $shape, $shapeId); + } + /*else if ($shape instanceof PHPPowerPoint_Shape_Table) + { + $this->_writeTable($objWriter, $shape, $shapeId); + } + else if ($shape instanceof PHPPowerPoint_Shape_Line) + { + $this->_writeLineShape($objWriter, $shape, $shapeId); + } + else if ($shape instanceof PHPPowerPoint_Shape_Chart) + { + $this->_writeChart($objWriter, $shape, $shapeId); + } + else*/ if ($shape instanceof PHPPowerPoint_Shape_BaseDrawing) + { + $this->_writePic($objWriter, $shape, $shapeId); + } + } + + + $objWriter->endElement(); + $objWriter->endElement(); + } + + /* + + + + + + */ + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + function _writePic(PHPPowerPoint_Shared_XMLWriter $objWriter = null, PHPPowerPoint_Shape_BaseDrawing $shape = null, $shapeId){ + $objWriter->startElement('draw:frame'); + $objWriter->writeAttribute('draw:name', $shape->getName()); + $objWriter->writeAttribute('svg:width', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getWidth()),3).'cm'); + $objWriter->writeAttribute('svg:height', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getHeight()),3).'cm'); + $objWriter->writeAttribute('svg:x', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getOffsetX()),3).'cm'); + $objWriter->writeAttribute('svg:y', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getOffsetY()),3).'cm'); + if ($shape->getShadow()->getVisible()) { + $objWriter->writeAttribute('draw:style-name', 'gr'.$shapeId); + } + + $objWriter->startElement('draw:image'); + $objWriter->writeAttribute('xlink:href', 'Pictures/'.str_replace(' ', '_', $shape->getIndexedFilename())); + $objWriter->writeAttribute('xlink:type', 'simple'); + $objWriter->writeAttribute('xlink:show', 'embed'); + $objWriter->writeAttribute('xlink:actuate', 'onLoad'); + + $objWriter->writeElement('text:p'); + + $objWriter->endElement(); + + $objWriter->endElement(); + } + + function _writeTxt(PHPPowerPoint_Shared_XMLWriter $objWriter = null, PHPPowerPoint_Shape_RichText $shape = null, $shapeId){ + // draw:custom-shape + $objWriter->startElement('draw:custom-shape'); + $objWriter->writeAttribute('draw:style-name', 'gr'.$shapeId); + $objWriter->writeAttribute('svg:width', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getWidth()),3).'cm'); + $objWriter->writeAttribute('svg:height', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getHeight()),3).'cm'); + $objWriter->writeAttribute('svg:x', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getOffsetX()),3).'cm'); + $objWriter->writeAttribute('svg:y', number_format(PHPPowerPoint_Shared_Drawing::pixelsToCentimeters($shape->getOffsetY()),3).'cm'); + + $paragraphs = $shape->getParagraphs(); + $paragraphId = 0; + foreach ($paragraphs as $paragraph){ + ++$paragraphId; + // text:p + $objWriter->startElement('text:p'); + $objWriter->writeAttribute('text:style-name', 'P'.$shapeId.'_'.$paragraphId); + // Loop trough rich text elements + $richtexts = $paragraph->getRichTextElements(); + $richtextId = 0; + foreach ($richtexts as $richtext) { + + ++$richtextId; + + $elements = $paragraph->getRichTextElements(); + $elementId = 0; + foreach ($elements as $element) { + // Not a line break + if ($element instanceof PHPPowerPoint_Shape_RichText_TextElement || $element instanceof PHPPowerPoint_Shape_RichText_Run) { + // text:span + $objWriter->startElement('text:span'); + if($element instanceof PHPPowerPoint_Shape_RichText_Run){ + $objWriter->writeAttribute('text:style-name', 'T'.$shapeId.'_'.$paragraphId.'_'.$richtextId.'_'.$elementId); + } + $objWriter->text($richtext->getText()); + $objWriter->endElement(); + } + } + } + $objWriter->endElement(); + } + $objWriter->endElement(); + } +} diff --git a/Classes/PHPPowerPoint/Writer/ODPresentation/Drawing.php b/Classes/PHPPowerPoint/Writer/ODPresentation/Drawing.php new file mode 100644 index 000000000..22f0f3c5d --- /dev/null +++ b/Classes/PHPPowerPoint/Writer/ODPresentation/Drawing.php @@ -0,0 +1,66 @@ +getSlideCount(); + for ($i = 0; $i < $slideCount; ++$i) { + // Loop trough images and add to array + $iterator = $pPHPPowerPoint->getSlide($i)->getShapeCollection()->getIterator(); + while ($iterator->valid()) { + if ($iterator->current() instanceof PHPPowerPoint_Shape_BaseDrawing && !($iterator->current() instanceof PHPPowerPoint_Shape_Table)) { + $aDrawings[] = $iterator->current(); + } + + $iterator->next(); + } + } + + return $aDrawings; + } +} diff --git a/Classes/PHPPowerPoint/Writer/ODPresentation/Manifest.php b/Classes/PHPPowerPoint/Writer/ODPresentation/Manifest.php new file mode 100644 index 000000000..43b456d9c --- /dev/null +++ b/Classes/PHPPowerPoint/Writer/ODPresentation/Manifest.php @@ -0,0 +1,126 @@ +getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPPowerPoint_Shared_XMLWriter(PHPPowerPoint_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPPowerPoint_Shared_XMLWriter(PHPPowerPoint_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8'); + + // manifest:manifest + $objWriter->startElement('manifest:manifest'); + $objWriter->writeAttribute('xmlns:manifest', 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0'); + $objWriter->writeAttribute('manifest:version', '1.2'); + + // manifest:file-entry + $objWriter->startElement('manifest:file-entry'); + $objWriter->writeAttribute('manifest:media-type', 'application/vnd.oasis.opendocument.presentation'); + $objWriter->writeAttribute('manifest:version', '1.2'); + $objWriter->writeAttribute('manifest:full-path', '/'); + $objWriter->endElement(); + // manifest:file-entry + $objWriter->startElement('manifest:file-entry'); + $objWriter->writeAttribute('manifest:media-type', 'text/xml'); + $objWriter->writeAttribute('manifest:full-path', 'content.xml'); + $objWriter->endElement(); + // manifest:file-entry + $objWriter->startElement('manifest:file-entry'); + $objWriter->writeAttribute('manifest:media-type', 'text/xml'); + $objWriter->writeAttribute('manifest:full-path', 'meta.xml'); + $objWriter->endElement(); + + for ($i = 0; $i < $this->getParentWriter()->getDrawingHashTable()->count(); ++$i) { + if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPPowerPoint_Shape_Drawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension()); + $mimeType = $this->_getImageMimeType( $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath() ); + + $objWriter->startElement('manifest:file-entry'); + $objWriter->writeAttribute('manifest:media-type', $mimeType); + $objWriter->writeAttribute('manifest:full-path', 'Pictures/' . str_replace(' ', '_', $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getIndexedFilename())); + $objWriter->endElement(); + } else if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPPowerPoint_Shape_MemoryDrawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType()); + $extension = explode('/', $extension); + $extension = $extension[1]; + + $mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType(); + + $objWriter->startElement('manifest:file-entry'); + $objWriter->writeAttribute('manifest:media-type', $mimeType); + $objWriter->writeAttribute('manifest:full-path', 'Pictures/' . str_replace(' ', '_', $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getIndexedFilename())); + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + + /** + * Get image mime type + * + * @param string $pFile Filename + * @return string Mime Type + * @throws Exception + */ + private function _getImageMimeType($pFile = '') + { + if (PHPPowerPoint_Shared_File::file_exists($pFile)) { + $image = getimagesize($pFile); + return image_type_to_mime_type($image[2]); + } else { + throw new Exception("File $pFile does not exist"); + } + } +} diff --git a/Classes/PHPPowerPoint/Writer/ODPresentation/Meta.php b/Classes/PHPPowerPoint/Writer/ODPresentation/Meta.php new file mode 100644 index 000000000..9dddee914 --- /dev/null +++ b/Classes/PHPPowerPoint/Writer/ODPresentation/Meta.php @@ -0,0 +1,105 @@ +getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPPowerPoint_Shared_XMLWriter(PHPPowerPoint_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPPowerPoint_Shared_XMLWriter(PHPPowerPoint_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8'); + + // office:document-meta + $objWriter->startElement('office:document-meta'); + $objWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); + $objWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); + $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $objWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); + $objWriter->writeAttribute('xmlns:presentation', 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0'); + $objWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); + $objWriter->writeAttribute('xmlns:smil', 'urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0'); + $objWriter->writeAttribute('xmlns:anim', 'urn:oasis:names:tc:opendocument:xmlns:animation:1.0'); + $objWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); + $objWriter->writeAttribute('xmlns:officeooo', 'http://openoffice.org/2009/office'); + $objWriter->writeAttribute('xmlns:drawooo', 'http://openoffice.org/2010/draw'); + $objWriter->writeAttribute('office:version', '1.2'); + + // office:meta + $objWriter->startElement('office:meta'); + + // dc:creator + $objWriter->writeElement('dc:creator', $pPHPPowerPoint->getProperties()->getLastModifiedBy()); + // dc:date + $objWriter->writeElement('dc:date', gmdate('Y-m-d\TH:i:s.000' ,$pPHPPowerPoint->getProperties()->getModified())); + // dc:description + $objWriter->writeElement('dc:description', $pPHPPowerPoint->getProperties()->getDescription()); + // dc:subject + $objWriter->writeElement('dc:subject', $pPHPPowerPoint->getProperties()->getSubject()); + // dc:title + $objWriter->writeElement('dc:title', $pPHPPowerPoint->getProperties()->getTitle()); + // meta:creation-date + $objWriter->writeElement('meta:creation-date', gmdate('Y-m-d\TH:i:s.000' ,$pPHPPowerPoint->getProperties()->getCreated())); + // meta:initial-creator + $objWriter->writeElement('meta:initial-creator', $pPHPPowerPoint->getProperties()->getCreator()); + // meta:keyword + $objWriter->writeElement('meta:keyword', $pPHPPowerPoint->getProperties()->getKeywords()); + + // @todo : Where these properties are written ? + // $pPHPPowerPoint->getProperties()->getCategory() + // $pPHPPowerPoint->getProperties()->getCompany() + + $objWriter->endElement(); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + +} diff --git a/Classes/PHPPowerPoint/Writer/ODPresentation/Mimetype.php b/Classes/PHPPowerPoint/Writer/ODPresentation/Mimetype.php new file mode 100644 index 000000000..42d80fd67 --- /dev/null +++ b/Classes/PHPPowerPoint/Writer/ODPresentation/Mimetype.php @@ -0,0 +1,51 @@ +_parentWriter = $pWriter; + } + + /** + * Get parent IWriter object + * + * @return PHPPowerPoint_Writer_IWriter + * @throws Exception + */ + public function getParentWriter() { + if (!is_null($this->_parentWriter)) { + return $this->_parentWriter; + } else { + throw new Exception("No parent PHPPowerPoint_Writer_IWriter assigned."); + } + } +} diff --git a/Tests/01simple.php b/Tests/01simple.php index e223d4848..81cfcbc5f 100644 --- a/Tests/01simple.php +++ b/Tests/01simple.php @@ -84,6 +84,10 @@ $objWriter = PHPPowerPoint_IOFactory::createWriter($objPHPPowerPoint, 'PowerPoint2007'); $objWriter->save(str_replace('.php', '.pptx', __FILE__)); +echo date('H:i:s') . " Write to OpenDocumentPresentation format
"; +$objWriter = PHPPowerPoint_IOFactory::createWriter($objPHPPowerPoint, 'ODPresentation'); +$objWriter->save(str_replace('.php', '.odp', __FILE__)); + // Echo memory peak usage echo date('H:i:s') . " Peak memory usage: " . (memory_get_peak_usage(true) / 1024 / 1024) . " MB\r\n";