diff --git a/.travis_shell_after_success.sh b/.travis_shell_after_success.sh index a88b576e7..d3138a248 100644 --- a/.travis_shell_after_success.sh +++ b/.travis_shell_after_success.sh @@ -5,8 +5,7 @@ echo "TRAVIS_REPO_SLUG: $TRAVIS_REPO_SLUG" echo "TRAVIS_PHP_VERSION: $TRAVIS_PHP_VERSION" echo "TRAVIS_PULL_REQUEST: $TRAVIS_PULL_REQUEST" -##if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPPresentation" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.5" ]; then -if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPPowerPoint" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.5" ]; then +if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPPresentation" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.5" ]; then echo -e "Publishing PHPDoc...\n" @@ -16,8 +15,7 @@ if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPPowerPoint" ] && [ "$TRAVIS_PULL_REQUE cd $HOME git config --global user.email "travis@travis-ci.org" git config --global user.name "travis-ci" - ## git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/PHPOffice/PHPPresentation gh-pages > /dev/null - git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/PHPOffice/PHPPowerPoint gh-pages > /dev/null + git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/PHPOffice/PHPPresentation gh-pages > /dev/null cd gh-pages echo "--DEBUG : Suppression" diff --git a/CHANGELOG.md b/CHANGELOG.md index 91743ab13..1c05729e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,25 @@ # Changelog +## 0.6.0 - 2016-01-24 + +### Bugfix +- Documentation : Fixes in the rename of PHPPowerPoint - @Progi1984 GH-127 +- ODPresentation : Exclude SVM files for reader - @Progi1984 GH-141 +- PowerPoint2007 Writer : Bugfix for opening PPTX on Mac - @thsteinmetz GH-89 + +### Changes +- PhpOffice\PhpPresentation\getProperties has been deprecated for PhpOffice\PhpPresentation\getDocumentProperties - @Progi1984 GH-154 +- PhpOffice\PhpPresentation\setProperties has been deprecated for PhpOffice\PhpPresentation\setDocumentProperties - @Progi1984 GH-154 +- PhpOffice\PhpPowerpoint\Style\Alignment::setLevel can now be defined great than 8 - @Progi1984 GH-141 + +### Features +- ODPresentation Reader/Writer : Name of the slide - @Progi1984 GH-121 +- ODPresentation Reader/Writer : Slide Background Color or Image - @Progi1984 GH-152 +- PowerPoint2007 Reader : Support for Layout Name - @Progi1984 GH-144 +- PowerPoint2007 Reader/Writer : Mark as final - @Progi1984 GH-118 +- PowerPoint2007 Reader/Writer : Set default zoom value for presentation - @Progi1984 GH-122 +- PowerPoint2007 Reader/Writer : Slide Background Color or Image - @Progi1984 GH-152 +- PowerPoint2007 Reader/Writer : Add Properties for allowing loop continuously until 'Esc' - @Progi1984 GH-154 + ## 0.5.0 - 2015-10-08 ### Features diff --git a/README.md b/README.md index e8529f039..c690dce6f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ![PHPPresentation](https://github.com/PHPOffice/PHPPresentation/raw/master/docs/images/PHPPowerPointLogo.png "PHPPresentation") [![Latest Stable Version](https://poser.pugx.org/phpoffice/phppowerpoint/v/stable.png)](https://packagist.org/packages/phpoffice/phppowerpoint) -[![Build Status](https://travis-ci.org/PHPOffice/PHPPowerPoint.svg?branch=master)](https://travis-ci.org/PHPOffice/PHPPowerPoint) +[![Build Status](https://travis-ci.org/PHPOffice/PHPPresentation.svg?branch=master)](https://travis-ci.org/PHPOffice/PHPPresentation) [![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPPowerPoint/badges/quality-score.png?s=b5997ce59ac2816b4514f3a38de9900f6d492c1d)](https://scrutinizer-ci.com/g/PHPOffice/PHPPowerPoint/) [![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PHPPowerPoint/badges/coverage.png?s=742a98745725c562955440edc8d2c39d7ff5ae25)](https://scrutinizer-ci.com/g/PHPOffice/PHPPowerPoint/) [![Total Downloads](https://poser.pugx.org/phpoffice/phppowerpoint/downloads.png)](https://packagist.org/packages/phpoffice/phppowerpoint) @@ -11,7 +11,7 @@ PHPPresentation is a library written in pure PHP that provides a set of classes to write to different presentation file formats, i.e. Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML) or OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF). -PHPPresentation is an open source project licensed under the terms of [LGPL version 3](https://github.com/PHPOffice/PHPPresentation/blob/develop/COPYING.LESSER). PHPPresentation is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPPowerPoint) and [unit testing](http://phpoffice.github.io/PHPPresentation/coverage/develop/). You can learn more about PHPPresentation by reading the [Developers' Documentation](http://phppowerpoint.readthedocs.org/) and the [API Documentation](http://phpoffice.github.io/PHPPresentation/docs/develop/). +PHPPresentation is an open source project licensed under the terms of [LGPL version 3](https://github.com/PHPOffice/PHPPresentation/blob/develop/COPYING.LESSER). PHPPresentation is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPPresentation) and [unit testing](http://phpoffice.github.io/PHPPresentation/coverage/develop/). You can learn more about PHPPresentation by reading the [Developers' Documentation](http://phppowerpoint.readthedocs.org/) and the [API Documentation](http://phpoffice.github.io/PHPPresentation/docs/develop/). Read more about PHPPresentation: @@ -79,7 +79,7 @@ require_once 'src/PhpPresentation/Autoloader.php'; // with Composer require_once 'vendor/autoload.php'; -use PhpOffice\PhpPresentation\PhpPowerpoint; +use PhpOffice\PhpPresentation\PhpPresentation; use PhpOffice\PhpPresentation\IOFactory; use PhpOffice\PhpPresentation\Style\Color; use PhpOffice\PhpPresentation\Style\Alignment; diff --git a/docs/faq.rst b/docs/faq.rst index 81b4bf895..0ab6c4336 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -50,5 +50,5 @@ the verbose class names will need to be updated accordingly. Why PHPPowerPoint become PHPPresentation ? ------------------------------------------ -As `Roman Syroeshko noticed us `__, PowerPoint is a `trademark `__. +As `Roman Syroeshko noticed us `__, PowerPoint is a `trademark `__. For avoiding any problems with Microsoft, we decide to change the name to a more logic name, with our panel of readers/writers. \ No newline at end of file diff --git a/docs/intro.rst b/docs/intro.rst index 1d01c9761..74b5bca5b 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -42,10 +42,16 @@ Writers +---------------------------+----------------------+--------+-------+-------+-------+ | Features | | PPTX | ODP | HTML | PDF | +===========================+======================+========+=======+=======+=======+ +| **Document** | Mark as final | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+ | **Document Properties** | Standard | ✓ | ✓ | | | +---------------------------+----------------------+--------+-------+-------+-------+ | | Custom | | | | | +---------------------------+----------------------+--------+-------+-------+-------+ +| **Slides** | | ✓ | ✓ | | | ++---------------------------+----------------------+--------+-------+-------+-------+ +| | Name | | ✓ | | | ++---------------------------+----------------------+--------+-------+-------+-------+ | **Element Shape** | Image | ✓ | ✓ | | | +---------------------------+----------------------+--------+-------+-------+-------+ | | Hyperlink | ✓ | ✓ | | | @@ -74,10 +80,16 @@ Readers +---------------------------+----------------------+--------+-------+-------+-------+-------+ | Features | | PPTX | ODP | HTML | PDF | PPT | +===========================+======================+========+=======+=======+=======+=======+ +| **Document** | Mark as final | ✓ | | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ | **Document Properties** | Standard | ✓ | ✓ | | | | +---------------------------+----------------------+--------+-------+-------+-------+-------+ | | Custom | | | | | | +---------------------------+----------------------+--------+-------+-------+-------+-------+ +| **Slides** | | ✓ | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ +| | Name | | ✓ | | | | ++---------------------------+----------------------+--------+-------+-------+-------+-------+ | **Element Shape** | Image | ✓ | ✓ | | | ✓ | +---------------------------+----------------------+--------+-------+-------+-------+-------+ | | Hyperlink | ✓ | ✓ | | | ✓ | diff --git a/docs/recipes.rst b/docs/recipes.rst index 6d0b8e171..ec2c604e8 100644 --- a/docs/recipes.rst +++ b/docs/recipes.rst @@ -3,11 +3,49 @@ Recipes ======= -Title ------------------------ +How to define the zoom of a presentation ? +------------------------------------------ -Recipe Text +You must define the zoom of your presentation with the method ``setZoom()`` .. code-block:: php - $content; + // Default + $zoom = $oPHPPresentation->getZoom(); + // $zoom = 1 + + // Without parameter + $oPHPPresentation->setZoom(); + $zoom = $oPHPPresentation->getZoom(); + // $zoom = true + + // Parameter = false + $oPHPPresentation->setZoom(2.8); + $zoom = $oPHPPresentation->getZoom(); + // $zoom = 2.8 + +How to mark a presentation as final ? +------------------------------------- + +You must define your presentation as it with the method ``markAsFinal()`` + +.. code-block:: php + + // Default + $state = $oPHPPresentation->isMarkedAsFinal(); + // $state = false + + // Without parameter + $oPHPPresentation->markAsFinal(); + $state = $oPHPPresentation->isMarkedAsFinal(); + // $state = true + + // Parameter = false + $oPHPPresentation->markAsFinal(false); + $state = $oPHPPresentation->isMarkedAsFinal(); + // $state = false + + // Parameter = true + $oPHPPresentation->markAsFinal(true); + $state = $oPHPPresentation->isMarkedAsFinal(); + // $state = true diff --git a/docs/slides.rst b/docs/slides.rst index 9d7858730..79a9bf4e3 100644 --- a/docs/slides.rst +++ b/docs/slides.rst @@ -4,3 +4,14 @@ Slides ====== Slides are pages in a presentation. Slides are stored as a zero based array in ``PHPPresentation`` object. Use ``createSlide`` to create a new slide and retrieve the slide for other operation such as creating shapes for that slide. + +Name +------- + +By default, a slide has not a name. +You can define it with the method ``setName``. + +.. code-block:: php + + $oSlide = $oPHPPresentation->createSlide(); + $oSlide->setName('Title of the slide'); \ No newline at end of file diff --git a/samples/Sample_13_MarkAsFinal.php b/samples/Sample_13_MarkAsFinal.php new file mode 100644 index 000000000..0556ff0d1 --- /dev/null +++ b/samples/Sample_13_MarkAsFinal.php @@ -0,0 +1,26 @@ +markAsFinal(true); + +// Create slide +echo date('H:i:s') . ' Create slide'.EOL; +$currentSlide = $objPHPPresentation->getActiveSlide(); +$currentSlide->addShape(clone $oShapeDrawing); +$currentSlide->addShape(clone $oShapeRichText); + +// Save file +echo write($objPHPPresentation, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_14_Zoom.php b/samples/Sample_14_Zoom.php new file mode 100644 index 000000000..253b6dc76 --- /dev/null +++ b/samples/Sample_14_Zoom.php @@ -0,0 +1,26 @@ +setZoom(3); + +// Create slide +echo date('H:i:s') . ' Create slide'.EOL; +$currentSlide = $objPHPPresentation->getActiveSlide(); +$currentSlide->addShape(clone $oShapeDrawing); +$currentSlide->addShape(clone $oShapeRichText); + +// Save file +echo write($objPHPPresentation, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_15_Background.php b/samples/Sample_15_Background.php new file mode 100644 index 000000000..7d7c05422 --- /dev/null +++ b/samples/Sample_15_Background.php @@ -0,0 +1,43 @@ +getActiveSlide(); +$oSlide1->addShape(clone $oShapeDrawing); +$oSlide1->addShape(clone $oShapeRichText); + +// Slide > Background > Color +$oBkgColor = new Color(); +$oBkgColor->setColor(new StyleColor(StyleColor::COLOR_DARKGREEN)); +$oSlide1->setBackground($oBkgColor); + +// Create slide +echo date('H:i:s') . ' Create slide'.EOL; +$oSlide2 = $objPHPPresentation->createSlide(); +$oSlide2->addShape(clone $oShapeDrawing); +$oSlide2->addShape(clone $oShapeRichText); + +// Slide > Background > Image +/* + * @link : http://publicdomainarchive.com/public-domain-images-cave-red-rocks-light-beam-cavern/ + */ +$oBkgImage = new Image(); +$oBkgImage->setPath('./resources/background.jpg'); +$oSlide2->setBackground($oBkgImage); + +// Save file +echo write($objPHPPresentation, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 2025141c4..3d42577f0 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -14,7 +14,9 @@ use PhpOffice\PhpPresentation\Shape\RichText; use PhpOffice\PhpPresentation\Shape\RichText\BreakElement; use PhpOffice\PhpPresentation\Shape\RichText\TextElement; +use PhpOffice\PhpPresentation\Style\Alignment; use PhpOffice\PhpPresentation\Style\Bullet; +use PhpOffice\PhpPresentation\Style\Color; error_reporting(E_ALL); define('CLI', (PHP_SAPI == 'cli') ? true : false); @@ -41,6 +43,32 @@ $pageTitle .= 'PHPPresentation'; $pageHeading = IS_INDEX ? '' : "

{$pageHeading}

"; +$oShapeDrawing = new Drawing(); +$oShapeDrawing->setName('PHPPresentation logo') + ->setDescription('PHPPresentation logo') + ->setPath('./resources/phppowerpoint_logo.gif') + ->setHeight(36) + ->setOffsetX(10) + ->setOffsetY(10); +$oShapeDrawing->getShadow()->setVisible(true) + ->setDirection(45) + ->setDistance(10); +$oShapeDrawing->getHyperlink()->setUrl('https://github.com/PHPOffice/PHPPresentation/')->setTooltip('PHPPresentation'); + +// Create a shape (text) +$oShapeRichText = new RichText(); +$oShapeRichText->setHeight(300) + ->setWidth(600) + ->setOffsetX(170) + ->setOffsetY(180); +$oShapeRichText->getActiveParagraph()->getAlignment()->setHorizontal( Alignment::HORIZONTAL_CENTER ); +$textRun = $oShapeRichText->createTextRun('Thank you for using PHPPresentation!'); +$textRun->getFont()->setBold(true) + ->setSize(60) + ->setColor( new Color( 'FFE06B20' ) ); + + + // Populate samples $files = ''; if ($handle = opendir('.')) { @@ -254,6 +282,16 @@ protected function displayPhpPresentationInfo(PhpPresentation $oPHPPpt) $this->append('
Offset Y
'.$oSlide->getOffsetY().'
'); $this->append('
Extent X
'.$oSlide->getExtentX().'
'); $this->append('
Extent Y
'.$oSlide->getExtentY().'
'); + $oBkg = $oSlide->getBackground(); + if ($oBkg instanceof Slide\AbstractBackground) { + if ($oBkg instanceof Slide\Background\Color) { + $this->append('
Background Color
#'.$oBkg->getColor()->getRGB().'
'); + } + if ($oBkg instanceof Slide\Background\Image) { + $sBkgImgContents = file_get_contents($oBkg->getPath()); + $this->append('
Background Image
'); + } + } $this->append(''); $this->append(''); diff --git a/samples/resources/PPTX_MarkAsFinal.pptx b/samples/resources/PPTX_MarkAsFinal.pptx new file mode 100644 index 000000000..b5ba81fb9 Binary files /dev/null and b/samples/resources/PPTX_MarkAsFinal.pptx differ diff --git a/samples/resources/background.jpg b/samples/resources/background.jpg new file mode 100644 index 000000000..063990c86 Binary files /dev/null and b/samples/resources/background.jpg differ diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index ecf747a65..552368ba1 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -404,7 +404,7 @@ public function setHyperlink(Hyperlink $pHyperlink = null) */ public function getHashCode() { - return md5((is_object($this->container)?$this->container->getHashCode():'') . $this->offsetX . $this->offsetY . $this->width . $this->height . $this->rotation . $this->getFill()->getHashCode() . $this->shadow->getHashCode() . (is_null($this->hyperlink) ? '' : $this->hyperlink->getHashCode()) . __CLASS__); + return md5((is_object($this->container)?$this->container->getHashCode():'') . $this->offsetX . $this->offsetY . $this->width . $this->height . $this->rotation . $this->getFill()->getHashCode() . (is_null($this->shadow) ? '' : $this->shadow->getHashCode()) . (is_null($this->hyperlink) ? '' : $this->hyperlink->getHashCode()) . __CLASS__); } /** diff --git a/src/PhpPresentation/PhpPresentation.php b/src/PhpPresentation/PhpPresentation.php index 2e1ed75d2..4a3921866 100644 --- a/src/PhpPresentation/PhpPresentation.php +++ b/src/PhpPresentation/PhpPresentation.php @@ -30,7 +30,14 @@ class PhpPresentation * * @var \PhpOffice\PhpPresentation\DocumentProperties */ - private $properties; + private $documentProperties; + + /** + * Presentation properties + * + * @var \PhpOffice\PhpPresentation\PresentationProperties + */ + private $presentationProperties; /** * Document layout @@ -53,6 +60,18 @@ class PhpPresentation */ private $activeSlideIndex = 0; + /** + * Mark as final + * @var bool + */ + private $markAsFinal = false; + + /** + * Zoom + * @var float + */ + private $zoom = 1; + /** * Create a new PhpPresentation with one Slide */ @@ -63,7 +82,8 @@ public function __construct() $this->setActiveSlideIndex(); // Set initial document properties & layout - $this->setProperties(new DocumentProperties()); + $this->setDocumentProperties(new DocumentProperties()); + $this->setPresentationProperties(new PresentationProperties()); $this->setLayout(new DocumentLayout()); } @@ -71,25 +91,70 @@ public function __construct() * Get properties * * @return \PhpOffice\PhpPresentation\DocumentProperties + * @deprecated for getDocumentProperties */ public function getProperties() { - return $this->properties; + return $this->getDocumentProperties(); } /** * Set properties * * @param \PhpOffice\PhpPresentation\DocumentProperties $value + * @deprecated for setDocumentProperties * @return PhpPresentation */ public function setProperties(DocumentProperties $value) { - $this->properties = $value; + return $this->setDocumentProperties($value); + } + + /** + * Get properties + * + * @return \PhpOffice\PhpPresentation\DocumentProperties + */ + public function getDocumentProperties() + { + return $this->documentProperties; + } + + /** + * Set properties + * + * @param \PhpOffice\PhpPresentation\DocumentProperties $value + * @return PhpPresentation + */ + public function setDocumentProperties(DocumentProperties $value) + { + $this->documentProperties = $value; return $this; } + /** + * Get presentation properties + * + * @return \PhpOffice\PhpPresentation\PresentationProperties + */ + public function getPresentationProperties() + { + return $this->presentationProperties; + } + + /** + * Set presentation properties + * + * @param \PhpOffice\PhpPresentation\PresentationProperties $value + * @return PhpPresentation + */ + public function setPresentationProperties(PresentationProperties $value) + { + $this->presentationProperties = $value; + return $this; + } + /** * Get layout * @@ -291,4 +356,48 @@ public function copy() return $copied; } + + /** + * Mark a document as final + * @param bool $state + * @return PhpPresentation + */ + public function markAsFinal($state = true) + { + if (is_bool($state)) { + $this->markAsFinal = $state; + } + return $this; + } + + /** + * Return if this document is marked as final + * @return bool + */ + public function isMarkedAsFinal() + { + return $this->markAsFinal; + } + + /** + * Set the zoom of the document (in percentage) + * @param float $zoom + * @return PhpPresentation + */ + public function setZoom($zoom = 1) + { + if (is_numeric($zoom)) { + $this->zoom = $zoom; + } + return $this; + } + + /** + * Return the zoom (in percentage) + * @return float + */ + public function getZoom() + { + return $this->zoom; + } } diff --git a/src/PhpPresentation/PresentationProperties.php b/src/PhpPresentation/PresentationProperties.php new file mode 100644 index 000000000..749e370fb --- /dev/null +++ b/src/PhpPresentation/PresentationProperties.php @@ -0,0 +1,46 @@ +isLoopUntilEsc; + } + + /** + * @param bool $value + * @return \PhpOffice\PhpPresentation\PresentationProperties + */ + public function setLoopContinuouslyUntilEsc($value = false) + { + $this->isLoopUntilEsc = $value; + return $this; + } +} diff --git a/src/PhpPresentation/Reader/ODPresentation.php b/src/PhpPresentation/Reader/ODPresentation.php index 996c6258d..56bed465b 100644 --- a/src/PhpPresentation/Reader/ODPresentation.php +++ b/src/PhpPresentation/Reader/ODPresentation.php @@ -52,6 +52,10 @@ class ODPresentation implements ReaderInterface * @var array[] */ protected $arrayStyles = array(); + /** + * @var array[] + */ + protected $arrayCommonStyles = array(); /** * @var \PhpOffice\Common\XMLReader */ @@ -131,6 +135,10 @@ protected function loadFile($pFilename) $this->loadDocumentProperties(); } $this->oXMLReader = new XMLReader(); + if ($this->oXMLReader->getDomFromZip($pFilename, 'styles.xml') !== false) { + $this->loadStylesFile(); + } + $this->oXMLReader = new XMLReader(); if ($this->oXMLReader->getDomFromZip($pFilename, 'content.xml') !== false) { $this->loadSlides(); } @@ -191,7 +199,30 @@ protected function loadSlides() protected function loadStyle(\DOMElement $nodeStyle) { $keyStyle = $nodeStyle->getAttribute('style:name'); - + + $nodeDrawingPageProps = $this->oXMLReader->getElement('style:drawing-page-properties', $nodeStyle); + if ($nodeDrawingPageProps) { + // Read Background Color + if ($nodeDrawingPageProps->hasAttribute('draw:fill-color') && $nodeDrawingPageProps->getAttribute('draw:fill') == 'solid') { + $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Color(); + $oColor = new Color(); + $oColor->setRGB(substr($nodeDrawingPageProps->getAttribute('draw:fill-color'), -6)); + $oBackground->setColor($oColor); + } + // Read Background Image + if ($nodeDrawingPageProps->getAttribute('draw:fill') == 'bitmap' && $nodeDrawingPageProps->hasAttribute('draw:fill-image-name')) { + $nameStyle = $nodeDrawingPageProps->getAttribute('draw:fill-image-name'); + if (!empty($this->arrayCommonStyles[$nameStyle]) && $this->arrayCommonStyles[$nameStyle]['type'] == 'image' && !empty($this->arrayCommonStyles[$nameStyle]['path'])) { + $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderODPBkg'); + $contentImg = $this->oZip->getFromName($this->arrayCommonStyles[$nameStyle]['path']); + file_put_contents($tmpBkgImg, $contentImg); + + $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Image(); + $oBackground->setPath($tmpBkgImg); + } + } + } + $nodeGraphicProps = $this->oXMLReader->getElement('style:graphic-properties', $nodeStyle); if ($nodeGraphicProps) { // Read Shadow @@ -235,6 +266,7 @@ protected function loadStyle(\DOMElement $nodeStyle) $oFont->setSize(substr($nodeTextProperties->getAttribute('fo:font-size'), 0, -2)); } } + $nodeParagraphProps = $this->oXMLReader->getElement('style:paragraph-properties', $nodeStyle); if ($nodeParagraphProps) { $oAlignment = new Alignment(); @@ -284,6 +316,7 @@ protected function loadStyle(\DOMElement $nodeStyle) $this->arrayStyles[$keyStyle] = array( 'alignment' => isset($oAlignment) ? $oAlignment : null, + 'background' => isset($oBackground) ? $oBackground : null, 'font' => isset($oFont) ? $oFont : null, 'shadow' => isset($oShadow) ? $oShadow : null, 'listStyle' => isset($arrayListStyle) ? $arrayListStyle : null, @@ -293,7 +326,8 @@ protected function loadStyle(\DOMElement $nodeStyle) } /** - * Extract data from slide + * Read Slide + * * @param \DOMElement $nodeSlide */ protected function loadSlide(\DOMElement $nodeSlide) @@ -301,6 +335,15 @@ protected function loadSlide(\DOMElement $nodeSlide) // Core $this->oPhpPresentation->createSlide(); $this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1); + if ($nodeSlide->hasAttribute('draw:name')) { + $this->oPhpPresentation->getActiveSlide()->setName($nodeSlide->getAttribute('draw:name')); + } + if ($nodeSlide->hasAttribute('draw:style-name')) { + $keyStyle = $nodeSlide->getAttribute('draw:style-name'); + if (isset($this->arrayStyles[$keyStyle])) { + $this->oPhpPresentation->getActiveSlide()->setBackground($this->arrayStyles[$keyStyle]['background']); + } + } foreach ($this->oXMLReader->getElements('draw:frame', $nodeSlide) as $oNodeFrame) { if ($this->oXMLReader->getElement('draw:image', $oNodeFrame)) { $this->loadShapeDrawing($oNodeFrame); @@ -315,6 +358,7 @@ protected function loadSlide(\DOMElement $nodeSlide) } /** + * Read Shape Drawing * * @param \DOMElement $oNodeFrame */ @@ -327,7 +371,12 @@ protected function loadShapeDrawing(\DOMElement $oNodeFrame) $oNodeImage = $this->oXMLReader->getElement('draw:image', $oNodeFrame); if ($oNodeImage) { if ($oNodeImage->hasAttribute('xlink:href')) { - $imageFile = $this->oZip->getFromName($oNodeImage->getAttribute('xlink:href')); + $sFilename = $oNodeImage->getAttribute('xlink:href'); + // svm = StarView Metafile + if (pathinfo($sFilename, PATHINFO_EXTENSION) == 'svm') { + return; + } + $imageFile = $this->oZip->getFromName($sFilename); if (!empty($imageFile)) { $oShape->setImageResource(imagecreatefromstring($imageFile)); } @@ -354,6 +403,7 @@ protected function loadShapeDrawing(\DOMElement $oNodeFrame) } /** + * Read Shape RichText * * @param \DOMElement $oNodeFrame */ @@ -393,8 +443,13 @@ protected function loadShapeRichText(\DOMElement $oNodeFrame) protected function readParagraph(RichText $oShape, \DOMElement $oNodeParent) { $oParagraph = $oShape->createParagraph(); - foreach ($this->oXMLReader->getElements('text:span', $oNodeParent) as $oNodeRichTextElement) { - $this->readParagraphItem($oParagraph, $oNodeRichTextElement); + $oDomList = $this->oXMLReader->getElements('text:span', $oNodeParent); + if ($oDomList->length == 0) { + $this->readParagraphItem($oParagraph, $oNodeParent); + } else { + foreach ($oDomList as $oNodeRichTextElement) { + $this->readParagraphItem($oParagraph, $oNodeRichTextElement); + } } } @@ -425,7 +480,13 @@ protected function readParagraphItem(Paragraph $oParagraph, \DOMElement $oNodePa } } } - + + /** + * Read List + * + * @param RichText $oShape + * @param \DOMElement $oNodeParent + */ protected function readList(RichText $oShape, \DOMElement $oNodeParent) { foreach ($this->oXMLReader->getElements('text:list-item/*', $oNodeParent) as $oNodeListItem) { @@ -441,7 +502,7 @@ protected function readList(RichText $oShape, \DOMElement $oNodeParent) } /** - * Read Paragraph + * Read List Item * @param RichText $oShape * @param \DOMElement $oNodeParent * @param \DOMElement $oNodeParagraph @@ -460,4 +521,19 @@ protected function readListItem(RichText $oShape, \DOMElement $oNodeParent, \DOM $this->readParagraphItem($oParagraph, $oNodeRichTextElement); } } + + /** + * Load file 'styles.xml' + */ + protected function loadStylesFile() + { + foreach ($this->oXMLReader->getElements('/office:document-styles/office:styles/*') as $oElement) { + if ($oElement->nodeName == 'draw:fill-image') { + $this->arrayCommonStyles[$oElement->getAttribute('draw:name')] = array( + 'type' => 'image', + 'path' => $oElement->hasAttribute('xlink:href') ? $oElement->getAttribute('xlink:href') : null + ); + } + } + } } diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index d36fbb3ef..ffead7ec5 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -21,10 +21,10 @@ use PhpOffice\Common\XMLReader; use PhpOffice\Common\Drawing as CommonDrawing; use PhpOffice\PhpPresentation\PhpPresentation; -use PhpOffice\PhpPresentation\Shape\Hyperlink; use PhpOffice\PhpPresentation\Shape\MemoryDrawing; use PhpOffice\PhpPresentation\Style\Bullet; use PhpOffice\PhpPresentation\Style\Color; +use PhpOffice\PhpPresentation\Writer\PowerPoint2007\LayoutPack\TemplateBased; /** * Serialized format reader @@ -45,6 +45,10 @@ class PowerPoint2007 implements ReaderInterface * @var string[] */ protected $arrayRels = array(); + /* + * @var string + */ + protected $filename; /** * Can the current \PhpOffice\PhpPresentation\Reader\ReaderInterface read the file? @@ -111,14 +115,25 @@ protected function loadFile($pFilename) { $this->oPhpPresentation = new PhpPresentation(); $this->oPhpPresentation->removeSlideByIndex(); + $this->filename = $pFilename; $this->oZip = new ZipArchive(); - $this->oZip->open($pFilename); + $this->oZip->open($this->filename); $docPropsCore = $this->oZip->getFromName('docProps/core.xml'); if ($docPropsCore !== false) { $this->loadDocumentProperties($docPropsCore); } - + + $docPropsCustom = $this->oZip->getFromName('docProps/custom.xml'); + if ($docPropsCustom !== false) { + $this->loadCustomProperties($docPropsCustom); + } + + $pptViewProps = $this->oZip->getFromName('ppt/viewProps.xml'); + if ($pptViewProps !== false) { + $this->loadViewProperties($pptViewProps); + } + $pptPresentation = $this->oZip->getFromName('ppt/presentation.xml'); if ($pptPresentation !== false) { $this->loadSlides($pptPresentation); @@ -160,6 +175,41 @@ protected function loadDocumentProperties($sPart) } } } + + /** + * Read Custom Properties + * @param string $sPart + */ + protected function loadCustomProperties($sPart) + { + $xmlReader = new XMLReader(); + $sPart = str_replace(' xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"', '', $sPart); + if ($xmlReader->getDomFromString($sPart)) { + $pathMarkAsFinal = '/Properties/property[@pid="2"][@fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"][@name="_MarkAsFinal"]/vt:bool'; + if (is_object($oElement = $xmlReader->getElement($pathMarkAsFinal))) { + if ($oElement->nodeValue == 'true') { + $this->oPhpPresentation->markAsFinal(true); + } + } + } + } + + /** + * Read View Properties + * @param string $sPart + */ + protected function loadViewProperties($sPart) + { + $xmlReader = new XMLReader(); + if ($xmlReader->getDomFromString($sPart)) { + $pathZoom = '/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx'; + if (is_object($oElement = $xmlReader->getElement($pathZoom))) { + if ($oElement->hasAttribute('d') && $oElement->hasAttribute('n')) { + $this->oPhpPresentation->setZoom($oElement->getAttribute('n') / $oElement->getAttribute('d')); + } + } + } + } /** * Extract all slides @@ -172,7 +222,7 @@ protected function loadSlides($sPart) $this->loadRels($fileRels); foreach ($xmlReader->getElements('/p:presentation/p:sldIdLst/p:sldId') as $oElement) { $rId = $oElement->getAttribute('r:id'); - $pathSlide = isset($this->arrayRels[$fileRels][$rId]) ? $this->arrayRels[$fileRels][$rId] : ''; + $pathSlide = isset($this->arrayRels[$fileRels][$rId]) ? $this->arrayRels[$fileRels][$rId]['Target'] : ''; if (!empty($pathSlide)) { $pptSlide = $this->oZip->getFromName('ppt/'.$pathSlide); if ($pptSlide !== false) { @@ -196,6 +246,51 @@ protected function loadSlide($sPart, $baseFile) // Core $this->oPhpPresentation->createSlide(); $this->oPhpPresentation->setActiveSlideIndex($this->oPhpPresentation->getSlideCount() - 1); + + // Background + $oElement = $xmlReader->getElement('/p:sld/p:cSld/p:bg/p:bgPr'); + if ($oElement) { + $oElementColor = $xmlReader->getElement('a:solidFill/a:srgbClr', $oElement); + if ($oElementColor) { + // Color + $oColor = new Color(); + $oColor->setRGB($oElementColor->hasAttribute('val') ? $oElementColor->getAttribute('val') : null); + // Background + $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Color(); + $oBackground->setColor($oColor); + // Slide Background + $oSlide = $this->oPhpPresentation->getActiveSlide(); + $oSlide->setBackground($oBackground); + } + $oElementImage = $xmlReader->getElement('a:blipFill/a:blip', $oElement); + if ($oElementImage) { + $relImg = $this->arrayRels['ppt/slides/_rels/'.$baseFile.'.rels'][$oElementImage->getAttribute('r:embed')]; + if (is_array($relImg)) { + // File + $pathImage = 'ppt/slides/'.$relImg['Target']; + $pathImage = explode('/', $pathImage); + foreach ($pathImage as $key => $partPath) { + if ($partPath == '..') { + unset($pathImage[$key - 1]); + unset($pathImage[$key]); + } + } + $pathImage = implode('/', $pathImage); + $contentImg = $this->oZip->getFromName($pathImage); + + $tmpBkgImg = tempnam(sys_get_temp_dir(), 'PhpPresentationReaderPpt2007Bkg'); + file_put_contents($tmpBkgImg, $contentImg); + // Background + $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Image(); + $oBackground->setPath($tmpBkgImg); + // Slide Background + $oSlide = $this->oPhpPresentation->getActiveSlide(); + $oSlide->setBackground($oBackground); + } + } + } + + // Shapes foreach ($xmlReader->getElements('/p:sld/p:cSld/p:spTree/*') as $oNode) { switch ($oNode->tagName) { case 'p:pic': @@ -208,6 +303,19 @@ protected function loadSlide($sPart, $baseFile) //var_export($oNode->tagName); } } + // Layout + $oLayoutPack = new TemplateBased($this->filename); + $oSlide = $this->oPhpPresentation->getActiveSlide(); + foreach ($this->arrayRels['ppt/slides/_rels/'.$baseFile.'.rels'] as $valueRel) { + if ($valueRel['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout') { + $layoutId = $valueRel['Target']; + $layoutId = str_replace('../slideLayouts/slideLayout', '', $layoutId); + $layoutId = str_replace('.xml', '', $layoutId); + $layoutName = $oLayoutPack->findLayoutName((int)$layoutId, $oSlide->getSlideMasterId()); + $oSlide->setSlideLayout($layoutName); + break; + } + } } } @@ -233,8 +341,8 @@ protected function loadShapeDrawing(XMLReader $document, \DOMElement $node, $bas $oElement = $document->getElement('p:blipFill/a:blip', $node); if ($oElement) { - if ($oElement->hasAttribute('r:embed') && isset($this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')])) { - $pathImage = 'ppt/slides/'.$this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]; + if ($oElement->hasAttribute('r:embed') && isset($this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target'])) { + $pathImage = 'ppt/slides/'.$this->arrayRels[$fileRels][$oElement->getAttribute('r:embed')]['Target']; $pathImage = explode('/', $pathImage); foreach ($pathImage as $key => $partPath) { if ($partPath == '..') { @@ -440,8 +548,8 @@ protected function loadShapeRichText(XMLReader $document, \DOMElement $node, $ba if ($oElementHlinkClick->hasAttribute('tooltip')) { $oText->getHyperlink()->setTooltip($oElementHlinkClick->getAttribute('tooltip')); } - if ($oElementHlinkClick->hasAttribute('r:id') && isset($this->arrayRels[$fileRels][$oElementHlinkClick->getAttribute('r:id')])) { - $oText->getHyperlink()->setUrl($this->arrayRels[$fileRels][$oElementHlinkClick->getAttribute('r:id')]); + if ($oElementHlinkClick->hasAttribute('r:id') && isset($this->arrayRels[$fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target'])) { + $oText->getHyperlink()->setUrl($this->arrayRels[$fileRels][$oElementHlinkClick->getAttribute('r:id')]['Target']); } } //} else { @@ -471,7 +579,10 @@ protected function loadRels($fileRels) $xmlReader = new XMLReader(); if ($xmlReader->getDomFromString($sPart)) { foreach ($xmlReader->getElements('*') as $oNode) { - $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = $oNode->getAttribute('Target'); + $this->arrayRels[$fileRels][$oNode->getAttribute('Id')] = array( + 'Target' => $oNode->getAttribute('Target'), + 'Type' => $oNode->getAttribute('Type'), + ); } } } diff --git a/src/PhpPresentation/Slide.php b/src/PhpPresentation/Slide.php index ca4b09e69..76ea01944 100644 --- a/src/PhpPresentation/Slide.php +++ b/src/PhpPresentation/Slide.php @@ -24,6 +24,7 @@ use PhpOffice\PhpPresentation\Shape\Line; use PhpOffice\PhpPresentation\Shape\RichText; use PhpOffice\PhpPresentation\Shape\Table; +use PhpOffice\PhpPresentation\Slide\AbstractBackground; use PhpOffice\PhpPresentation\Slide\Layout; use PhpOffice\PhpPresentation\Slide\Note; use PhpOffice\PhpPresentation\Slide\Transition; @@ -114,6 +115,20 @@ class Slide implements ComparableInterface, ShapeContainerInterface */ protected $extentY; + /** + * Name of the title + * + * @var string + */ + protected $name; + + /** + * Background of the slide + * + * @var AbstractBackground + */ + protected $background; + /** * Create a new slide * @@ -462,4 +477,42 @@ public function setTransition(Transition $transition = null) return $this; } + + /** + * Get the name of the slide + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Set the name of the slide + * @param string $name + * @return $this + */ + public function setName($name = null) + { + $this->name = $name; + return $this; + } + + /** + * @return AbstractBackground + */ + public function getBackground() + { + return $this->background; + } + + /** + * @param AbstractBackground $background + * @return $this + */ + public function setBackground(AbstractBackground $background = null) + { + $this->background = $background; + return $this; + } } diff --git a/src/PhpPresentation/Slide/AbstractBackground.php b/src/PhpPresentation/Slide/AbstractBackground.php new file mode 100644 index 000000000..72edbdf21 --- /dev/null +++ b/src/PhpPresentation/Slide/AbstractBackground.php @@ -0,0 +1,8 @@ +color = $color; + return $this; + } + + /** + * @return StyleColor + */ + public function getColor() + { + return $this->color; + } +} diff --git a/src/PhpPresentation/Slide/Background/Image.php b/src/PhpPresentation/Slide/Background/Image.php new file mode 100644 index 000000000..a838fd432 --- /dev/null +++ b/src/PhpPresentation/Slide/Background/Image.php @@ -0,0 +1,100 @@ +path; + } + + /** + * Set Path + * + * @param string $pValue File path + * @param boolean $pVerifyFile Verify file + * @throws \Exception + * @return \PhpOffice\PhpPresentation\Shape\Drawing + */ + public function setPath($pValue = '', $pVerifyFile = true) + { + if ($pVerifyFile) { + if (file_exists($pValue)) { + $this->path = $pValue; + + if ($this->width == 0 && $this->height == 0) { + // Get width/height + list($this->width, $this->height) = getimagesize($pValue); + } + } else { + throw new \Exception("File $pValue not found!"); + } + } else { + $this->path = $pValue; + } + + return $this; + } + + /** + * Get Filename + * + * @return string + */ + public function getFilename() + { + return basename($this->path); + } + + /** + * Get Extension + * + * @return string + */ + public function getExtension() + { + $exploded = explode('.', basename($this->path)); + + return $exploded[count($exploded) - 1]; + } + + /** + * Get indexed filename (using image index) + * + * @return string + */ + public function getIndexedFilename($numSlide) + { + return 'background_' . $numSlide . '.' . $this->getExtension(); + } +} diff --git a/src/PhpPresentation/Style/Alignment.php b/src/PhpPresentation/Style/Alignment.php index 499825abd..031093775 100644 --- a/src/PhpPresentation/Style/Alignment.php +++ b/src/PhpPresentation/Style/Alignment.php @@ -173,8 +173,8 @@ public function getLevel() */ public function setLevel($pValue = 0) { - if ($pValue < 0 || $pValue > 8) { - throw new \Exception("Invalid value: shoul be range 0 - 8."); + if ($pValue < 0) { + throw new \Exception("Invalid value should be more than 0."); } $this->level = $pValue; diff --git a/src/PhpPresentation/Writer/ODPresentation.php b/src/PhpPresentation/Writer/ODPresentation.php index fe001d513..b14b1f3db 100644 --- a/src/PhpPresentation/Writer/ODPresentation.php +++ b/src/PhpPresentation/Writer/ODPresentation.php @@ -21,6 +21,7 @@ use PhpOffice\PhpPresentation\PhpPresentation; use PhpOffice\PhpPresentation\Shape\Drawing as ShapeDrawing; use PhpOffice\PhpPresentation\Shape\MemoryDrawing; +use PhpOffice\PhpPresentation\Slide\Background\Image; use PhpOffice\PhpPresentation\Writer\ODPresentation\Content; use PhpOffice\PhpPresentation\Writer\ODPresentation\Drawing; use PhpOffice\PhpPresentation\Writer\ODPresentation\Manifest; @@ -236,6 +237,14 @@ public function save($pFilename) } } + foreach ($this->presentation->getAllSlides() as $keySlide => $oSlide) { + // Add background image slide + $oBkgImage = $oSlide->getBackground(); + if ($oBkgImage instanceof Image) { + $objZip->addFromString('Pictures/'.$oBkgImage->getIndexedFilename($keySlide), file_get_contents($oBkgImage->getPath())); + } + } + // Close file if ($objZip->close() === false) { throw new \Exception("Could not close zip file $pFilename."); diff --git a/src/PhpPresentation/Writer/ODPresentation/Content.php b/src/PhpPresentation/Writer/ODPresentation/Content.php index 9f4214c3c..fce2eddae 100644 --- a/src/PhpPresentation/Writer/ODPresentation/Content.php +++ b/src/PhpPresentation/Writer/ODPresentation/Content.php @@ -268,7 +268,10 @@ public function writePart(PhpPresentation $pPhpPresentation) for ($i = 0; $i < $slideCount; ++$i) { $pSlide = $pPhpPresentation->getSlide($i); $objWriter->startElement('draw:page'); - $objWriter->writeAttribute('draw:name', 'page' . $i); + $name = $pSlide->getName(); + if (!is_null($name)) { + $objWriter->writeAttribute('draw:name', $name); + } $objWriter->writeAttribute('draw:master-page-name', 'Standard'); $objWriter->writeAttribute('draw:style-name', 'stylePage' . $i); // Images @@ -299,8 +302,19 @@ public function writePart(PhpPresentation $pPhpPresentation) $objWriter->endElement(); } + + if ($pPhpPresentation->getPresentationProperties()->isLoopContinuouslyUntilEsc()) { + $objWriter->startElement('presentation:settings'); + $objWriter->writeAttribute('presentation:endless', 'true'); + $objWriter->writeAttribute('presentation:pause', 'P0s'); + $objWriter->writeAttribute('presentation:mouse-visible', 'false'); + $objWriter->endElement(); + } + // > office:presentation $objWriter->endElement(); + // > office:body $objWriter->endElement(); + // > office:document-content $objWriter->endElement(); // Return @@ -1209,6 +1223,19 @@ public function writeStyleSlide(XMLWriter $objWriter, Slide $slide, $incPage) break; } } + $oBackground = $slide->getBackground(); + if ($oBackground instanceof Slide\AbstractBackground) { + $objWriter->writeAttribute('presentation:background-visible', 'true'); + if ($oBackground instanceof Slide\Background\Color) { + $objWriter->writeAttribute('draw:fill', 'solid'); + $objWriter->writeAttribute('draw:fill-color', '#' . $oBackground->getColor()->getRGB()); + } + if ($oBackground instanceof Slide\Background\Image) { + $objWriter->writeAttribute('draw:fill', 'bitmap'); + $objWriter->writeAttribute('draw:fill-image-name', 'background_'.$incPage); + $objWriter->writeAttribute('style:repeat', 'stretch'); + } + } $objWriter->endElement(); // > style:style $objWriter->endElement(); diff --git a/src/PhpPresentation/Writer/ODPresentation/Manifest.php b/src/PhpPresentation/Writer/ODPresentation/Manifest.php index 9408aed8d..585a048cf 100644 --- a/src/PhpPresentation/Writer/ODPresentation/Manifest.php +++ b/src/PhpPresentation/Writer/ODPresentation/Manifest.php @@ -21,6 +21,7 @@ use PhpOffice\PhpPresentation\PhpPresentation; use PhpOffice\PhpPresentation\Shape\Drawing as ShapeDrawing; use PhpOffice\PhpPresentation\Shape\MemoryDrawing; +use PhpOffice\PhpPresentation\Slide\Background\Image; use PhpOffice\PhpPresentation\Writer\ODPresentation; /** @@ -112,6 +113,18 @@ public function writePart() } } + foreach ($parentWriter->getPhpPresentation()->getAllSlides() as $numSlide => $oSlide) { + $oBkgImage = $oSlide->getBackground(); + if ($oBkgImage instanceof Image) { + $mimeType = $this->getImageMimeType($oBkgImage->getPath()); + + $objWriter->startElement('manifest:file-entry'); + $objWriter->writeAttribute('manifest:media-type', $mimeType); + $objWriter->writeAttribute('manifest:full-path', 'Pictures/' . str_replace(' ', '_', $oBkgImage->getIndexedFilename($numSlide))); + $objWriter->endElement(); + } + } + $objWriter->endElement(); // Return diff --git a/src/PhpPresentation/Writer/ODPresentation/Styles.php b/src/PhpPresentation/Writer/ODPresentation/Styles.php index cd9f02fde..7f4ca5a4f 100644 --- a/src/PhpPresentation/Writer/ODPresentation/Styles.php +++ b/src/PhpPresentation/Writer/ODPresentation/Styles.php @@ -23,6 +23,7 @@ use PhpOffice\PhpPresentation\PhpPresentation; use PhpOffice\PhpPresentation\Shape\Group; use PhpOffice\PhpPresentation\Shape\Table; +use PhpOffice\PhpPresentation\Slide\Background\Image; use PhpOffice\PhpPresentation\Style\Fill; use PhpOffice\PhpPresentation\Shape\RichText; use PhpOffice\PhpPresentation\Style\Border; @@ -113,8 +114,8 @@ public function writePart(PhpPresentation $pPhpPresentation) // > style:style $objWriter->endElement(); - foreach ($pPhpPresentation->getAllSlides() as $slide) { - foreach ($slide->getShapeCollection() as $shape) { + foreach ($pPhpPresentation->getAllSlides() as $keySlide => $oSlide) { + foreach ($oSlide->getShapeCollection() as $shape) { if ($shape instanceof Table) { $this->writeTableStyle($objWriter, $shape); } elseif ($shape instanceof Group) { @@ -123,6 +124,10 @@ public function writePart(PhpPresentation $pPhpPresentation) $this->writeRichTextStyle($objWriter, $shape); } } + $oBkgImage = $oSlide->getBackground(); + if ($oBkgImage instanceof Image) { + $this->writeBackgroundStyle($objWriter, $oBkgImage, $keySlide); + } } // > office:styles $objWriter->endElement(); @@ -317,4 +322,20 @@ protected function writeGradientFill(XMLWriter $objWriter, Fill $oFill) $objWriter->endElement(); $this->arrayGradient[] = $oFill->getHashCode(); } + + /** + * Write the background image style + * @param XMLWriter $objWriter + * @param Image $oBkgImage + */ + protected function writeBackgroundStyle(XMLWriter $objWriter, Image $oBkgImage, $numSlide) + { + $objWriter->startElement('draw:fill-image'); + $objWriter->writeAttribute('draw:name', 'background_'.$numSlide); + $objWriter->writeAttribute('xlink:href', 'Pictures/'.str_replace(' ', '_', $oBkgImage->getIndexedFilename($numSlide))); + $objWriter->writeAttribute('xlink:type', 'simple'); + $objWriter->writeAttribute('xlink:show', 'embed'); + $objWriter->writeAttribute('xlink:actuate', 'onLoad'); + $objWriter->endElement(); + } } diff --git a/src/PhpPresentation/Writer/PowerPoint2007.php b/src/PhpPresentation/Writer/PowerPoint2007.php index 360a1a302..6ada7f59a 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007.php +++ b/src/PhpPresentation/Writer/PowerPoint2007.php @@ -22,6 +22,7 @@ use PhpOffice\PhpPresentation\Shape\Drawing as DrawingShape; use PhpOffice\PhpPresentation\Shape\MemoryDrawing as MemoryDrawingShape; use PhpOffice\PhpPresentation\Shape\Chart as ChartShape; +use PhpOffice\PhpPresentation\Slide\Background\Image; use PhpOffice\PhpPresentation\Writer\PowerPoint2007\AbstractLayoutPack; use PhpOffice\PhpPresentation\Writer\PowerPoint2007\Chart; use PhpOffice\PhpPresentation\Writer\PowerPoint2007\ContentTypes; @@ -214,9 +215,9 @@ public function save($pFilename) $objZip->addFromString('[Content_Types].xml', $wPartContentTypes->writeContentTypes($this->presentation)); // Add PPT properties and styles to ZIP file - Required for Apple Keynote compatibility. - $objZip->addFromString('ppt/presProps.xml', $wPptProps->writePresProps()); + $objZip->addFromString('ppt/presProps.xml', $wPptProps->writePresProps($this->presentation)); $objZip->addFromString('ppt/tableStyles.xml', $wPptProps->writeTableStyles()); - $objZip->addFromString('ppt/viewProps.xml', $wPptProps->writeViewProps()); + $objZip->addFromString('ppt/viewProps.xml', $wPptProps->writeViewProps($this->presentation)); // Add relationships to ZIP file $objZip->addFromString('_rels/.rels', $wPartRels->writeRelationships()); @@ -225,6 +226,7 @@ public function save($pFilename) // Add document properties to ZIP file $objZip->addFromString('docProps/app.xml', $wPartDocProps->writeDocPropsApp($this->presentation)); $objZip->addFromString('docProps/core.xml', $wPartDocProps->writeDocPropsCore($this->presentation)); + $objZip->addFromString('docProps/custom.xml', $wPartDocProps->writeDocPropsCustom($this->presentation)); $masterSlides = $this->getLayoutPack()->getMasterSlides(); foreach ($masterSlides as $masterSlide) { @@ -268,11 +270,18 @@ public function save($pFilename) // Add slides (drawings, ...) and slide relationships (drawings, ...) for ($i = 0; $i < $this->presentation->getSlideCount(); ++$i) { + $oSlide = $this->presentation->getSlide($i); // Add slide - $objZip->addFromString('ppt/slides/_rels/slide' . ($i + 1) . '.xml.rels', $wPartRels->writeSlideRelationships($this->presentation->getSlide($i))); - $objZip->addFromString('ppt/slides/slide' . ($i + 1) . '.xml', $wPartSlide->writeSlide($this->presentation->getSlide($i))); - if ($this->presentation->getSlide($i)->getNote()->getShapeCollection()->count() > 0) { - $objZip->addFromString('ppt/notesSlides/notesSlide' . ($i + 1) . '.xml', $wPartSlide->writeNote($this->presentation->getSlide($i)->getNote())); + $objZip->addFromString('ppt/slides/_rels/slide' . ($i + 1) . '.xml.rels', $wPartRels->writeSlideRelationships($oSlide)); + $objZip->addFromString('ppt/slides/slide' . ($i + 1) . '.xml', $wPartSlide->writeSlide($oSlide)); + // Add note slide + if ($oSlide->getNote()->getShapeCollection()->count() > 0) { + $objZip->addFromString('ppt/notesSlides/notesSlide' . ($i + 1) . '.xml', $wPartSlide->writeNote($oSlide->getNote())); + } + // Add background image slide + $oBkgImage = $oSlide->getBackground(); + if ($oBkgImage instanceof Image) { + $objZip->addFromString('ppt/media/'.$oBkgImage->getIndexedFilename($i), file_get_contents($oBkgImage->getPath())); } } diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractLayoutPack.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractLayoutPack.php index 5ff54f0cb..93345b07b 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractLayoutPack.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractLayoutPack.php @@ -204,4 +204,23 @@ public function findLayoutId($name = '', $masterId = 1) throw new \Exception("Could not find slide layout $name in current layout pack."); } + + /** + * Find specific slide layout name. + * + * @param int $idLayout + * @param int $masterId + * @return int + * @throws \Exception + */ + public function findLayoutName($idLayout = '', $masterId = 1) + { + foreach ($this->layouts as $layoutId => $layout) { + if ($layoutId == $idLayout && $layout['masterid'] == $masterId) { + return $layout['name']; + } + } + + throw new \Exception("Could not find slide layout $idLayout in current layout pack."); + } } diff --git a/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php b/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php index 8c90bdb80..431bc44d0 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php @@ -76,6 +76,7 @@ public function writeContentTypes(PhpPresentation $pPhpPresentation) // DocProps $this->writeOverrideContentType($objWriter, '/docProps/app.xml', 'application/vnd.openxmlformats-officedocument.extended-properties+xml'); $this->writeOverrideContentType($objWriter, '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml'); + $this->writeOverrideContentType($objWriter, '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.custom-properties+xml'); // Slide masters $masterSlides = $parentWriter->getLayoutPack()->getMasterSlides(); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocProps.php b/src/PhpPresentation/Writer/PowerPoint2007/DocProps.php index 966b49965..8554fc12d 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocProps.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocProps.php @@ -176,6 +176,54 @@ public function writeDocPropsCore(PhpPresentation $pPhpPresentation) // cp:category $objWriter->writeElement('cp:category', $pPhpPresentation->getProperties()->getCategory()); + if ($pPhpPresentation->isMarkedAsFinal()) { + // cp:contentStatus = Final + $objWriter->writeElement('cp:contentStatus', 'Final'); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + + + /** + * Write docProps/custom.xml to XML format + * + * @param PhpPresentation $pPhpPresentation + * @return string XML Output + * @throws \Exception + */ + public function writeDocPropsCustom(PhpPresentation $pPhpPresentation) + { + // Create XML writer + $objWriter = $this->getXMLWriter(); + + // XML header + $objWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // Properties + $objWriter->startElement('Properties'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties'); + $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + + if ($pPhpPresentation->isMarkedAsFinal()) { + // property + $objWriter->startElement('property'); + $objWriter->writeAttribute('fmtid', '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}'); + $objWriter->writeAttribute('pid', 2); + $objWriter->writeAttribute('name', '_MarkAsFinal'); + + // property > vt:bool + $objWriter->writeElement('vt:bool', 'true'); + + // > property + $objWriter->endElement(); + } + + // > Properties $objWriter->endElement(); // Return diff --git a/src/PhpPresentation/Writer/PowerPoint2007/Drawing.php b/src/PhpPresentation/Writer/PowerPoint2007/Drawing.php index 4acd2087b..6e628b85d 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/Drawing.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/Drawing.php @@ -43,21 +43,23 @@ public function allDrawings(PhpPresentation $pPhpPresentation) $slideCount = $pPhpPresentation->getSlideCount(); for ($i = 0; $i < $slideCount; ++$i) { // Loop trough images and add to array - $iterator = $pPhpPresentation->getSlide($i)->getShapeCollection()->getIterator(); - while ($iterator->valid()) { - if ($iterator->current() instanceof AbstractDrawing && !($iterator->current() instanceof Table)) { - $aDrawings[] = $iterator->current(); - } elseif ($iterator->current() instanceof Group) { - $iterator2 = $iterator->current()->getShapeCollection()->getIterator(); - while ($iterator2->valid()) { - if ($iterator2->current() instanceof AbstractDrawing && !($iterator2->current() instanceof Table)) { - $aDrawings[] = $iterator2->current(); + if ($pPhpPresentation->getSlide($i)->getShapeCollection()->count() > 0) { + $iterator = $pPhpPresentation->getSlide($i)->getShapeCollection()->getIterator(); + while ($iterator->valid()) { + if ($iterator->current() instanceof AbstractDrawing && !($iterator->current() instanceof Table)) { + $aDrawings[] = $iterator->current(); + } elseif ($iterator->current() instanceof Group) { + $iterator2 = $iterator->current()->getShapeCollection()->getIterator(); + while ($iterator2->valid()) { + if ($iterator2->current() instanceof AbstractDrawing && !($iterator2->current() instanceof Table)) { + $aDrawings[] = $iterator2->current(); + } + $iterator2->next(); } - $iterator2->next(); } - } - $iterator->next(); + $iterator->next(); + } } } diff --git a/src/PhpPresentation/Writer/PowerPoint2007/LayoutPack/PackDefault.php b/src/PhpPresentation/Writer/PowerPoint2007/LayoutPack/PackDefault.php index db5b13355..1929eaf70 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/LayoutPack/PackDefault.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/LayoutPack/PackDefault.php @@ -1061,7 +1061,7 @@ public function __construct() - ?#? + ‹#› @@ -1229,7 +1229,7 @@ public function __construct() - ?#? + ‹#› @@ -1473,7 +1473,7 @@ public function __construct() - ?#? + ‹#› @@ -1759,7 +1759,7 @@ public function __construct() - ?#? + ‹#› @@ -2179,7 +2179,7 @@ public function __construct() - ?#? + ‹#› @@ -2295,7 +2295,7 @@ public function __construct() - ?#? + ‹#› @@ -2388,7 +2388,7 @@ public function __construct() - ?#? + ‹#› @@ -2663,7 +2663,7 @@ public function __construct() - ?#? + ‹#› @@ -2914,7 +2914,7 @@ public function __construct() - ?#? + ‹#› @@ -3082,7 +3082,7 @@ public function __construct() - ?#? + ‹#› @@ -3260,7 +3260,7 @@ public function __construct() - ?#? + ‹#› diff --git a/src/PhpPresentation/Writer/PowerPoint2007/PptProps.php b/src/PhpPresentation/Writer/PowerPoint2007/PptProps.php index 27dd316ff..62018e187 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/PptProps.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/PptProps.php @@ -27,8 +27,10 @@ class PptProps extends AbstractPart * @return string XML Output * @throws \Exception */ - public function writePresProps() + public function writePresProps(PhpPresentation $pPhpPresentation) { + $presentationPpts = $pPhpPresentation->getPresentationProperties(); + // Create XML writer $objWriter = $this->getXMLWriter(); @@ -40,6 +42,13 @@ public function writePresProps() $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); $objWriter->writeAttribute('xmlns:p', 'http://schemas.openxmlformats.org/presentationml/2006/main'); + + // p:presentationPr > p:showPr + if ($presentationPpts->isLoopContinuouslyUntilEsc()) { + $objWriter->startElement('p:showPr'); + $objWriter->writeAttribute('loop', '1'); + $objWriter->endElement(); + } // p:extLst $objWriter->startElement('p:extLst'); @@ -105,7 +114,7 @@ public function writeTableStyles() * @return string XML Output * @throws \Exception */ - public function writeViewProps() + public function writeViewProps(PhpPresentation $oPhpPresentation) { // Create XML writer $objWriter = $this->getXMLWriter(); @@ -120,7 +129,46 @@ public function writeViewProps() $objWriter->writeAttribute('xmlns:p', 'http://schemas.openxmlformats.org/presentationml/2006/main'); $objWriter->writeAttribute('showComments', '0'); - // > p:viewPr + // p:viewPr > p:slideViewPr + $objWriter->startElement('p:slideViewPr'); + + // p:viewPr > p:slideViewPr > p:cSldViewPr + $objWriter->startElement('p:cSldViewPr'); + + // p:viewPr > p:slideViewPr > p:cSldViewPr > p:cViewPr + $objWriter->startElement('p:cViewPr'); + + // p:viewPr > p:slideViewPr > p:cSldViewPr > p:cViewPr > p:scale + $objWriter->startElement('p:scale'); + + $objWriter->startElement('a:sx'); + $objWriter->writeAttribute('d', '100'); + $objWriter->writeAttribute('n', (int)($oPhpPresentation->getZoom() * 100)); + $objWriter->endElement(); + + $objWriter->startElement('a:sy'); + $objWriter->writeAttribute('d', '100'); + $objWriter->writeAttribute('n', (int)($oPhpPresentation->getZoom() * 100)); + $objWriter->endElement(); + + // > // p:viewPr > p:slideViewPr > p:cSldViewPr > p:cViewPr > p:scale + $objWriter->endElement(); + + $objWriter->startElement('p:origin'); + $objWriter->writeAttribute('x', '0'); + $objWriter->writeAttribute('y', '0'); + $objWriter->endElement(); + + // > // p:viewPr > p:slideViewPr > p:cSldViewPr > p:cViewPr + $objWriter->endElement(); + + // > // p:viewPr > p:slideViewPr > p:cSldViewPr + $objWriter->endElement(); + + // > // p:viewPr > p:slideViewPr + $objWriter->endElement(); + + // > // p:viewPr $objWriter->endElement(); return $objWriter->getData(); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/Rels.php b/src/PhpPresentation/Writer/PowerPoint2007/Rels.php index b72f28eeb..ba762faa2 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/Rels.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/Rels.php @@ -53,6 +53,9 @@ public function writeRelationships() $objWriter->startElement('Relationships'); $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + // Relationship docProps/custom.xml + $this->writeRelationship($objWriter, 4, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties', 'docProps/custom.xml'); + // Relationship docProps/app.xml $this->writeRelationship($objWriter, 3, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties', 'docProps/app.xml'); @@ -333,6 +336,14 @@ public function writeSlideRelationships(SlideElement $pSlide) } } + // Write background relationships? + $oBackground = $pSlide->getBackground(); + if ($oBackground instanceof SlideElement\Background\Image) { + $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', '../media/' . $oBackground->getIndexedFilename($idxSlide)); + $oBackground->relationId = 'rId' . $relId; + ++$relId; + } + // Write hyperlink relationships? if ($pSlide->getShapeCollection()->count() > 0) { // Loop trough hyperlinks and write relationships diff --git a/src/PhpPresentation/Writer/PowerPoint2007/Slide.php b/src/PhpPresentation/Writer/PowerPoint2007/Slide.php index fb0983770..8d7533775 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/Slide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/Slide.php @@ -72,6 +72,59 @@ public function writeSlide(SlideElement $pSlide = null) // p:cSld $objWriter->startElement('p:cSld'); + // Background + if ($pSlide->getBackground() instanceof SlideElement\AbstractBackground) { + $oBackground = $pSlide->getBackground(); + // p:bg + $objWriter->startElement('p:bg'); + + // p:bgPr + $objWriter->startElement('p:bgPr'); + + if ($oBackground instanceof SlideElement\Background\Color) { + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', $oBackground->getColor()->getRGB()); + $objWriter->endElement(); + + // > a:solidFill + $objWriter->endElement(); + } + + if ($oBackground instanceof SlideElement\Background\Image) { + // a:blipFill + $objWriter->startElement('a:blipFill'); + + // a:blip + $objWriter->startElement('a:blip'); + $objWriter->writeAttribute('r:embed', $oBackground->relationId); + + // > a:blipFill + $objWriter->endElement(); + + // a:stretch + $objWriter->startElement('a:stretch'); + + // a:fillRect + $objWriter->writeElement('a:fillRect'); + + // > a:stretch + $objWriter->endElement(); + + // > a:blipFill + $objWriter->endElement(); + } + + // > p:bgPr + $objWriter->endElement(); + + // > p:bg + $objWriter->endElement(); + } + // p:spTree $objWriter->startElement('p:spTree'); @@ -854,10 +907,10 @@ private function writeParagraphs(XMLWriter $objWriter, $paragraphs) $objWriter->startElement('a:rPr'); // Bold - $objWriter->writeAttribute('b', ($element->getFont()->isBold() ? 'true' : 'false')); + $objWriter->writeAttribute('b', ($element->getFont()->isBold() ? '1' : '0')); // Italic - $objWriter->writeAttribute('i', ($element->getFont()->isItalic() ? 'true' : 'false')); + $objWriter->writeAttribute('i', ($element->getFont()->isItalic() ? '1' : '0')); // Strikethrough $objWriter->writeAttribute('strike', ($element->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); diff --git a/tests/PhpPresentation/Tests/PhpPowerpointTest.php b/tests/PhpPresentation/Tests/PhpPowerpointTest.php index 228e58d47..13b4805ac 100644 --- a/tests/PhpPresentation/Tests/PhpPowerpointTest.php +++ b/tests/PhpPresentation/Tests/PhpPowerpointTest.php @@ -92,6 +92,20 @@ public function testGetSlideException() $object->getSlide(1); } + public function testMarkAsFinal() + { + $object = new PhpPresentation(); + $this->assertFalse($object->isMarkedAsFinal()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $object->markAsFinal('AAAA')); + $this->assertFalse($object->isMarkedAsFinal()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $object->markAsFinal(true)); + $this->assertTrue($object->isMarkedAsFinal()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $object->markAsFinal(false)); + $this->assertFalse($object->isMarkedAsFinal()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $object->markAsFinal()); + $this->assertTrue($object->isMarkedAsFinal()); + } + /** * Test set active slide index exception * @@ -103,4 +117,16 @@ public function testSetActiveSlideIndexException() $object = new PhpPresentation(); $object->setActiveSlideIndex(1); } + + public function testZoom() + { + $object = new PhpPresentation(); + $this->assertEquals(1, $object->getZoom()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $object->setZoom('AAAA')); + $this->assertEquals(1, $object->getZoom()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $object->setZoom(2.3)); + $this->assertEquals(2.3, $object->getZoom()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $object->setZoom()); + $this->assertEquals(1, $object->getZoom()); + } } diff --git a/tests/PhpPresentation/Tests/Reader/ODPresentationTest.php b/tests/PhpPresentation/Tests/Reader/ODPresentationTest.php index 9b866fd4b..6e1287e45 100644 --- a/tests/PhpPresentation/Tests/Reader/ODPresentationTest.php +++ b/tests/PhpPresentation/Tests/Reader/ODPresentationTest.php @@ -464,4 +464,41 @@ public function testLoadFile01() $this->assertEquals('https://github.com/PHPOffice/PHPPresentation/', $oRichText->getHyperlink()->getUrl()); //$this->assertEquals('PHPPresentation', $oRichText->getHyperlink()->getTooltip()); } + + public function testSlideName() + { + $file = PHPPRESENTATION_TESTS_BASE_DIR . '/resources/files/ODP_Slide_Name.odp'; + $object = new ODPresentation(); + $oPhpPresentation = $object->load($file); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $oPhpPresentation); + + $this->assertEquals('MaDiapo', $oPhpPresentation->getSlide(0)->getName()); + } + + public function testIssue00141() + { + $file = PHPPRESENTATION_TESTS_BASE_DIR . '/resources/files/Issue_00141.odp'; + $object = new ODPresentation(); + $oPhpPresentation = $object->load($file); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $oPhpPresentation); + + $this->assertCount(3, $oPhpPresentation->getAllSlides()); + + // Slide 1 + $oSlide = $oPhpPresentation->getSlide(1); + $arrayShape = $oSlide->getShapeCollection(); + $this->assertCount(2, $arrayShape); + // Slide 1 : Shape 1 + $oShape = reset($arrayShape); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\RichText', $oShape); + // Slide 1 : Shape 1 : Paragraph 1 + $oParagraph = $oShape->getParagraph(); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\RichText\\Paragraph', $oParagraph); + // Slide 1 : Shape 1 : Paragraph 1 : RichText Elements + $arrayElements = $oParagraph->getRichTextElements(); + $this->assertCount(1, $arrayElements); + $oElement = reset($arrayElements); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\RichText\\TextElement', $oElement); + $this->assertEquals('TEST IMAGE', $oElement->getText()); + } } diff --git a/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php b/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php index 9f0ceb651..084d5ed96 100644 --- a/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php +++ b/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php @@ -462,4 +462,36 @@ public function testLoadFile01() $this->assertEquals('https://github.com/PHPOffice/PHPPresentation/', $oRichText->getHyperlink()->getUrl()); $this->assertEquals('PHPPresentation', $oRichText->getHyperlink()->getTooltip()); } + + public function testMarkAsFinal() + { + $file = PHPPRESENTATION_TESTS_BASE_DIR . '/resources/files/Sample_12.pptx'; + $object = new PowerPoint2007(); + $oPhpPresentation = $object->load($file); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $oPhpPresentation); + $this->assertFalse($oPhpPresentation->isMarkedAsFinal()); + + + $file = PHPPRESENTATION_TESTS_BASE_DIR . '/resources/files/PPTX_MarkAsFinal.pptx'; + $object = new PowerPoint2007(); + $oPhpPresentation = $object->load($file); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $oPhpPresentation); + $this->assertTrue($oPhpPresentation->isMarkedAsFinal()); + } + + public function testZoom() + { + $file = PHPPRESENTATION_TESTS_BASE_DIR . '/resources/files/Sample_12.pptx'; + $object = new PowerPoint2007(); + $oPhpPresentation = $object->load($file); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $oPhpPresentation); + $this->assertEquals(1, $oPhpPresentation->getZoom()); + + + $file = PHPPRESENTATION_TESTS_BASE_DIR . '/resources/files/PPTX_Zoom.pptx'; + $object = new PowerPoint2007(); + $oPhpPresentation = $object->load($file); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\PhpPresentation', $oPhpPresentation); + $this->assertEquals(2.68, $oPhpPresentation->getZoom()); + } } diff --git a/tests/PhpPresentation/Tests/Slide/Background/ColorTest.php b/tests/PhpPresentation/Tests/Slide/Background/ColorTest.php new file mode 100644 index 000000000..7221cf81a --- /dev/null +++ b/tests/PhpPresentation/Tests/Slide/Background/ColorTest.php @@ -0,0 +1,23 @@ +setRGB('123456'); + + $this->assertNull($object->getColor()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\Background\\Color', $object->setColor($oStyleColor)); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Color', $object->getColor()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\Background\\Color', $object->setColor()); + $this->assertNull($object->getColor()); + } +} diff --git a/tests/PhpPresentation/Tests/Slide/Background/ImageTest.php b/tests/PhpPresentation/Tests/Slide/Background/ImageTest.php new file mode 100644 index 000000000..1bcfb1316 --- /dev/null +++ b/tests/PhpPresentation/Tests/Slide/Background/ImageTest.php @@ -0,0 +1,33 @@ +assertNull($object->getPath()); + $this->assertEmpty($object->getFilename()); + $this->assertEmpty($object->getExtension()); + $this->assertEquals('background_' . $numSlide . '.', $object->getIndexedFilename($numSlide)); + + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\Background\\Image', $object->setPath($imagePath)); + $this->assertEquals($imagePath, $object->getPath()); + $this->assertEquals('PhpPresentationLogo.png', $object->getFilename()); + $this->assertEquals('png', $object->getExtension()); + $this->assertEquals('background_' . $numSlide . '.png', $object->getIndexedFilename($numSlide)); + + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\Background\\Image', $object->setPath(null, false)); + $this->assertNull($object->getPath()); + $this->assertEmpty($object->getFilename()); + $this->assertEmpty($object->getExtension()); + $this->assertEquals('background_' . $numSlide . '.', $object->getIndexedFilename($numSlide)); + } +} diff --git a/tests/PhpPresentation/Tests/SlideTest.php b/tests/PhpPresentation/Tests/SlideTest.php index 6b161ed25..3af785fe0 100644 --- a/tests/PhpPresentation/Tests/SlideTest.php +++ b/tests/PhpPresentation/Tests/SlideTest.php @@ -77,13 +77,35 @@ public function testSlideMasterId() $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide', $object->setSlideMasterId($value)); $this->assertEquals($value, $object->getSlideMasterId()); } - + + public function testBackground() + { + $oStub = $this->getMockForAbstractClass('PhpOffice\PhpPresentation\Slide\AbstractBackground'); + + $object = new Slide(); + $this->assertNull($object->getBackground()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide', $object->setBackground($oStub)); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\AbstractBackground', $object->getBackground()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide', $object->setBackground()); + $this->assertNull($object->getBackground()); + } + public function testGroup() { $object = new Slide(); $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\Group', $object->createGroup()); } + public function testName() + { + $object = new Slide(); + $this->assertNull($object->getName()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide', $object->setName('AAAA')); + $this->assertEquals('AAAA', $object->getName()); + $this->assertInstanceOf('PhpOffice\\PhpPresentation\\Slide', $object->setName()); + $this->assertNull($object->getName()); + } + public function testTransition() { $object = new Slide(); diff --git a/tests/PhpPresentation/Tests/Style/AlignmentTest.php b/tests/PhpPresentation/Tests/Style/AlignmentTest.php index 2996a5ffa..4197cc00c 100644 --- a/tests/PhpPresentation/Tests/Style/AlignmentTest.php +++ b/tests/PhpPresentation/Tests/Style/AlignmentTest.php @@ -70,20 +70,10 @@ public function testSetGetVertical() public function testSetGetLevelExceptionMin() { $object = new Alignment(); - $this->setExpectedException('\Exception', 'Invalid value: shoul be range 0 - 8.'); + $this->setExpectedException('\Exception', 'Invalid value should be more than 0.'); $object->setLevel(-1); } - /** - * Test get/set max level exception - */ - public function testSetGetLevelExceptionMax() - { - $object = new Alignment(); - $this->setExpectedException('\Exception', 'Invalid value: shoul be range 0 - 8.'); - $object->setLevel(9); - } - /** * Test get/set level */ diff --git a/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php b/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php index 0fb9ffab5..ffd9d725e 100644 --- a/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php +++ b/tests/PhpPresentation/Tests/Writer/ODPresentation/ContentTest.php @@ -305,7 +305,32 @@ public function testRichTextShadow() } } } - + + public function testSlideName() + { + $phpPresentation = new PhpPresentation(); + $oSlide = $phpPresentation->getActiveSlide(); + + $element = '/office:document-content/office:body/office:presentation/draw:page'; + + $pres = TestHelperDOCX::getDocument($phpPresentation, 'ODPresentation'); + $this->assertTrue($pres->elementExists($element, 'content.xml')); + $this->assertFalse($pres->attributeElementExists($element, 'draw:name', 'content.xml')); + + $oSlide->setName('AAAA'); + + $pres = TestHelperDOCX::getDocument($phpPresentation, 'ODPresentation'); + $this->assertTrue($pres->elementExists($element, 'content.xml')); + $this->assertTrue($pres->attributeElementExists($element, 'draw:name', 'content.xml')); + $this->assertEquals('AAAA', $pres->getElementAttribute($element, 'draw:name', 'content.xml')); + + $oSlide->setName(); + + $pres = TestHelperDOCX::getDocument($phpPresentation, 'ODPresentation'); + $this->assertTrue($pres->elementExists($element, 'content.xml')); + $this->assertFalse($pres->attributeElementExists($element, 'draw:name', 'content.xml')); + } + public function testStyleAlignment() { $phpPresentation = new PhpPresentation(); diff --git a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/LayoutPack/TemplateBasedTest.php b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/LayoutPack/TemplateBasedTest.php index c489733b5..2ad2b261b 100644 --- a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/LayoutPack/TemplateBasedTest.php +++ b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/LayoutPack/TemplateBasedTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpPresentation\Tests\Writer\PowerPoint2007\LayoutPack; +use PhpOffice\PhpPresentation\Writer\PowerPoint2007\LayoutPack\PackDefault; use PhpOffice\PhpPresentation\Writer\PowerPoint2007\LayoutPack\TemplateBased; /** @@ -71,4 +72,22 @@ public function testFindLayoutIdException() $name = 'Invalid'; $templateBased->findLayoutId($name); } + + public function testFindLayoutName() + { + $oLayout = new PackDefault(); + foreach ($oLayout->getLayouts() as $keyLayout => $layout) { + $foundLayoutName = $oLayout->findLayoutName($keyLayout); + $this->assertEquals($layout['name'], $foundLayoutName); + } + } + + /** + * @expectedException \Exception + */ + public function testFindLayoutNameException() + { + $oLayout = new PackDefault(); + $oLayout->findLayoutName(1000); + } } diff --git a/tests/PhpPresentation/Tests/Writer/PowerPoint2007Test.php b/tests/PhpPresentation/Tests/Writer/PowerPoint2007Test.php index 8c0abf169..9036a0ba0 100644 --- a/tests/PhpPresentation/Tests/Writer/PowerPoint2007Test.php +++ b/tests/PhpPresentation/Tests/Writer/PowerPoint2007Test.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpPresentation\Tests\Writer; use PhpOffice\PhpPresentation\PhpPresentation; +use PhpOffice\PhpPresentation\Tests\TestHelperDOCX; use PhpOffice\PhpPresentation\Writer\PowerPoint2007; /** @@ -137,4 +138,53 @@ public function testSetUseDiskCachingException() $object = new PowerPoint2007(new PhpPresentation()); $object->setUseDiskCaching(true, 'foo'); } + + public function testMarkAsFinal() + { + $oPhpPresentation = new PhpPresentation(); + + $pres = TestHelperDOCX::getDocument($oPhpPresentation, 'PowerPoint2007'); + $this->assertFalse($pres->elementExists('/Properties/property[@name="_MarkAsFinal"]', 'docProps/custom.xml')); + $this->assertFalse($pres->elementExists('/cp:coreProperties/cp:contentStatus', 'docProps/core.xml')); + + $oPhpPresentation->markAsFinal(true); + + $pres = TestHelperDOCX::getDocument($oPhpPresentation, 'PowerPoint2007'); + $this->assertTrue($pres->elementExists('/Properties', 'docProps/custom.xml')); + $this->assertTrue($pres->elementExists('/Properties/property', 'docProps/custom.xml')); + $this->assertTrue($pres->elementExists('/Properties/property[@pid="2"][@fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"][@name="_MarkAsFinal"]', 'docProps/custom.xml')); + $this->assertTrue($pres->elementExists('/Properties/property[@pid="2"][@fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"][@name="_MarkAsFinal"]/vt:bool', 'docProps/custom.xml')); + $this->assertTrue($pres->elementExists('/cp:coreProperties/cp:contentStatus', 'docProps/core.xml')); + $this->assertEquals('Final', $pres->getElement('/cp:coreProperties/cp:contentStatus', 'docProps/core.xml')->nodeValue); + + $oPhpPresentation->markAsFinal(false); + + $pres = TestHelperDOCX::getDocument($oPhpPresentation, 'PowerPoint2007'); + $this->assertFalse($pres->elementExists('/Properties/property[@name="_MarkAsFinal"]', 'docProps/custom.xml')); + $this->assertFalse($pres->elementExists('/cp:coreProperties/cp:contentStatus', 'docProps/core.xml')); + } + + public function testZoom() + { + $oPhpPresentation = new PhpPresentation(); + + $pres = TestHelperDOCX::getDocument($oPhpPresentation, 'PowerPoint2007'); + $this->assertTrue($pres->elementExists('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx', 'ppt/viewProps.xml')); + $this->assertEquals('100', $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx', 'n', 'ppt/viewProps.xml')); + $this->assertEquals('100', $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx', 'd', 'ppt/viewProps.xml')); + $this->assertTrue($pres->elementExists('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sy', 'ppt/viewProps.xml')); + $this->assertEquals('100', $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sy', 'n', 'ppt/viewProps.xml')); + $this->assertEquals('100', $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sy', 'd', 'ppt/viewProps.xml')); + + $value = rand(1, 100); + $oPhpPresentation->setZoom($value); + + $pres = TestHelperDOCX::getDocument($oPhpPresentation, 'PowerPoint2007'); + $this->assertTrue($pres->elementExists('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx', 'ppt/viewProps.xml')); + $this->assertEquals($value * 100, $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx', 'n', 'ppt/viewProps.xml')); + $this->assertEquals('100', $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sx', 'd', 'ppt/viewProps.xml')); + $this->assertTrue($pres->elementExists('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sy', 'ppt/viewProps.xml')); + $this->assertEquals($value * 100, $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sy', 'n', 'ppt/viewProps.xml')); + $this->assertEquals('100', $pres->getElementAttribute('/p:viewPr/p:slideViewPr/p:cSldViewPr/p:cViewPr/p:scale/a:sy', 'd', 'ppt/viewProps.xml')); + } } diff --git a/tests/PhpPresentation/Tests/_includes/XmlDocument.php b/tests/PhpPresentation/Tests/_includes/XmlDocument.php index 5320241fb..57075ee30 100644 --- a/tests/PhpPresentation/Tests/_includes/XmlDocument.php +++ b/tests/PhpPresentation/Tests/_includes/XmlDocument.php @@ -68,6 +68,7 @@ public function __construct($path) */ public function getFileDom($file = 'word/document.xml') { + $baseFile = $file; if (null !== $this->dom && $file === $this->file) { return $this->dom; } @@ -77,7 +78,12 @@ public function getFileDom($file = 'word/document.xml') $file = $this->path . '/' . $file; $this->dom = new \DOMDocument(); - $this->dom->load($file); + $strContent = file_get_contents($file); + // docProps/custom.xml + if ($baseFile == 'docProps/custom.xml') { + $strContent = str_replace(' xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"', '', $strContent); + } + $this->dom->loadXML($strContent); return $this->dom; } diff --git a/tests/resources/files/Issue_00141.odp b/tests/resources/files/Issue_00141.odp new file mode 100644 index 000000000..36e21c150 Binary files /dev/null and b/tests/resources/files/Issue_00141.odp differ diff --git a/tests/resources/files/ODP_Slide_Name.odp b/tests/resources/files/ODP_Slide_Name.odp new file mode 100644 index 000000000..4a8b2fdc1 Binary files /dev/null and b/tests/resources/files/ODP_Slide_Name.odp differ diff --git a/tests/resources/files/PPTX_MarkAsFinal.pptx b/tests/resources/files/PPTX_MarkAsFinal.pptx new file mode 100644 index 000000000..b5ba81fb9 Binary files /dev/null and b/tests/resources/files/PPTX_MarkAsFinal.pptx differ diff --git a/tests/resources/files/PPTX_Zoom.pptx b/tests/resources/files/PPTX_Zoom.pptx new file mode 100644 index 000000000..0ef676fc9 Binary files /dev/null and b/tests/resources/files/PPTX_Zoom.pptx differ