From 715e9434075d658284d4fde43867c91e14d44222 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Fri, 14 Aug 2020 17:10:01 +0200 Subject: [PATCH 01/23] Add read/write Revision document attribut Add read/write Revision document attribut. Informations are stored into document properties. Available for Powerpoint 2007 (reading/writing) --- src/PhpPresentation/DocumentProperties.php | 28 ++++++++++++++++++- src/PhpPresentation/Reader/PowerPoint2007.php | 3 +- .../Writer/PowerPoint2007/DocPropsCore.php | 3 ++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/PhpPresentation/DocumentProperties.php b/src/PhpPresentation/DocumentProperties.php index 7c48cef1d..cbcd052eb 100644 --- a/src/PhpPresentation/DocumentProperties.php +++ b/src/PhpPresentation/DocumentProperties.php @@ -100,7 +100,14 @@ class DocumentProperties * @var string */ private $company; - + + /** + * revision + * + * @var string + */ + private $revision; + /** * Custom Properties. * @@ -124,6 +131,7 @@ public function __construct() $this->keywords = ''; $this->category = ''; $this->company = 'Microsoft Corporation'; + $this->revision = ''; } /** @@ -453,4 +461,22 @@ public function setCustomProperty(string $propertyName, $propertyValue = '', ?st return $this; } + + /* + * Get Revision. + */ + public function getRevision(): string + { + return $this->revision; + } + + /** + * Set Revision + */ + public function setRevision(string $pValue = ''): self + { + $this->revision = $pValue; + + return $this; + } } diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index 763848c92..ef28e3e48 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -223,7 +223,8 @@ protected function loadDocumentProperties(string $sPart): void '/cp:coreProperties/cp:category' => 'setCategory', '/cp:coreProperties/dcterms:created' => 'setCreated', '/cp:coreProperties/dcterms:modified' => 'setModified', - ]; + '/cp:coreProperties/cp:revision' => 'setRevision', + ); $oProperties = $this->oPhpPresentation->getDocumentProperties(); foreach ($arrayProperties as $path => $property) { $oElement = $xmlReader->getElement($path); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php index 63897ee18..afd8c08d2 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php @@ -70,6 +70,9 @@ public function render(): ZipInterface // cp:keywords $objWriter->writeElement('cp:keywords', $this->oPresentation->getDocumentProperties()->getKeywords()); + // cp:revision + $objWriter->writeElement('cp:revision', $this->oPresentation->getDocumentProperties()->getRevision()); + // cp:category $objWriter->writeElement('cp:category', $this->oPresentation->getDocumentProperties()->getCategory()); From 71fee9c81997caef43973d2e67d238071d7cbdaa Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Fri, 14 Aug 2020 23:12:38 +0200 Subject: [PATCH 02/23] Conserve thumbnail if already exist in file Conserve thumbnail if already exist in file: If an thumbnail exist in a file, when open it, thumbnail is loaded and when you save existing thumbnail is save to output --- .../PresentationProperties.php | 62 ++++++++++++++++--- src/PhpPresentation/Reader/PowerPoint2007.php | 28 ++++++++- .../PowerPoint2007/DocPropsThumbnail.php | 18 +++++- .../Writer/PowerPoint2007/Relationships.php | 16 ++++- 4 files changed, 112 insertions(+), 12 deletions(-) diff --git a/src/PhpPresentation/PresentationProperties.php b/src/PhpPresentation/PresentationProperties.php index c10c915f8..63eca8fb5 100644 --- a/src/PhpPresentation/PresentationProperties.php +++ b/src/PhpPresentation/PresentationProperties.php @@ -30,6 +30,9 @@ class PresentationProperties public const VIEW_SLIDE_SORTER = 'sldSorterView'; public const VIEW_SLIDE_THUMBNAIL = 'sldThumbnailView'; + public const THUMBNAIL_FILE = 'file'; // Thumbnail path is out of PPT + public const THUMBNAIL_ZIP = 'zip'; // Thumbnail path point to an image store into file loaded + /** * @var array */ @@ -69,10 +72,20 @@ class PresentationProperties */ protected $markAsFinal = false; - /** - * @var null|string + /* + * @var string Define the thumbnail content (if content into zip file) + */ + protected $thumbnail = null; + + /* + * @var string Define the thumbnail place */ - protected $thumbnail; + protected $thumbnailPath = ''; + + /* + * @var string Define if thumbnail is out of PPT or previouly store into PPT + */ + protected $thumbnailType = self::THUMBNAIL_FILE; /** * Zoom. @@ -113,23 +126,58 @@ public function setLoopContinuouslyUntilEsc(bool $value = false): self */ public function getThumbnailPath(): ?string { + return $this->thumbnailPath; + } + + /** + * Return the content of thumbnail + * + * @return binary Content of image + */ + public function getThumbnail() + { + // Return content of local file + if ($this->getThumbnailType() == self::THUMBNAIL_FILE) { + if (file_exists($this->getThumbnailPath())) + return file_get_contents($this->getThumbnailPath()); + } + // Return content of image stored into zip file + if ($this->getThumbnailType() == self::THUMBNAIL_ZIP) { return $this->thumbnail; + } + // Return null if no thumbnail + return null; } /** * Define the path for the thumbnail file / preview picture. */ - public function setThumbnailPath(string $path = ''): self + public function setThumbnailPath(string $path = '', $type = self::THUMBNAIL_FILE, $content = null) { - if (file_exists($path)) { - $this->thumbnail = $path; + if (file_exists($path) && ($type == self::THUMBNAIL_FILE)) { + $this->thumbnailPath = $path; + $this->thumbnailType = $type; + } + if (($path != '') && ($type == self::THUMBNAIL_ZIP)) { + $this->thumbnailPath = $path; + $this->thumbnailType = $type; + $this->thumbnail = $content; } return $this; } /** - * Mark a document as final. + * Return the thumbnail type + * @return string + */ + public function getThumbnailType() + { + return $this->thumbnailType; + } + + /** + * Mark a document as final */ public function markAsFinal(bool $state = true): self { diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index ef28e3e48..4fa609b51 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -154,6 +154,11 @@ protected function loadFile(string $pFilename): PhpPresentation $this->loadDocumentProperties($docPropsCore); } + $docThumbnail = $this->oZip->getFromName('_rels/.rels'); + if ($docThumbnail !== false) { + $this->loadThumbnailProperties($docThumbnail); + } + $docPropsCustom = $this->oZip->getFromName('docProps/custom.xml'); if (false !== $docPropsCustom) { $this->loadCustomProperties($docPropsCustom); @@ -241,7 +246,28 @@ protected function loadDocumentProperties(string $sPart): void } /** - * Read Custom Properties. + * Read information of the document thumbnail + * @param string $sPart Content of XML file for retrieving data + */ + protected function loadThumbnailProperties($sPart) + { + $xmlReader = new XMLReader(); + if ($xmlReader->getDomFromString($sPart)) { + $oElement = $xmlReader->getElement('*[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); + if ($oElement instanceof \DOMElement) { + $path = $oElement->getAttribute('Target'); + $this->oPhpPresentation + ->getPresentationProperties() + ->setThumbnailPath($path + , \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP + , $this->oZip->getFromName($path)); + } + } + } + + /** + * Read Custom Properties + * @param string $sPart */ protected function loadCustomProperties(string $sPart): void { diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php index 358affd6a..103309e5c 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php @@ -26,8 +26,10 @@ class DocPropsThumbnail extends AbstractDecoratorWriter public function render(): ZipInterface { $pathThumbnail = $this->getPresentation()->getPresentationProperties()->getThumbnailPath(); + $type = $this->getPresentation()->getPresentationProperties()->getThumbnailType(); - if ($pathThumbnail) { + // From local file + if ($pathThumbnail && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_FILE) { $fileThumbnail = file_get_contents($pathThumbnail); $gdImage = imagecreatefromstring($fileThumbnail); if ($gdImage) { @@ -36,7 +38,19 @@ public function render(): ZipInterface $imageContents = ob_get_contents(); ob_end_clean(); imagedestroy($gdImage); - + $this->getZip()->addFromString('docProps/thumbnail.jpeg', $imageContents); + } + } + + // From ZIP original file + if ($pathThumbnail && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP) { + $gdImage = imagecreatefromstring($this->getPresentation()->getPresentationProperties()->getThumbnail()); + if ($gdImage) { + ob_start(); + imagejpeg($gdImage); + $imageContents = ob_get_contents(); + ob_end_clean(); + imagedestroy($gdImage); $this->getZip()->addFromString('docProps/thumbnail.jpeg', $imageContents); } } diff --git a/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php b/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php index 58eb325dd..804c175e2 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php @@ -64,8 +64,11 @@ protected function writeRelationships(): string $idxRelation = 5; // Thumbnail - if ($this->getPresentation()->getPresentationProperties()->getThumbnailPath()) { - $pathThumbnail = file_get_contents($this->getPresentation()->getPresentationProperties()->getThumbnailPath()); + $path = $this->getPresentation()->getPresentationProperties()->getThumbnailPath(); + $type = $this->getPresentation()->getPresentationProperties()->getThumbnailType(); + // From local file + if ($path && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_FILE) { + $pathThumbnail = file_get_contents($path); $gdImage = imagecreatefromstring($pathThumbnail); if ($gdImage) { imagedestroy($gdImage); @@ -73,6 +76,15 @@ protected function writeRelationships(): string $this->writeRelationship($objWriter, $idxRelation, 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail', 'docProps/thumbnail.jpeg'); } } + // From ZIP original file + if ($path && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP) { + $gdImage = imagecreatefromstring($this->getPresentation()->getPresentationProperties()->getThumbnail()); + if ($gdImage) { + imagedestroy($gdImage); + // Relationship docProps/thumbnail.jpeg + $this->writeRelationship($objWriter, $idxRelation, 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail', 'docProps/thumbnail.jpeg'); + } + } // ++$idxRelation $objWriter->endElement(); From 24839e69d72bb6406cc23e36c66a92c203b36a6a Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sun, 16 Aug 2020 18:25:43 +0200 Subject: [PATCH 03/23] BUGFIX whe setting image ressource Sometime when loading PPTX I've some error --- src/PhpPresentation/Shape/Drawing/Gd.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpPresentation/Shape/Drawing/Gd.php b/src/PhpPresentation/Shape/Drawing/Gd.php index 16fa6fe16..690966608 100644 --- a/src/PhpPresentation/Shape/Drawing/Gd.php +++ b/src/PhpPresentation/Shape/Drawing/Gd.php @@ -93,8 +93,8 @@ public function setImageResource($value = null) if (null !== $this->imageResource) { // Get width/height - $this->width = imagesx($this->imageResource); - $this->height = imagesy($this->imageResource); + $this->width = (int)@imagesx($this->imageResource); + $this->height = (int)@imagesy($this->imageResource); } return $this; From 8e8ae7cd7d647fbe8988d2a2e0eeebb5b565f312 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sun, 16 Aug 2020 23:07:13 +0200 Subject: [PATCH 04/23] EVOL Move Shape name to AbstractShape Evolution : - move Shape::name to AbstractShape - add reading name for Shape in PowerPoint2007 --- src/PhpPresentation/AbstractShape.php | 36 +++++++++++++++++-- src/PhpPresentation/Reader/PowerPoint2007.php | 4 +++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index 083154379..380966045 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -110,7 +110,14 @@ abstract class AbstractShape implements ComparableInterface private $hashIndex; /** - * Create a new self. + * Name + * + * @var string + */ + protected $name = ''; + + /** + * Create a new self */ public function __construct() { @@ -118,6 +125,7 @@ public function __construct() $this->fill = new Fill(); $this->shadow = new Shadow(); $this->border = new Border(); + $this->border->setLineStyle(Style\Border::LINE_NONE); } @@ -181,7 +189,31 @@ public function setContainer(?ShapeContainerInterface $pValue = null, $pOverride } /** - * Get OffsetX. + * Get Name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Set Name + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Shape\AbstractGraphic + */ + public function setName($pValue = '') + { + $this->name = $pValue; + return $this; + } + + /** + * Get OffsetX + * + * @return int */ public function getOffsetX(): int { diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index 4fa609b51..1fd51214a 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -933,6 +933,10 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl $this->fileRels = $oSlide->getRelsIndex(); } + $oElement = $document->getElement('p:nvSpPr/p:cNvPr', $node); + if ($oElement instanceof \DOMElement) + $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : ''); + $oElement = $document->getElement('p:spPr/a:xfrm', $node); if ($oElement instanceof DOMElement && $oElement->hasAttribute('rot')) { $oShape->setRotation((int) CommonDrawing::angleToDegrees((int) $oElement->getAttribute('rot'))); From 25c99a20ddb26daee8719fbe7f7d29a15c578b03 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sat, 12 Sep 2020 21:48:07 +0200 Subject: [PATCH 05/23] BUGFIX - Name, in shape, is not preserved if not a placeholder While wrting shape, the name is not preserved if it is not a placehoder --- src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index 5aa7303a7..fd4e3cf63 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -172,7 +172,7 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh if ($shape->isPlaceholder()) { $objWriter->writeAttribute('name', 'Placeholder for ' . $shape->getPlaceholder()->getType()); } else { - $objWriter->writeAttribute('name', ''); + $objWriter->writeAttribute('name', $shape->getName()); } // Hyperlink if ($shape->hasHyperlink()) { From 02318261aac527ce7e29d048ffca536c5376c725 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sat, 12 Sep 2020 21:54:38 +0200 Subject: [PATCH 06/23] CHG-Load also richtext shape without text It seems tha Powerpoint 2007 use also richtext to define rectangle with or without text. So keep loading richtext without text --- src/PhpPresentation/Reader/PowerPoint2007.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index 1fd51214a..e2a078673 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -922,9 +922,6 @@ protected function loadShapeDrawing(XMLReader $document, DOMElement $node, Abstr */ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSlide): void { - if (!$document->elementExists('p:txBody/a:p/a:r', $node)) { - return; - } // Core $oShape = $oSlide->createRichTextShape(); $oShape->setParagraphs([]); From 3f1ff7bc140e760682b1f86e1787599c3c748462 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sat, 12 Sep 2020 22:55:04 +0200 Subject: [PATCH 07/23] ADD-Preserve shape properties (background color, etc.) for richttext When loading richt text shape, read also properties who defining backgroupnd color, border color, etc. use loadStyleFill function --- src/PhpPresentation/Reader/PowerPoint2007.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index e2a078673..b0451bae1 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -974,6 +974,12 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl } } + $oElement = $document->getElement('p:spPr', $node); + if ($oElement instanceof \DOMElement) { + $oFill = $this->loadStyleFill($document, $oElement); + $oShape->setFill($oFill); + } + if (count($oShape->getParagraphs()) > 0) { $oShape->setActiveParagraph(0); } From b237d340fae617077aaa593476b8d2e91d890076 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sat, 12 Sep 2020 23:17:59 +0200 Subject: [PATCH 08/23] ADD-Shape RichtText preserve spelling lang while loading When loading a ric text shape, get the spelling lang --- src/PhpPresentation/Reader/PowerPoint2007.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index b0451bae1..142f0341e 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -1246,6 +1246,9 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh if ($oElementrPr->hasAttribute('cap')) { $oText->getFont()->setCapitalization($oElementrPr->getAttribute('cap')); } + if ($oElementrPr->hasAttribute('lang')) { + $oText->setLanguage($oElementrPr->getAttribute('lang')); + } // Color $oElementSrgbClr = $document->getElement('a:solidFill/a:srgbClr', $oElementrPr); if (is_object($oElementSrgbClr) && $oElementSrgbClr->hasAttribute('val')) { From cef70f6a76c14690803a4d4f77c1027fedadbac1 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sun, 13 Sep 2020 00:01:17 +0200 Subject: [PATCH 09/23] ADD-Preserve shape richtext font face while loading file Add reading typeface while load file in shape richt text Preserving loading to save --- src/PhpPresentation/Reader/PowerPoint2007.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index 142f0341e..115694ac7 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -1283,8 +1283,14 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh if (is_object($oElementFontFormat) && $oElementFontFormat->hasAttribute('typeface')) { $oText->getFont()->setName($oElementFontFormat->getAttribute('typeface')); } - - //} else { + // Font definition + $oElementFont = $document->getElement('a:latin', $oElementrPr); + if (is_object($oElementFont)) { + if ($oElementFont->hasAttribute('typeface')) { + $oText->getFont()->setName($oElementFont->getAttribute('typeface')); + } + } + //} else { // $oText = $oParagraph->createText(); $oSubSubElement = $document->getElement('a:t', $oSubElement); From 33c46190af8a283c59b1b737d84d8458196cdf9d Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sun, 13 Sep 2020 12:58:15 +0200 Subject: [PATCH 10/23] EVOL-Allow different style of strick paragraph Paragraph double strick were not supported, modification has been done to support different strick type --- src/PhpPresentation/Reader/PowerPoint2007.php | 2 +- src/PhpPresentation/Style/Font.php | 6 +++++- src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index 115694ac7..368780ee9 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -1235,7 +1235,7 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh $oText->getFont()->setItalic('true' == $att || '1' == $att ? true : false); } if ($oElementrPr->hasAttribute('strike')) { - $oText->getFont()->setStrikethrough('noStrike' == $oElementrPr->getAttribute('strike') ? false : true); + $oText->getFont()->setStrikethrough($oElementrPr->getAttribute('strike')); } if ($oElementrPr->hasAttribute('sz')) { $oText->getFont()->setSize((int) ((int) $oElementrPr->getAttribute('sz') / 100)); diff --git a/src/PhpPresentation/Style/Font.php b/src/PhpPresentation/Style/Font.php index 2ba0bca7c..5a4ca7951 100644 --- a/src/PhpPresentation/Style/Font.php +++ b/src/PhpPresentation/Style/Font.php @@ -149,6 +149,7 @@ class Font implements ComparableInterface public function __construct() { $this->color = new Color(Color::COLOR_BLACK); + $this->strikethrough = 'noStrike'; } /** @@ -344,8 +345,11 @@ public function isStrikethrough(): bool /** * Set Strikethrough. */ - public function setStrikethrough(bool $pValue = false): self + public function setStrikethrough($pValue = 'noStrike') { + if ($pValue == '') { + $pValue = 'noStrike'; + } $this->strikethrough = $pValue; return $this; diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index fd4e3cf63..71b0762f6 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -649,7 +649,7 @@ protected function writeRunStyles(XMLWriter $objWriter, RichText\Run $element): $objWriter->writeAttributeIf($element->getFont()->isBold(), 'b', '1'); $objWriter->writeAttributeIf($element->getFont()->isItalic(), 'i', '1'); - $objWriter->writeAttributeIf($element->getFont()->isStrikethrough(), 'strike', 'sngStrike'); + $objWriter->writeAttributeIf($element->getFont()->isStrikethrough(), 'strike', $element->getFont()->isStrikethrough()); // Size $objWriter->writeAttribute('sz', ($element->getFont()->getSize() * 100)); From cd9a17ff227a97443668efbba9fd5f9577824da8 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sun, 13 Sep 2020 13:05:03 +0200 Subject: [PATCH 11/23] EVOL-Define const for strike types --- src/PhpPresentation/Style/Font.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/PhpPresentation/Style/Font.php b/src/PhpPresentation/Style/Font.php index 5a4ca7951..566fdc104 100644 --- a/src/PhpPresentation/Style/Font.php +++ b/src/PhpPresentation/Style/Font.php @@ -46,6 +46,11 @@ class Font implements ComparableInterface public const UNDERLINE_WAVYDOUBLE = 'wavyDbl'; public const UNDERLINE_WAVYHEAVY = 'wavyHeavy'; public const UNDERLINE_WORDS = 'words'; + + /* Strike types */ + public const STRIKE_NONE = 'noStrike'; + public const STRIKE_SINGLE = 'sngStrike'; + public const STRIKE_DOUBLE = 'dblStrike'; public const FORMAT_LATIN = 'latin'; public const FORMAT_EAST_ASIAN = 'ea'; @@ -149,7 +154,7 @@ class Font implements ComparableInterface public function __construct() { $this->color = new Color(Color::COLOR_BLACK); - $this->strikethrough = 'noStrike'; + $this->strikethrough = self::STRIKE_NONE; } /** @@ -345,10 +350,10 @@ public function isStrikethrough(): bool /** * Set Strikethrough. */ - public function setStrikethrough($pValue = 'noStrike') + public function setStrikethrough($pValue = self::STRIKE_NONE) { if ($pValue == '') { - $pValue = 'noStrike'; + $pValue = self::STRIKE_NONE; } $this->strikethrough = $pValue; From 5aecc8d87c72e3912809c8f6dac5c0e2e85303d7 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Sun, 13 Sep 2020 13:39:40 +0200 Subject: [PATCH 12/23] EVOL-Super script and sub script for paragraph Using true/fasle and default value 300000 or -250000 are too mutch (in Office 365). So when reading, get values setted by PowerPoint and modify default values into the code to set values seen during my tests --- src/PhpPresentation/Reader/PowerPoint2007.php | 7 +++ src/PhpPresentation/Style/Font.php | 46 +++++++++++++++---- .../Writer/PowerPoint2007/AbstractSlide.php | 4 +- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index 368780ee9..ef5733a20 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -1249,6 +1249,13 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh if ($oElementrPr->hasAttribute('lang')) { $oText->setLanguage($oElementrPr->getAttribute('lang')); } + if ($oElementrPr->hasAttribute('baseline')) { + if ((int)$oElementrPr->getAttribute('baseline')>0) { + $oText->getFont()->setSuperScript((int)$oElementrPr->getAttribute('baseline')); + } else if ((int)$oElementrPr->getAttribute('baseline')<0) { + $oText->getFont()->setSubScript((int)$oElementrPr->getAttribute('baseline')); + } + } // Color $oElementSrgbClr = $document->getElement('a:solidFill/a:srgbClr', $oElementrPr); if (is_object($oElementSrgbClr) && $oElementSrgbClr->hasAttribute('val')) { diff --git a/src/PhpPresentation/Style/Font.php b/src/PhpPresentation/Style/Font.php index 566fdc104..44f95548e 100644 --- a/src/PhpPresentation/Style/Font.php +++ b/src/PhpPresentation/Style/Font.php @@ -59,6 +59,10 @@ class Font implements ComparableInterface public const CAPITALIZATION_NONE = 'none'; public const CAPITALIZATION_SMALL = 'small'; public const CAPITALIZATION_ALL = 'all'; + + /* Script sub and super values */ + const SCRIPT_SUPER = 30000; + const SCRIPT_SUB = -25000; /** * Name. @@ -154,6 +158,8 @@ class Font implements ComparableInterface public function __construct() { $this->color = new Color(Color::COLOR_BLACK); + $this->superScript = 0; + $this->subScript = 0; $this->strikethrough = self::STRIKE_NONE; } @@ -254,38 +260,60 @@ public function setItalic(bool $pValue = false): self /** * Get SuperScript. */ - public function isSuperScript(): bool + public function isSuperScript(): int { return $this->superScript; } /** - * Set SuperScript. + * Set SuperScript + * + * @param integer $pValue + * @return \PhpOffice\PhpPresentation\Style\Font */ - public function setSuperScript(bool $pValue = false): self + public function setSuperScript($pValue = 0) { + if ($pValue == '') { + $pValue = 0; + } + $this->superScript = $pValue; // Set SubScript at false only if SuperScript is true - if (true === $pValue) { - $this->subScript = false; + if ($pValue != 0) { + $this->subScript = 0; } return $this; } - public function isSubScript(): bool + /** + * Get SubScript + * + * @return integer + */ + public function isSubScript() { return $this->subScript; } - public function setSubScript(bool $pValue = false): self + /** + * Set SubScript + * + * @param integer $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setSubScript($pValue = 0) { + if ($pValue == '') { + $pValue = 0; + } + $this->subScript = $pValue; // Set SuperScript at false only if SubScript is true - if (true === $pValue) { - $this->superScript = false; + if ($pValue != 0) { + $this->superScript = 0; } return $this; diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index 71b0762f6..d85cf2d95 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -664,8 +664,8 @@ protected function writeRunStyles(XMLWriter $objWriter, RichText\Run $element): $objWriter->writeAttribute('cap', $element->getFont()->getCapitalization()); // Superscript / subscript - $objWriter->writeAttributeIf($element->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($element->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($element->getFont()->isSuperScript() != 0, 'baseline', (int)$element->getFont()->isSuperScript()); + $objWriter->writeAttributeIf($element->getFont()->isSubScript() != 0, 'baseline', (int)$element->getFont()->isSubScript()); // Color - a:solidFill $objWriter->startElement('a:solidFill'); From afc58c0fe7084c39e4359d48bd96d8c6c361896a Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Wed, 27 Jan 2021 20:27:38 +0100 Subject: [PATCH 13/23] ADD Property 'status' reading and writing ADD the 'status' properties for reading and wrinting into the document --- src/PhpPresentation/DocumentProperties.php | 33 ++++++++++++++++++- src/PhpPresentation/Reader/PowerPoint2007.php | 1 + .../Writer/PowerPoint2007/DocPropsCore.php | 3 ++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/PhpPresentation/DocumentProperties.php b/src/PhpPresentation/DocumentProperties.php index cbcd052eb..c6a24e453 100644 --- a/src/PhpPresentation/DocumentProperties.php +++ b/src/PhpPresentation/DocumentProperties.php @@ -116,7 +116,14 @@ class DocumentProperties private $customProperties = []; /** - * Create a new \PhpOffice\PhpPresentation\DocumentProperties. + * status + * + * @var string + */ + private $status; + + /** + * Create a new \PhpOffice\PhpPresentation\DocumentProperties */ public function __construct() { @@ -132,6 +139,7 @@ public function __construct() $this->category = ''; $this->company = 'Microsoft Corporation'; $this->revision = ''; + $this->status = ''; } /** @@ -479,4 +487,27 @@ public function setRevision(string $pValue = ''): self return $this; } + + /** + * Get Status + * + * @return string + */ + public function getStatus() + { + return $this->status; + } + + /** + * Set Status + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\DocumentProperties + */ + public function setStatus($pValue = '') + { + $this->status = $pValue; + + return $this; + } } diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index ef5733a20..d7af17130 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -229,6 +229,7 @@ protected function loadDocumentProperties(string $sPart): void '/cp:coreProperties/dcterms:created' => 'setCreated', '/cp:coreProperties/dcterms:modified' => 'setModified', '/cp:coreProperties/cp:revision' => 'setRevision', + '/cp:coreProperties/cp:contentStatus' => 'setStatus', ); $oProperties = $this->oPhpPresentation->getDocumentProperties(); foreach ($arrayProperties as $path => $property) { diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php index afd8c08d2..6df85cde0 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php @@ -73,6 +73,9 @@ public function render(): ZipInterface // cp:revision $objWriter->writeElement('cp:revision', $this->oPresentation->getDocumentProperties()->getRevision()); + // cp:contentStatus + $objWriter->writeElement('cp:contentStatus', $this->oPresentation->getDocumentProperties()->getStatus()); + // cp:category $objWriter->writeElement('cp:category', $this->oPresentation->getDocumentProperties()->getCategory()); From db96a0af77f56d3f85aababde7b3ce1f1802ec8f Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Mon, 1 Feb 2021 17:19:32 +0100 Subject: [PATCH 14/23] BUGFIX while cloning an existant slide BUGFIX while cloning an existant slide : - considere if existing object - cloning each object into collection - cloning each paragraph for RichText --- src/PhpPresentation/AbstractShape.php | 19 ++++++++++++++++--- src/PhpPresentation/Shape/RichText.php | 18 +++++++++++++++++- src/PhpPresentation/Slide.php | 23 +++++++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index 380966045..26d9dc8a0 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -135,9 +135,22 @@ public function __construct() public function __clone() { $this->container = null; - $this->fill = clone $this->fill; - $this->border = clone $this->border; - $this->shadow = clone $this->shadow; + $this->name = $this->name; + if (isset($this->fill)) { + $this->fill = clone $this->fill; + } + if (isset($this->border)) { + $this->border = clone $this->border; + } + if (isset($this->shadow)) { + $this->shadow = clone $this->shadow; + } + if (isset($this->placeholder)) { + $this->placeholder = clone $this->placeholder; + } + if (isset($this->hyperlink)) { + $this->hyperlink = clone $this->hyperlink; + } } /** diff --git a/src/PhpPresentation/Shape/RichText.php b/src/PhpPresentation/Shape/RichText.php index 59fc22140..8c717bc83 100644 --- a/src/PhpPresentation/Shape/RichText.php +++ b/src/PhpPresentation/Shape/RichText.php @@ -185,7 +185,23 @@ public function __construct() } /** - * Get active paragraph index. + * Magic Method : clone + */ + public function __clone() + { + // Call perent clonage for heritage + parent::__clone(); + // Clone each paragraph + if (isset($this->richTextParagraphs)) { + foreach ($this->richTextParagraphs as &$paragraph) { + $paragraph = clone $paragraph; + }} + } + + /** + * Get active paragraph index + * + * @return int */ public function getActiveParagraphIndex(): int { diff --git a/src/PhpPresentation/Slide.php b/src/PhpPresentation/Slide.php index 345e24bba..150e14426 100644 --- a/src/PhpPresentation/Slide.php +++ b/src/PhpPresentation/Slide.php @@ -132,6 +132,29 @@ public function setSlideMasterId($masterId = 1) return $this; } + + public function __clone() + { + // Set parent + $this->parent = clone $this->parent; + // Shape collection + if (isset($this->shapeCollection)) { + $this->shapeCollection = clone $this->shapeCollection; + foreach ($this->shapeCollection as &$shape) { + $shape = clone $shape; + } + } + // Transition object + if (isset($this->slideTransition)) { + $this->slideTransition = clone $this->slideTransition; + } + // Note object + if (isset($this->slideNote)) { + $this->slideNote = clone $this->slideNote; + } + + } + /** * Copy slide (!= clone!). * From 9f3f6868ba584d65fbfe0d0b80ee6e3d04ca0169 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Tue, 2 Feb 2021 15:53:57 +0100 Subject: [PATCH 15/23] ADD Read also texte zone margin RLTB ADD Read also from original PPTX mragin of shape (left,right,top,bottom) Writing already existing and object have been initialized by default (so now setted by reading existing file) --- src/PhpPresentation/Reader/PowerPoint2007.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index d7af17130..f4c80d63e 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -968,6 +968,20 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl } } + $bodyPr = $document->getElement('p:txBody/a:bodyPr', $node); + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('lIns')) { + $oShape->setInsetLeft((int)$bodyPr->getAttribute('lIns')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('tIns')) { + $oShape->setInsetTop((int)$bodyPr->getAttribute('tIns')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('rIns')) { + $oShape->setInsetRight((int)$bodyPr->getAttribute('rIns')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('bIns')) { + $oShape->setInsetBottom((int)$bodyPr->getAttribute('bIns')); + } + $arrayElements = $document->getElements('p:txBody/a:p', $node); foreach ($arrayElements as $oElement) { if ($oElement instanceof DOMElement) { From cdaa211973fb315504d4bb07c64c8b09aca661fb Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Tue, 2 Feb 2021 17:03:05 +0100 Subject: [PATCH 16/23] ADD Vertical alignment for shape RichText ADD Vertical alignment for RichText position top,middle and bottom position center or not center Reading from file, editing and saving --- src/PhpPresentation/Reader/PowerPoint2007.php | 6 ++ src/PhpPresentation/Shape/RichText.php | 73 +++++++++++++++++++ .../Writer/PowerPoint2007/AbstractSlide.php | 5 +- 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index f4c80d63e..f077d02db 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -981,6 +981,12 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('bIns')) { $oShape->setInsetBottom((int)$bodyPr->getAttribute('bIns')); } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('anchor')) { + $oShape->setVerticalAlignment($bodyPr->getAttribute('anchor')); + } + if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('anchorCtr')) { + $oShape->setVerticalAlignCenter((int)$bodyPr->getAttribute('anchorCtr')); + } $arrayElements = $document->getElements('p:txBody/a:p', $node); foreach ($arrayElements as $oElement) { diff --git a/src/PhpPresentation/Shape/RichText.php b/src/PhpPresentation/Shape/RichText.php index 8c717bc83..86f75c924 100644 --- a/src/PhpPresentation/Shape/RichText.php +++ b/src/PhpPresentation/Shape/RichText.php @@ -43,6 +43,15 @@ class RichText extends AbstractShape implements ComparableInterface /** Overflow */ public const OVERFLOW_CLIP = 'clip'; public const OVERFLOW_OVERFLOW = 'overflow'; + + /** Vertical alignment */ + const VALIGN_TOP = 't'; + const VALIGN_MIDDLE = 'ctr'; + const VALIGN_BOTTOM = 'b'; + + /** Vertical alignment center */ + const VALIGN_CENTER = 1; + const VALIGN_NOTCENTER = 0; /** * Rich text paragraphs. @@ -169,6 +178,17 @@ class RichText extends AbstractShape implements ComparableInterface * @var null|float */ private $lnSpcReduction; + + /** + * Define vertical text position into shape (top,center,bottom) + * @var string + */ + private $verticalAlign = self::VALIGN_TOP; + /** + * Define vertical text center position into shape (center,not center) + * @var int + */ + private $verticalAlignCenter = self::VALIGN_NOTCENTER; /** * Create a new \PhpOffice\PhpPresentation\Shape\RichText instance. @@ -486,6 +506,59 @@ public function setVertical(bool $value = false): self return $this; } + + /** + * Define the vertical alignment + * + * @param string|null $value top,center,bottom + * @return $this + * @see self::VALIGN_TOP, self::VALIGN_MIDLE, self::VALIGN_BOTTOM + */ + public function setVerticalAlignment(?string $value) + { + if (isset($value)) { + $this->verticalAlign = $value; + } else { + $this->verticalAlign = self::VALIGN_TOP; + } + return $this; + } + + /** + * Get the vertical alignment + * + * @return string + * @see self::VALIGN_TOP, self::VALIGN_MIDLE, self::VALIGN_BOTTOM + */ + public function getVerticalAlignment():string + { + return $this->verticalAlign; + } + + /** + * Define the vertical alignment if centered or not + * @param int|null $value 1=center 0=not center + * @return $this + * @see self::VALIGN_CENTER, self::VALIGN_NOTCENTER + */ + public function setVerticalAlignCenter(?int $value) + { + if (isset($value)) { + $this->verticalAlignCenter = $value; + } else { + $this->verticalAlignCenter = self::VALIGN_NOTCENTER; + } + return $this; + } + + /** + * Get the vertical alignment center + * @return int + */ + public function getVerticalAlignCenter():int + { + return $this->verticalAlignCenter; + } /** * Get columns. diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index d85cf2d95..58e383e92 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -262,7 +262,10 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh $objWriter->writeAttribute('lIns', CommonDrawing::pixelsToEmu($shape->getInsetLeft())); $objWriter->writeAttribute('rIns', CommonDrawing::pixelsToEmu($shape->getInsetRight())); $objWriter->writeAttribute('tIns', CommonDrawing::pixelsToEmu($shape->getInsetTop())); - if (1 != $shape->getColumns()) { + // Vertical alignment + $objWriter->writeAttribute('anchor', $shape->getVerticalAlignment()); + $objWriter->writeAttribute('anchorCtr', (int)$shape->getVerticalAlignCenter()); + if ($shape->getColumns() <> 1) { $objWriter->writeAttribute('numCol', $shape->getColumns()); $objWriter->writeAttribute('spcCol', CommonDrawing::pixelsToEmu($shape->getColumnSpacing())); } From 3dfc5f53ae22ffcf2775a928f5b597356eff91d2 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Wed, 3 Feb 2021 00:08:24 +0100 Subject: [PATCH 17/23] ADD Effect managment to Shape,Paragraph and Text ADD Effect mangment Effect is a collection of effect into each element (innerShadow, outerShadow, reflection, glos, etc. Actualy only shadow are supported, but the strucure is desgin for other effect --- src/PhpPresentation/AbstractShape.php | 49 ++- src/PhpPresentation/Reader/PowerPoint2007.php | 127 ++++--- .../Shape/RichText/Paragraph.php | 51 ++- src/PhpPresentation/Shape/RichText/Run.php | 51 ++- src/PhpPresentation/Style/Effect.php | 310 ++++++++++++++++++ .../Writer/PowerPoint2007/AbstractSlide.php | 54 ++- 6 files changed, 598 insertions(+), 44 deletions(-) create mode 100644 src/PhpPresentation/Style/Effect.php diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index 26d9dc8a0..d93596156 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -103,7 +103,13 @@ abstract class AbstractShape implements ComparableInterface protected $placeholder; /** - * Hash index. + * List of effect apply to shape + * @var array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected ?array $effectCollection = null; + + /** + * Hash index * * @var int */ @@ -125,6 +131,7 @@ public function __construct() $this->fill = new Fill(); $this->shadow = new Shadow(); $this->border = new Border(); + $this->effectCollection = null; $this->border->setLineStyle(Style\Border::LINE_NONE); } @@ -411,6 +418,46 @@ public function setHyperlink(?Hyperlink $pHyperlink = null): self return $this; } + + /** + * Add an effect to the shpae + * + * @param \PhpOffice\PhpPresentation\Style\Effect $effect + * @return $this + */ + public function addEffect(Shape\Effect $effect) + { + if (!isset($this->effectCollection)) { + $this->effectCollection = array(); + } + $this->effectCollection[] = $effect; + return $this; + } + + /** + * Get the effect collection + * + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + public function getEffectCollection():?array + { + return $this->effectCollection; + } + + /** + * Set the effect collection + * + * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection + * @return $this + */ + public function setEffectCollection(array $effectCollection) + { + if ( isset($effectCollection) + && is_array($effectCollection)) { + $this->effectCollection = $effectCollection; + } + return $this; + } /** * Get hash code. diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index f077d02db..819fb5de4 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -877,46 +877,81 @@ protected function loadShapeDrawing(XMLReader $document, DOMElement $node, Abstr $oShape->setHeight(CommonDrawing::emuToPixels((int) $oElement->getAttribute('cy'))); } } - - $oElement = $document->getElement('p:spPr/a:effectLst', $node); - if ($oElement instanceof DOMElement) { - $oShape->getShadow()->setVisible(true); - - $oSubElement = $document->getElement('a:outerShdw', $oElement); - if ($oSubElement instanceof DOMElement) { - if ($oSubElement->hasAttribute('blurRad')) { - $oShape->getShadow()->setBlurRadius(CommonDrawing::emuToPixels((int) $oSubElement->getAttribute('blurRad'))); - } - if ($oSubElement->hasAttribute('dist')) { - $oShape->getShadow()->setDistance(CommonDrawing::emuToPixels((int) $oSubElement->getAttribute('dist'))); - } - if ($oSubElement->hasAttribute('dir')) { - $oShape->getShadow()->setDirection((int) CommonDrawing::angleToDegrees((int) $oSubElement->getAttribute('dir'))); - } - if ($oSubElement->hasAttribute('algn')) { - $oShape->getShadow()->setAlignment($oSubElement->getAttribute('algn')); - } - } - - $oSubElement = $document->getElement('a:outerShdw/a:srgbClr', $oElement); - if ($oSubElement instanceof DOMElement) { - if ($oSubElement->hasAttribute('val')) { - $oColor = new Color(); - $oColor->setRGB($oSubElement->getAttribute('val')); - $oShape->getShadow()->setColor($oColor); - } - } - - $oSubElement = $document->getElement('a:outerShdw/a:srgbClr/a:alpha', $oElement); - if ($oSubElement instanceof DOMElement) { - if ($oSubElement->hasAttribute('val')) { - $oShape->getShadow()->setAlpha((int) $oSubElement->getAttribute('val') / 1000); - } - } + // Load shape effects + $oEffect = $document->getElement('p:spPr/a:effectLst', $node); + if ($oEffect instanceof \DOMElement) { + $aEffect = $this->loadEffect($document, $oEffect); + if (isset($aEffect) && is_array($aEffect)) { + $oShape->setEffectCollection($aEffect); + } } - $oSlide->addShape($oShape); } + + /** + * Load Effect for shape or paragraph + * + * @param XMLReader $document + * @param \DOMElement $node + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected function loadEffect(XMLReader $document, \DOMElement $nodeEffect) + { + $aEffect = null; + if ($nodeEffect instanceof \DOMElement) { + + $aNodes = $document->getElements('*', $nodeEffect); + foreach ($aNodes as $node) { + + $type = explode(':', $node->tagName); + $type = array_pop($type); + if ( $type == 'outerShdw' + || $type == 'innerShdw') { +// @TODO || $type == 'reflection') { + + // Create a new effect + $effect = new \PhpOffice\PhpPresentation\Style\Effect($type); + // load blur radius + if ($node->hasAttribute('blurRad')) { + $effect->setBlurRadius(CommonDrawing::emuToPixels($node->getAttribute('blurRad'))); + } + // load distance + if ($node->hasAttribute('dist')) { + $effect->setDistance(CommonDrawing::emuToPixels($node->getAttribute('dist'))); + } + // load direction + if ($node->hasAttribute('dir')) { + $effect->setDirection(CommonDrawing::angleToDegrees($node->getAttribute('dir'))); + } + // load alignment + if ($node->hasAttribute('algn')) { + $effect->setAlignment($node->getAttribute('algn')); + } + + // Get color define by prstClr + $oSubElement = $document->getElement('a:prstClr', $node); + if ($oSubElement instanceof \DOMElement && $oSubElement->hasAttribute('val')) { + $oColor = new Color(); + $oColor->setRGB($oSubElement->getAttribute('val')); + $effect->setColor($oColor); + // Get Alpha + $oSubElt = $document->getElement('a:alpha', $oSubElement); + if ($oSubElt instanceof \DOMElement && $oSubElt->hasAttribute('val')) { + $effect->setAlpha((int)$oSubElt->getAttribute('val') / 1000); + } + } + // Load reflection atributs +// @TODO future implementation + if ($node->tagName == 'a:reflection') { + } + + if (!isset($aEffect)) $aEffect = array(); + $aEffect[] = $effect; + } + } + } + return $aEffect; + } /** * @param AbstractSlide|Note $oSlide @@ -968,6 +1003,16 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl } } + // Load shape effects + $oEffect = $document->getElement('p:spPr/a:effectLst', $node); + if ($oEffect instanceof \DOMElement) { + $aEffect = $this->loadEffect($document, $oEffect); + if (isset($aEffect) && is_array($aEffect)) { + $oShape->setEffectCollection($aEffect); + } + } + +// FBU-20210202+ Read body definitions $bodyPr = $document->getElement('p:txBody/a:bodyPr', $node); if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('lIns')) { $oShape->setInsetLeft((int)$bodyPr->getAttribute('lIns')); @@ -1317,6 +1362,14 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh if ($oElementFont->hasAttribute('typeface')) { $oText->getFont()->setName($oElementFont->getAttribute('typeface')); } + } + // Load shape effects + $oEffect = $document->getElement('a:effectLst', $oElementrPr); + if ($oEffect instanceof \DOMElement) { + $aEffect = $this->loadEffect($document, $oEffect); + if (isset($aEffect) && is_array($aEffect)) { + $oText->setEffectCollection($aEffect); + } } //} else { // $oText = $oParagraph->createText(); diff --git a/src/PhpPresentation/Shape/RichText/Paragraph.php b/src/PhpPresentation/Shape/RichText/Paragraph.php index b1d80f8d2..8f9e02652 100644 --- a/src/PhpPresentation/Shape/RichText/Paragraph.php +++ b/src/PhpPresentation/Shape/RichText/Paragraph.php @@ -66,6 +66,14 @@ class Paragraph implements ComparableInterface private $lineSpacing = 100; /** + * List of effect apply to paragraph + * @var array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected ?array $effectCollection = null; + + /** + * Hash index + * * @var string */ private $lineSpacingMode = self::LINE_SPACING_MODE_PERCENT; @@ -95,6 +103,7 @@ public function __construct() $this->alignment = new Alignment(); $this->font = new Font(); $this->bulletStyle = new Bullet(); + $this->effectCollection = null; } /** @@ -255,7 +264,47 @@ public function setRichTextElements(array $pElements = []): self } /** - * Get hash code. + * Add an effect to the shpae + * + * @param \PhpOffice\PhpPresentation\Style\Effect $effect + * @return $this + */ + public function addEffect(Shape\Effect $effect) + { + if (!isset($this->effectCollection)) { + $this->effectCollection = array(); + } + $this->effectCollection[] = $effect; + return $this; + } + + /** + * Get the effect collection + * + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + public function getEffectCollection():?array + { + return $this->effectCollection; + } + + /** + * Set the effect collection + * + * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection + * @return $this + */ + public function setEffectCollection(array $effectCollection) + { + if ( isset($effectCollection) + && is_array($effectCollection)) { + $this->effectCollection = $effectCollection; + } + return $this; + } + + /** + * Get hash code * * @return string Hash code */ diff --git a/src/PhpPresentation/Shape/RichText/Run.php b/src/PhpPresentation/Shape/RichText/Run.php index ba8fc12a5..e4528acb6 100644 --- a/src/PhpPresentation/Shape/RichText/Run.php +++ b/src/PhpPresentation/Shape/RichText/Run.php @@ -34,7 +34,13 @@ class Run extends TextElement implements TextElementInterface private $font; /** - * Create a new \PhpOffice\PhpPresentation\Shape\RichText\Run instance. + * List of effect apply to paragraph + * @var array \PhpOffice\PhpPresentation\Style\Effect[] + */ + protected ?array $effectCollection = null; + + /** + * Create a new \PhpOffice\PhpPresentation\Shape\RichText\Run instance * * @param string $pText Text */ @@ -43,6 +49,7 @@ public function __construct($pText = '') // Initialise variables $this->setText($pText); $this->font = new Font(); + $this->effectCollection = null; } /** @@ -68,7 +75,47 @@ public function setFont(?Font $pFont = null) } /** - * Get hash code. + * Add an effect to the shpae + * + * @param \PhpOffice\PhpPresentation\Style\Effect $effect + * @return $this + */ + public function addEffect(Shape\Effect $effect) + { + if (!isset($this->effectCollection)) { + $this->effectCollection = array(); + } + $this->effectCollection[] = $effect; + return $this; + } + + /** + * Get the effect collection + * + * @return array \PhpOffice\PhpPresentation\Style\Effect[] + */ + public function getEffectCollection():?array + { + return $this->effectCollection; + } + + /** + * Set the effect collection + * + * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection + * @return $this + */ + public function setEffectCollection(array $effectCollection) + { + if ( isset($effectCollection) + && is_array($effectCollection)) { + $this->effectCollection = $effectCollection; + } + return $this; + } + + /** + * Get hash code * * @return string Hash code */ diff --git a/src/PhpPresentation/Style/Effect.php b/src/PhpPresentation/Style/Effect.php new file mode 100644 index 000000000..5c25ca4f4 --- /dev/null +++ b/src/PhpPresentation/Style/Effect.php @@ -0,0 +1,310 @@ +effectType = $type; + $this->blurRadius = 6; + $this->distance = 2; + $this->direction = 0; + $this->alignment = self::SHADOW_BOTTOM_RIGHT; + $this->color = new Color(Color::COLOR_BLACK); + $this->alpha = 50; + } + + /** + * Define the type effect + * + * @param string $type + * @return $this + * @see self::EFFECT_SHADOW_INNER, self::EFFECT_SHADOW_OUTER, self::EFFECT_REFLECTION + */ + public function setEffectType(string $type) + { + $this->effectType = $type; + return $this; + } + + /** + * Get the effect type + * + * @return string + */ + public function getEffectType():string + { + return $this->effectType; + } + + /** + * Set the direction + * + * @param int $dir + * @return $this + */ + public function setDirection(?int $dir) + { + if (!isset($dir)) $dir = 0; + $this->direction = (int)$dir; + return $this; + } + + /** + * Get the direction + * + * @return int + */ + public function getDirection():int + { + return $this->direction; + } + + /** + * Set the blur radius + * + * @param int $radius + * @return $this + */ + public function setBlurRadius(?int $radius) + { + if (!isset($radius)) $radius = 6; + $this->blurRadius = $radius; + return $this; + } + + /** + * Get the blur radius + * + * @return int + */ + public function getBlurRadius():int + { + return $this->blurRadius; + } + + /** + * Get Shadow distance + * + * @return int + */ + public function getDistance():int + { + return $this->distance; + } + + /** + * Set Shadow distance + * + * @param int $distance + * @return $this + */ + public function setDistance(int $distance = 2) + { + $this->distance = $distance; + + return $this; + } + + /** + * Set the effect alignment + * + * @param string $align + * @return $this + */ + public function setAlignment(?string $align) + { + if (!isset($align)) $align = self::SHADOW_BOTTOM_RIGHT; + $this->align = $align; + return $this; + } + + /** + * Get the effect alignment + * + * @return string + */ + public function getAlignment():string + { + return $this->align; + } + + /** + * Set Color + * + * @param \PhpOffice\PhpPresentation\Style\Color $color + * @return $this + */ + public function setColor(Color $color = null) + { + $this->color = $color; + + return $this; + } + + /** + * Get Color + * + * @return \PhpOffice\PhpPresentation\Style\Color + */ + public function getColor() + { + return $this->color; + } + + /** + * Set Alpha + * + * @param int $alpha + * @return $this + */ + public function setAlpha(?int $alpha) + { + if (!isset($alpha)) $alpha = 0; + $this->alpha = $alpha; + + return $this; + } + + /** + * Get Alpha + * + * @return int + */ + public function getAlpha():int + { + return $this->alpha; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + return md5($this->effectType . $this->blurRadius . $this->distance . $this->direction . $this->alignment . $this->color->getHashCode() . $this->alpha . __CLASS__); + } + + /** + * Get hash index + * + * Note that this index may vary during script execution! Only reliable moment is + * while doing a write of a workbook and when changes are not allowed. + * + * @return string Hash index + */ + public function getHashIndex() + { + return $this->hashIndex; + } + + /** + * Set hash index + * + * Note that this index may vary during script execution! Only reliable moment is + * while doing a write of a workbook and when changes are not allowed. + * + * @param string $value Hash index + */ + public function setHashIndex($value) + { + $this->hashIndex = $value; + } + +} diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index 58e383e92..bce5218a0 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -228,7 +228,7 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh $this->writeFill($objWriter, $shape->getFill()); $this->writeBorder($objWriter, $shape->getBorder(), ''); - $this->writeShadow($objWriter, $shape->getShadow()); + $this->writeEffect($objWriter, $shape->getEffectCollection()); // > p:sp\p:spPr $objWriter->endElement(); @@ -809,7 +809,55 @@ protected function writeShadow(XMLWriter $objWriter, Shadow $oShadow): void } /** - * Write hyperlink. + * Write Effect + * @param XMLWriter $objWriter + * @param array \PhpOffice\PhpPresentation\Style\Effect[] + * @param Shadow $oShadow + */ + protected function writeEffect(XMLWriter $objWriter, ?array $aEffect, ?string $tagClr=null) + { + // NO Effect => return + if (!isset($aEffect) && !is_array($aEffect)) { + return; + } + if (!isset($tagClr)) { + $tagClr = 'prstClr'; + } + + // a:effectLst + $objWriter->startElement('a:effectLst'); + // Write each effect + foreach($aEffect as $effect) { + // a: + if ( $effect->getEffectType() == 'outerShdw' + || $effect->getEffectType() == 'innerShdw') { +// @TODO || $effect->getEffectType() == 'reflection') { + + $objWriter->startElement('a:'.$effect->getEffectType()); + $objWriter->writeAttribute('blurRad', CommonDrawing::pixelsToEmu($effect->getBlurRadius())); + $objWriter->writeAttribute('dist', CommonDrawing::pixelsToEmu($effect->getDistance())); + $objWriter->writeAttribute('dir', CommonDrawing::degreesToAngle($effect->getDirection())); + $objWriter->writeAttribute('algn', $effect->getAlignment()); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:prstClr + $objWriter->startElement('a:'.$tagClr); + $objWriter->writeAttribute('val', $effect->getColor()->getRGB()); + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', $effect->getAlpha() * 1000); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } + + /** + * Write hyperlink * * @param XMLWriter $objWriter XML Writer * @param AbstractShape|TextElement $shape @@ -1440,7 +1488,7 @@ protected function writeShapePic(XMLWriter $objWriter, AbstractGraphic $shape, i $this->writeFill($objWriter, $shape->getFill()); $this->writeBorder($objWriter, $shape->getBorder(), ''); - $this->writeShadow($objWriter, $shape->getShadow()); + $this->writeEffect($objWriter, $shape->getEffectCollection()); $objWriter->endElement(); From 0be11d0545d6e49ccb118fd74492651db6aeb487 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Wed, 3 Feb 2021 15:33:07 +0100 Subject: [PATCH 18/23] BUGFIX for duplacting slide BUGFIX when duplicating slide an each composants, text into paragraph into richText where forget --- .../Shape/RichText/Paragraph.php | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/PhpPresentation/Shape/RichText/Paragraph.php b/src/PhpPresentation/Shape/RichText/Paragraph.php index 8f9e02652..95c9004ce 100644 --- a/src/PhpPresentation/Shape/RichText/Paragraph.php +++ b/src/PhpPresentation/Shape/RichText/Paragraph.php @@ -107,7 +107,26 @@ public function __construct() } /** - * Get alignment. + * Magic Method : clone + */ + public function __clone() + { + // Clone each text + if (isset($this->richTextElements)) { + foreach ($this->richTextElements as &$txtElt) { + $txtElt = clone $txtElt; + }} + // Clone each effect + if (isset($this->effectCollection)) { + foreach ($this->effectCollection as &$effect) { + $effect = clone $effect; + }} + } + + /** + * Get alignment + * + * @return \PhpOffice\PhpPresentation\Style\Alignment */ public function getAlignment(): Alignment { From a49854f4b86f5e220c757dd6af5d94b412a6a49f Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Wed, 3 Feb 2021 15:35:03 +0100 Subject: [PATCH 19/23] ADD vertical alos need horz sometimes ADD vertical alos need horz sometimes --- src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index bce5218a0..fc3853a12 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -258,6 +258,9 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh if ($shape->isVertical()) { $objWriter->writeAttribute('vert', 'vert'); } + else { + $objWriter->writeAttribute('vert', 'horz'); + } $objWriter->writeAttribute('bIns', CommonDrawing::pixelsToEmu($shape->getInsetBottom())); $objWriter->writeAttribute('lIns', CommonDrawing::pixelsToEmu($shape->getInsetLeft())); $objWriter->writeAttribute('rIns', CommonDrawing::pixelsToEmu($shape->getInsetRight())); From 7a31dbb87a4f0ce7a715e33a777a5ded47060543 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Wed, 3 Feb 2021 15:42:46 +0100 Subject: [PATCH 20/23] ADD Get more font attributs Need some mor informations to be same as original when reading, like charset, etc --- src/PhpPresentation/Reader/PowerPoint2007.php | 15 ++- src/PhpPresentation/Style/Font.php | 96 ++++++++++++++++++- .../Writer/PowerPoint2007/AbstractSlide.php | 9 ++ 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index 819fb5de4..e619a2607 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -1358,10 +1358,17 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh } // Font definition $oElementFont = $document->getElement('a:latin', $oElementrPr); - if (is_object($oElementFont)) { - if ($oElementFont->hasAttribute('typeface')) { - $oText->getFont()->setName($oElementFont->getAttribute('typeface')); - } + if (is_object($oElementFont) && $oElementFont->hasAttribute('typeface')) { + $oText->getFont()->setName($oElementFont->getAttribute('typeface')); + } + if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('panose')) { + $oText->getFont()->setPanose($oElementFont->getAttribute('panose')); + } + if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('pitchFamily')) { + $oText->getFont()->setPitchFamily($oElementFont->getAttribute('pitchFamily')); + } + if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('charset')) { + $oText->getFont()->setCharset($oElementFont->getAttribute('charset')); } // Load shape effects $oEffect = $document->getElement('a:effectLst', $oElementrPr); diff --git a/src/PhpPresentation/Style/Font.php b/src/PhpPresentation/Style/Font.php index 44f95548e..474d3e0e3 100644 --- a/src/PhpPresentation/Style/Font.php +++ b/src/PhpPresentation/Style/Font.php @@ -72,7 +72,26 @@ class Font implements ComparableInterface private $name = 'Calibri'; /** - * Font Size. + * panose + * + * @var string + */ + private $panose; + /** + * pitchFamily + * + * @var string + */ + private $pitchFamily; + /** + * charset + * + * @var string + */ + private $charset; + + /** + * Font Size * * @var int */ @@ -180,6 +199,81 @@ public function setName(string $pValue = 'Calibri'): self $pValue = 'Calibri'; } $this->name = $pValue; + return $this; + } + + /** + * Get panose + * + * @return string + */ + public function getPanose() + { + return $this->panose; + } + + /** + * Set panose + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setPanose($pValue) + { + if ($pValue == '') { + $pValue = ''; + } + $this->panose = $pValue; + + return $this; + } + /** + * Get pitchFamily + * + * @return string + */ + public function getPitchFamily() + { + return $this->pitchFamily; + } + + /** + * Set pitchFamily + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setPitchFamily($pValue) + { + if ($pValue == '') { + $pValue = ''; + } + $this->pitchFamily = $pValue; + + return $this; + } + /** + * Get charset + * + * @return string + */ + public function getCharset() + { + return $this->charset; + } + + /** + * Set charset + * + * @param string $pValue + * @return \PhpOffice\PhpPresentation\Style\Font + */ + public function setCharset($pValue) + { + if ($pValue == '') { + $pValue = ''; + } + $this->charset = $pValue; return $this; } diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index fc3853a12..79ea0c22a 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -678,12 +678,21 @@ protected function writeRunStyles(XMLWriter $objWriter, RichText\Run $element): $this->writeColor($objWriter, $element->getFont()->getColor()); $objWriter->endElement(); + // Write Effects + $this->writeEffect($objWriter, $element->getEffectCollection(), 'srgbClr'); + // Font // - a:latin // - a:ea // - a:cs $objWriter->startElement('a:' . $element->getFont()->getFormat()); $objWriter->writeAttribute('typeface', $element->getFont()->getName()); + if ($element->getFont()->getPanose()!="") + $objWriter->writeAttribute('panose', $element->getFont()->getPanose()); + if ($element->getFont()->getPitchFamily()!="") + $objWriter->writeAttribute('pitchFamily', $element->getFont()->getPitchFamily()); + if ($element->getFont()->getCharset()!="") + $objWriter->writeAttribute('charset', $element->getFont()->getCharset()); $objWriter->endElement(); // a:hlinkClick From 0e032326ef2d7a46761e0507ce5f521b00002120 Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Wed, 3 Feb 2021 17:04:50 +0100 Subject: [PATCH 21/23] BUGFIX Forgot clone for effect shape BUGFIX Forgot clone for effect shape --- src/PhpPresentation/AbstractShape.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index d93596156..176247149 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -158,6 +158,11 @@ public function __clone() if (isset($this->hyperlink)) { $this->hyperlink = clone $this->hyperlink; } + // Clone each effect + if (isset($this->effectCollection)) { + foreach ($this->effectCollection as &$effect) { + $effect = clone $effect; + }} } /** From 0e5dd8547dceab4a62a0e0d281dd5878acb1c83f Mon Sep 17 00:00:00 2001 From: devX2712 <69680982+devX2712@users.noreply.github.com> Date: Wed, 3 Feb 2021 17:06:59 +0100 Subject: [PATCH 22/23] ADD usefull function te search shape into a slide For modifing existing slide, usefull to search shape and doing action on it --- src/PhpPresentation/Slide/AbstractSlide.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/PhpPresentation/Slide/AbstractSlide.php b/src/PhpPresentation/Slide/AbstractSlide.php index b3d6fedfd..d67d51b16 100644 --- a/src/PhpPresentation/Slide/AbstractSlide.php +++ b/src/PhpPresentation/Slide/AbstractSlide.php @@ -118,9 +118,25 @@ public function getShapeCollection() } /** - * Get collection of shapes. + * Search into collection of shapes for a name (eventually filtered by type ex: RichText) * - * @param array|ArrayObject $shapeCollection + * @param string $name The name to find into the shape collection + * @param PhpOffice\PhpPresentation\Shape\RichText | PhpOffice\PhpPresentation\Shape\... $type Type of the class + * @return \ArrayObject|\PhpOffice\PhpPresentation\AbstractShape[] + */ + public function searchShapeByName(string $name, ?string $type=null) + { + if (isset($this->shapeCollection)) { + foreach ($this->shapeCollection as $shape) { + if ($shape->getName() == $name) { + if (!isset($type) || get_class($shape) == $type) { + return $shape; + }}}} + return null; + } + + /** + * Get collection of shapes * * @return AbstractSlide */ From ec4700e447b2c4f798f43f0bb6e71acfa3006874 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Wed, 13 Dec 2023 15:30:29 +0100 Subject: [PATCH 23/23] Feedbacks from @Progi1984 --- .gitignore | 1 + docs/changes/1.1.0.md | 15 + docs/usage/presentation.md | 32 +- docs/usage/styles.md | 35 +- samples/Sample_04_Table.php | 2 +- samples/Sample_05_Chart.php | 4 +- samples/Sample_17_Comment.php | 6 +- samples/Sample_22_ExternalSlide.php | 2 +- samples/Sample_Header.php | 13 +- src/PhpPresentation/AbstractShape.php | 104 ++---- src/PhpPresentation/DocumentProperties.php | 59 ++-- .../Exception/InvalidParameterException.php | 11 +- .../PresentationProperties.php | 69 ++-- src/PhpPresentation/Reader/ODPresentation.php | 5 +- src/PhpPresentation/Reader/PowerPoint2007.php | 238 ++++++-------- src/PhpPresentation/Reader/PowerPoint97.php | 2 +- src/PhpPresentation/Reader/Serialized.php | 13 +- src/PhpPresentation/Shape/AbstractGraphic.php | 31 -- src/PhpPresentation/Shape/Chart/Legend.php | 22 +- src/PhpPresentation/Shape/Chart/Title.php | 12 +- .../Shape/Chart/Type/AbstractTypeBar.php | 4 +- src/PhpPresentation/Shape/Chart/View3D.php | 8 +- src/PhpPresentation/Shape/Drawing/Gd.php | 4 +- src/PhpPresentation/Shape/Group.php | 32 +- src/PhpPresentation/Shape/RichText.php | 94 ++---- .../Shape/RichText/Paragraph.php | 71 +--- src/PhpPresentation/Shape/RichText/Run.php | 61 +--- .../Shape/RichText/TextElement.php | 4 +- .../Shape/RichText/TextElementInterface.php | 4 +- src/PhpPresentation/Shape/Table/Cell.php | 14 +- .../ShapeContainerInterface.php | 9 +- src/PhpPresentation/Slide.php | 34 +- src/PhpPresentation/Slide/AbstractSlide.php | 62 +--- src/PhpPresentation/Slide/Animation.php | 37 +-- src/PhpPresentation/Slide/Iterator.php | 11 +- src/PhpPresentation/Slide/Note.php | 35 +- src/PhpPresentation/Slide/SlideLayout.php | 5 +- src/PhpPresentation/Slide/SlideMaster.php | 3 - src/PhpPresentation/Style/Borders.php | 24 +- src/PhpPresentation/Style/Bullet.php | 10 +- src/PhpPresentation/Style/Color.php | 4 +- src/PhpPresentation/Style/Effect.php | 310 ------------------ src/PhpPresentation/Style/Font.php | 251 +++++++------- src/PhpPresentation/Style/Shadow.php | 37 ++- .../Traits/ShapeCollection.php | 96 ++++++ .../Writer/AbstractDecoratorWriter.php | 2 +- src/PhpPresentation/Writer/AbstractWriter.php | 16 +- src/PhpPresentation/Writer/ODPresentation.php | 2 +- .../Writer/ODPresentation/Content.php | 11 +- .../Writer/ODPresentation/ObjectsChart.php | 4 +- src/PhpPresentation/Writer/PowerPoint2007.php | 2 +- .../Writer/PowerPoint2007/AbstractSlide.php | 148 +++------ .../Writer/PowerPoint2007/ContentTypes.php | 2 +- .../Writer/PowerPoint2007/DocPropsCore.php | 11 +- .../PowerPoint2007/DocPropsThumbnail.php | 23 +- .../Writer/PowerPoint2007/PptCharts.php | 64 ++-- .../Writer/PowerPoint2007/PptSlides.php | 83 ++--- .../Writer/PowerPoint2007/Relationships.php | 23 +- src/PhpPresentation/Writer/Serialized.php | 22 +- .../Tests/DocumentPropertiesTest.php | 2 + .../Tests/PresentationPropertiesTest.php | 26 +- .../Tests/Reader/PowerPoint2007Test.php | 2 + .../PhpPresentation/Tests/Shape/GroupTest.php | 4 +- .../Tests/Shape/RichTextTest.php | 2 +- .../Tests/Slide/AbstractSlideTest.php | 34 ++ .../PhpPresentation/Tests/Slide/NoteTest.php | 8 +- .../Tests/Slide/SlideLayoutTest.php | 2 +- .../Tests/Slide/SlideMasterTest.php | 2 +- .../Tests/Style/BorderTest.php | 6 +- .../PhpPresentation/Tests/Style/ColorTest.php | 2 +- .../PhpPresentation/Tests/Style/FillTest.php | 8 +- .../PhpPresentation/Tests/Style/FontTest.php | 86 ++++- .../PowerPoint2007/DocPropsCoreTest.php | 18 +- .../PowerPoint2007/DocPropsThumbnailTest.php | 30 +- .../PowerPoint2007/PptSlideMastersTest.php | 2 +- .../Writer/PowerPoint2007/PptSlidesTest.php | 141 ++++++++ .../_includes/PhpPresentationTestCase.php | 12 + tests/bootstrap.php | 2 +- tests/resources/files/serialized.phppt | Bin 14433 -> 14495 bytes 79 files changed, 1193 insertions(+), 1509 deletions(-) delete mode 100644 src/PhpPresentation/Style/Effect.php create mode 100644 src/PhpPresentation/Traits/ShapeCollection.php diff --git a/.gitignore b/.gitignore index afe22ddd1..4cdc9c601 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ Desktop.ini ### Continuous Integration build/ phpunit.xml +php-cs-fixer.phar .php-cs-fixer.cache .phpunit.result.cache composer.phar diff --git a/docs/changes/1.1.0.md b/docs/changes/1.1.0.md index 81ba6ae1e..ebab02d39 100644 --- a/docs/changes/1.1.0.md +++ b/docs/changes/1.1.0.md @@ -17,9 +17,24 @@ - PowerPoint2007 Reader - PowerPoint2007 Writer - PowerPoint2007 Writer: Enable style and position of a Placeholder - [@qmachard](https://github.com/qmachard) in [#787](https://github.com/PHPOffice/PHPPresentation/pull/787) +- PowerPoint2007 Reader: Added support for thumbnail image - [@devX2712](https://github.com/devX2712) in [#788](https://github.com/PHPOffice/PHPPresentation/pull/787) ## Improvements - Slide : Raised max value for identifier rand call - [@Scheissy](https://github.com/Scheissy) in [#777](https://github.com/PHPOffice/PHPPresentation/pull/777) +- Document Properties : Support for Revision & Status - [@devX2712](https://github.com/devX2712) in [#788](https://github.com/PHPOffice/PHPPresentation/pull/787) + - PowerPoint2007 Reader + - PowerPoint2007 Writer +- Presentation Properties : Added support to define content of the thumbnail - [@devX2712](https://github.com/devX2712) in [#788](https://github.com/PHPOffice/PHPPresentation/pull/787) +- Font : Support for Capitalization, Strikethrough, Pitch Family, Charset & Panose - [@devX2712](https://github.com/devX2712) in [#788](https://github.com/PHPOffice/PHPPresentation/pull/787) + - PowerPoint2007 Reader + - PowerPoint2007 Writer +- Font : Replaced Superscript/Subscript by baseline in PowerPoint2007 Writer - [@devX2712](https://github.com/devX2712) in [#788](https://github.com/PHPOffice/PHPPresentation/pull/787) +- RichText : Support for Vertical Align - [@devX2712](https://github.com/devX2712) in [#788](https://github.com/PHPOffice/PHPPresentation/pull/787) + - PowerPoint2007 Reader + - PowerPoint2007 Writer +- Shadow : Support for Type Inner & Reflection - [@devX2712](https://github.com/devX2712) in [#788](https://github.com/PHPOffice/PHPPresentation/pull/787) + - PowerPoint2007 Reader + - PowerPoint2007 Writer ## Bugfixes diff --git a/docs/usage/presentation.md b/docs/usage/presentation.md index 03080aa1c..a06e0958b 100644 --- a/docs/usage/presentation.md +++ b/docs/usage/presentation.md @@ -62,6 +62,8 @@ $properties->setCreated(mktime(0, 0, 0, 3, 12, 2014)); $properties->setModified(mktime(0, 0, 0, 3, 14, 2014)); $properties->setSubject('My subject'); $properties->setKeywords('my, key, word'); +$properties->setStatus('Work in Progress'); +$properties->setRevision('Version 1.2.3'); ``` ### Custom Properties @@ -203,16 +205,44 @@ echo $properties->getSlideshowType(); You can define the thumbnail of the presentation with the method `setThumbnailPath`. + +#### From a file ``` php getPresentationProperties(); // Set path of the thumbnail -$properties->setThumbnailPath(__DIR__.'\resources\phppowerpoint_logo.gif'); +$properties->setThumbnailPath( + __DIR__.'\resources\phppowerpoint_logo.gif', + PresentationProperties::THUMBNAIL_FILE +); // Get path of the thumbnail echo $properties->getThumbnailPath(); +// Get content of the thumbnail +echo $properties->getThumbnail(); +``` + +#### From the content of the file +``` php +getPresentationProperties(); +// Set path of the thumbnail +$properties->setThumbnailPath( + '', + PresentationProperties::THUMBNAIL_DATA, + file_get_contents(__DIR__.'\resources\phppowerpoint_logo.gif') +); +// Get content of the thumbnail +echo $properties->getThumbnail(); ``` ### Zoom diff --git a/docs/usage/styles.md b/docs/usage/styles.md index e9ff72c60..a21efdc8e 100644 --- a/docs/usage/styles.md +++ b/docs/usage/styles.md @@ -97,12 +97,24 @@ echo $alignment->isRTL(); - `name` - `bold` - `italic` -- `superScript` -- `subScript` +- `superScript` (deprecated) +- `subScript` (deprecated) - `underline` - `strikethrough` - `color` -- `capitalization` +- `pitchFamily` +- `charset` + +### Baseline + +The baseline set the position relative to the line. +The value is a percentage. + +You can use some predefined values : + +* `Font::BASELINE_SUPERSCRIPT` (= 300000 = 300%) +* `Font::BASELINE_SUBSCRIPT` (= -250000 = -250%) + ### Capitalization @@ -145,6 +157,23 @@ $font->setFormat(Font::FORMAT_EAST_ASIAN); // Get format of font echo $font->getFormat(); ``` + +### Panose +The support of Panose 1.0 is only used. + +``` php +setPanose('4494D72242'); +// Get panose of font +echo $font->getPanose(); +``` + ## Bullet - `bulletType` diff --git a/samples/Sample_04_Table.php b/samples/Sample_04_Table.php index 0dce634c6..e6558d623 100644 --- a/samples/Sample_04_Table.php +++ b/samples/Sample_04_Table.php @@ -85,7 +85,7 @@ $oCell->createTextRun('R2C1'); $oCell->getActiveParagraph()->getAlignment() ->setMarginLeft(30) - ->setTextDirection(\PhpOffice\PhpPresentation\Style\Alignment::TEXT_DIRECTION_VERTICAL_270); + ->setTextDirection(PhpOffice\PhpPresentation\Style\Alignment::TEXT_DIRECTION_VERTICAL_270); $oCell = $row->nextCell(); $oCell->createTextRun('R2C2'); $oCell->getActiveParagraph()->getAlignment() diff --git a/samples/Sample_05_Chart.php b/samples/Sample_05_Chart.php index 201d9a46a..ad9c32f74 100644 --- a/samples/Sample_05_Chart.php +++ b/samples/Sample_05_Chart.php @@ -132,7 +132,7 @@ function fnSlide_BarHorizontal(PhpPresentation $objPHPPresentation): void // Create a bar chart (that should be inserted in a shape) echo date('H:i:s') . ' Create a horizontal bar chart (that should be inserted in a chart shape) ' . EOL; - $barChartHorz = clone $objPHPPresentation->getSlide(1)->getShapeCollection()->offsetGet(1)->getPlotArea()->getType(); + $barChartHorz = clone $objPHPPresentation->getSlide(1)->getShapeCollection()[1]->getPlotArea()->getType(); $barChartHorz->setBarDirection(Bar3D::DIRECTION_HORIZONTAL); // Create templated slide @@ -363,7 +363,7 @@ function fnSlide_Bar3DHorizontal(PhpPresentation $objPHPPresentation): void // Create a bar chart (that should be inserted in a shape) echo date('H:i:s') . ' Create a horizontal bar chart (that should be inserted in a chart shape) ' . EOL; - $bar3DChartHorz = clone $objPHPPresentation->getSlide(5)->getShapeCollection()->offsetGet(1)->getPlotArea()->getType(); + $bar3DChartHorz = clone $objPHPPresentation->getSlide(5)->getShapeCollection()[1]->getPlotArea()->getType(); $bar3DChartHorz->setBarDirection(Bar3D::DIRECTION_HORIZONTAL); // Create templated slide diff --git a/samples/Sample_17_Comment.php b/samples/Sample_17_Comment.php index c9fa84926..d417c4bfd 100644 --- a/samples/Sample_17_Comment.php +++ b/samples/Sample_17_Comment.php @@ -14,13 +14,13 @@ $oSlide1->addShape(clone $oShapeDrawing); $oSlide1->addShape(clone $oShapeRichText); -$oAuthor = new \PhpOffice\PhpPresentation\Shape\Comment\Author(); +$oAuthor = new PhpOffice\PhpPresentation\Shape\Comment\Author(); $oAuthor->setName('Progi1984'); $oAuthor->setInitials('P'); // Add Comment 1 echo date('H:i:s') . ' Add Comment 1' . EOL; -$oComment1 = new \PhpOffice\PhpPresentation\Shape\Comment(); +$oComment1 = new PhpOffice\PhpPresentation\Shape\Comment(); $oComment1->setText('Text A'); $oComment1->setOffsetX(10); $oComment1->setOffsetY(55); @@ -30,7 +30,7 @@ // Add Comment echo date('H:i:s') . ' Add Comment 2' . EOL; -$oComment2 = new \PhpOffice\PhpPresentation\Shape\Comment(); +$oComment2 = new PhpOffice\PhpPresentation\Shape\Comment(); $oComment2->setText('Text B'); $oComment2->setOffsetX(170); $oComment2->setOffsetY(180); diff --git a/samples/Sample_22_ExternalSlide.php b/samples/Sample_22_ExternalSlide.php index 3e89bf3d2..763234a6b 100644 --- a/samples/Sample_22_ExternalSlide.php +++ b/samples/Sample_22_ExternalSlide.php @@ -9,7 +9,7 @@ $objPHPPresentation = new PhpPresentation(); $objPHPPresentation->removeSlideByIndex(0); -$oReader = \PhpOffice\PhpPresentation\IOFactory::createReader('PowerPoint2007'); +$oReader = PhpOffice\PhpPresentation\IOFactory::createReader('PowerPoint2007'); $oPresentation04 = $oReader->load(__DIR__ . '/results/Sample_04_Table.pptx'); foreach ($oPresentation04->getAllSlides() as $oSlide) { diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 61796fe6f..803480e29 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -31,7 +31,7 @@ } else { if (is_file(__DIR__ . '/../../Common/src/Common/Autoloader.php')) { include_once __DIR__ . '/../../Common/src/Common/Autoloader.php'; - \PhpOffice\Common\Autoloader::register(); + PhpOffice\Common\Autoloader::register(); } else { throw new Exception('Can not find the vendor or the common folder!'); } @@ -109,7 +109,7 @@ /** * Write documents. * - * @param \PhpOffice\PhpPresentation\PhpPresentation $phpPresentation + * @param PhpPresentation $phpPresentation * @param string $filename * @param array $writers * @@ -180,7 +180,7 @@ function getEndingNotes($writers) /** * Creates a templated slide. */ -function createTemplatedSlide(PHPPresentation $objPHPPresentation): Slide +function createTemplatedSlide(PhpPresentation $objPHPPresentation): Slide { // Create slide $slide = $objPHPPresentation->createSlide(); @@ -326,7 +326,7 @@ protected function displayPhpPresentationInfo(PhpPresentation $oPHPPpt): void } } $oNote = $oSlide->getNote(); - if ($oNote->getShapeCollection()->count() > 0) { + if (count($oNote->getShapeCollection()) > 0) { $this->append('
Notes
'); foreach ($oNote->getShapeCollection() as $oShape) { if ($oShape instanceof RichText) { @@ -366,11 +366,11 @@ protected function displayShapeInfo(AbstractShape $oShape): void $this->append('
None
'); } else { switch ($oShape->getFill()->getFillType()) { - case \PhpOffice\PhpPresentation\Style\Fill::FILL_NONE: + case PhpOffice\PhpPresentation\Style\Fill::FILL_NONE: $this->append('
None
'); break; - case \PhpOffice\PhpPresentation\Style\Fill::FILL_SOLID: + case PhpOffice\PhpPresentation\Style\Fill::FILL_SOLID: $this->append('
Solid ('); $this->append('Color : #' . $oShape->getFill()->getStartColor()->getRGB()); $this->append(' - Alpha : ' . $oShape->getFill()->getStartColor()->getAlpha() . '%'); @@ -442,6 +442,7 @@ protected function displayShapeInfo(AbstractShape $oShape): void $this->append('Italic : ' . ($oRichText->getFont()->isItalic() ? 'Y' : 'N') . ' - '); $this->append('Underline : Underline::' . $this->getConstantName('\PhpOffice\PhpPresentation\Style\Font', $oRichText->getFont()->getUnderline()) . ' - '); $this->append('Strikethrough : ' . ($oRichText->getFont()->isStrikethrough() ? 'Y' : 'N') . ' - '); + $this->append('Baseline : ' . $oRichText->getFont()->getBaseline() . ' - '); $this->append('SubScript : ' . ($oRichText->getFont()->isSubScript() ? 'Y' : 'N') . ' - '); $this->append('SuperScript : ' . ($oRichText->getFont()->isSuperScript() ? 'Y' : 'N')); $this->append('
'); diff --git a/src/PhpPresentation/AbstractShape.php b/src/PhpPresentation/AbstractShape.php index 176247149..bbe9de54d 100644 --- a/src/PhpPresentation/AbstractShape.php +++ b/src/PhpPresentation/AbstractShape.php @@ -20,6 +20,7 @@ namespace PhpOffice\PhpPresentation; use PhpOffice\PhpPresentation\Exception\ShapeContainerAlreadyAssignedException; +use PhpOffice\PhpPresentation\Shape\Group; use PhpOffice\PhpPresentation\Shape\Hyperlink; use PhpOffice\PhpPresentation\Shape\Placeholder; use PhpOffice\PhpPresentation\Style\Border; @@ -103,27 +104,21 @@ abstract class AbstractShape implements ComparableInterface protected $placeholder; /** - * List of effect apply to shape - * @var array \PhpOffice\PhpPresentation\Style\Effect[] - */ - protected ?array $effectCollection = null; - - /** - * Hash index + * Hash index. * * @var int */ private $hashIndex; /** - * Name + * Name. * * @var string */ protected $name = ''; - + /** - * Create a new self + * Create a new self. */ public function __construct() { @@ -131,9 +126,8 @@ public function __construct() $this->fill = new Fill(); $this->shadow = new Shadow(); $this->border = new Border(); - $this->effectCollection = null; - $this->border->setLineStyle(Style\Border::LINE_NONE); + $this->border->setLineStyle(Border::LINE_NONE); } /** @@ -143,26 +137,19 @@ public function __clone() { $this->container = null; $this->name = $this->name; + $this->border = clone $this->border; if (isset($this->fill)) { - $this->fill = clone $this->fill; - } - if (isset($this->border)) { - $this->border = clone $this->border; + $this->fill = clone $this->fill; } if (isset($this->shadow)) { - $this->shadow = clone $this->shadow; + $this->shadow = clone $this->shadow; } if (isset($this->placeholder)) { - $this->placeholder = clone $this->placeholder; + $this->placeholder = clone $this->placeholder; } if (isset($this->hyperlink)) { - $this->hyperlink = clone $this->hyperlink; + $this->hyperlink = clone $this->hyperlink; } - // Clone each effect - if (isset($this->effectCollection)) { - foreach ($this->effectCollection as &$effect) { - $effect = clone $effect; - }} } /** @@ -186,21 +173,18 @@ public function setContainer(?ShapeContainerInterface $pValue = null, $pOverride // Add drawing to ShapeContainerInterface $this->container = $pValue; if (null !== $this->container) { - $this->container->getShapeCollection()->append($this); + $this->container->addShape($this); } } else { if ($pOverrideOld) { // Remove drawing from old ShapeContainerInterface - $iterator = $this->container->getShapeCollection()->getIterator(); - - while ($iterator->valid()) { - if ($iterator->current()->getHashCode() == $this->getHashCode()) { - $this->container->getShapeCollection()->offsetUnset($iterator->key()); + foreach ($this->container->getShapeCollection() as $key => $shape) { + if ($shape->getHashCode() == $this->getHashCode()) { + $this->container->unsetShape($key); $this->container = null; break; } - $iterator->next(); } // Set new \PhpOffice\PhpPresentation\Slide @@ -214,31 +198,27 @@ public function setContainer(?ShapeContainerInterface $pValue = null, $pOverride } /** - * Get Name - * - * @return string + * Get Name. */ - public function getName() + public function getName(): string { return $this->name; } /** - * Set Name + * Set Name. * - * @param string $pValue - * @return \PhpOffice\PhpPresentation\Shape\AbstractGraphic + * @return static */ - public function setName($pValue = '') + public function setName(string $pValue = ''): self { $this->name = $pValue; + return $this; } /** - * Get OffsetX - * - * @return int + * Get OffsetX. */ public function getOffsetX(): int { @@ -423,46 +403,6 @@ public function setHyperlink(?Hyperlink $pHyperlink = null): self return $this; } - - /** - * Add an effect to the shpae - * - * @param \PhpOffice\PhpPresentation\Style\Effect $effect - * @return $this - */ - public function addEffect(Shape\Effect $effect) - { - if (!isset($this->effectCollection)) { - $this->effectCollection = array(); - } - $this->effectCollection[] = $effect; - return $this; - } - - /** - * Get the effect collection - * - * @return array \PhpOffice\PhpPresentation\Style\Effect[] - */ - public function getEffectCollection():?array - { - return $this->effectCollection; - } - - /** - * Set the effect collection - * - * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection - * @return $this - */ - public function setEffectCollection(array $effectCollection) - { - if ( isset($effectCollection) - && is_array($effectCollection)) { - $this->effectCollection = $effectCollection; - } - return $this; - } /** * Get hash code. diff --git a/src/PhpPresentation/DocumentProperties.php b/src/PhpPresentation/DocumentProperties.php index c6a24e453..bd0b4a8b6 100644 --- a/src/PhpPresentation/DocumentProperties.php +++ b/src/PhpPresentation/DocumentProperties.php @@ -100,30 +100,30 @@ class DocumentProperties * @var string */ private $company; - + /** - * revision + * Revision. * * @var string */ private $revision; - + /** - * Custom Properties. + * Status. * - * @var array> + * @var string */ - private $customProperties = []; + private $status; /** - * status + * Custom Properties. * - * @var string + * @var array> */ - private $status; + private $customProperties = []; /** - * Create a new \PhpOffice\PhpPresentation\DocumentProperties + * Create a new \PhpOffice\PhpPresentation\DocumentProperties. */ public function __construct() { @@ -139,7 +139,7 @@ public function __construct() $this->category = ''; $this->company = 'Microsoft Corporation'; $this->revision = ''; - $this->status = ''; + $this->status = ''; } /** @@ -157,7 +157,7 @@ public function getCreator() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setCreator($pValue = '') { @@ -181,7 +181,7 @@ public function getLastModifiedBy() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setLastModifiedBy($pValue = '') { @@ -205,7 +205,7 @@ public function getCreated() * * @param int $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setCreated($pValue = null) { @@ -232,7 +232,7 @@ public function getModified() * * @param int $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setModified($pValue = null) { @@ -259,7 +259,7 @@ public function getTitle() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setTitle($pValue = '') { @@ -283,7 +283,7 @@ public function getDescription() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setDescription($pValue = '') { @@ -307,7 +307,7 @@ public function getSubject() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setSubject($pValue = '') { @@ -331,7 +331,7 @@ public function getKeywords() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setKeywords($pValue = '') { @@ -355,7 +355,7 @@ public function getCategory() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setCategory($pValue = '') { @@ -379,7 +379,7 @@ public function getCompany() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\DocumentProperties + * @return DocumentProperties */ public function setCompany($pValue = '') { @@ -470,7 +470,7 @@ public function setCustomProperty(string $propertyName, $propertyValue = '', ?st return $this; } - /* + /** * Get Revision. */ public function getRevision(): string @@ -479,7 +479,7 @@ public function getRevision(): string } /** - * Set Revision + * Set Revision. */ public function setRevision(string $pValue = ''): self { @@ -489,22 +489,17 @@ public function setRevision(string $pValue = ''): self } /** - * Get Status - * - * @return string + * Get Status. */ - public function getStatus() + public function getStatus(): string { return $this->status; } /** - * Set Status - * - * @param string $pValue - * @return \PhpOffice\PhpPresentation\DocumentProperties + * Set Status. */ - public function setStatus($pValue = '') + public function setStatus(string $pValue = ''): self { $this->status = $pValue; diff --git a/src/PhpPresentation/Exception/InvalidParameterException.php b/src/PhpPresentation/Exception/InvalidParameterException.php index 961809623..5a426ea61 100644 --- a/src/PhpPresentation/Exception/InvalidParameterException.php +++ b/src/PhpPresentation/Exception/InvalidParameterException.php @@ -21,12 +21,17 @@ class InvalidParameterException extends PhpPresentationException { - public function __construct(string $parameter, string $value) + public function __construct(string $parameter, string $value, ?string $error = null) { - parent::__construct(sprintf( + $message = sprintf( 'The parameter %s can\'t have the value "%s"', $parameter, $value - )); + ); + if ($error) { + $message = sprintf('%s (Validation: %s)', $message, $error); + } + + parent::__construct($message); } } diff --git a/src/PhpPresentation/PresentationProperties.php b/src/PhpPresentation/PresentationProperties.php index 63eca8fb5..dce8f439d 100644 --- a/src/PhpPresentation/PresentationProperties.php +++ b/src/PhpPresentation/PresentationProperties.php @@ -30,8 +30,8 @@ class PresentationProperties public const VIEW_SLIDE_SORTER = 'sldSorterView'; public const VIEW_SLIDE_THUMBNAIL = 'sldThumbnailView'; - public const THUMBNAIL_FILE = 'file'; // Thumbnail path is out of PPT - public const THUMBNAIL_ZIP = 'zip'; // Thumbnail path point to an image store into file loaded + public const THUMBNAIL_FILE = 'file'; + public const THUMBNAIL_DATA = 'data'; /** * @var array @@ -72,17 +72,17 @@ class PresentationProperties */ protected $markAsFinal = false; - /* - * @var string Define the thumbnail content (if content into zip file) + /** + * @var null|string Define the thumbnail content (if content into zip file) */ - protected $thumbnail = null; + protected $thumbnail; - /* - * @var string Define the thumbnail place + /** + * @var null|string Define the thumbnail place */ - protected $thumbnailPath = ''; + protected $thumbnailPath; - /* + /** * @var string Define if thumbnail is out of PPT or previouly store into PPT */ protected $thumbnailType = self::THUMBNAIL_FILE; @@ -128,38 +128,40 @@ public function getThumbnailPath(): ?string { return $this->thumbnailPath; } - + /** - * Return the content of thumbnail - * - * @return binary Content of image + * Return the content of thumbnail. */ - public function getThumbnail() + public function getThumbnail(): ?string { - // Return content of local file - if ($this->getThumbnailType() == self::THUMBNAIL_FILE) { - if (file_exists($this->getThumbnailPath())) - return file_get_contents($this->getThumbnailPath()); - } - // Return content of image stored into zip file - if ($this->getThumbnailType() == self::THUMBNAIL_ZIP) { - return $this->thumbnail; - } - // Return null if no thumbnail - return null; + // Return content of local file + if ($this->getThumbnailType() == self::THUMBNAIL_FILE) { + if ($this->getThumbnailPath()) { + return file_get_contents($this->getThumbnailPath()); + } + + return null; + } + + // Return content of image stored into zip file + if ($this->getThumbnailType() == self::THUMBNAIL_DATA) { + return $this->thumbnail; + } + + return null; } /** * Define the path for the thumbnail file / preview picture. */ - public function setThumbnailPath(string $path = '', $type = self::THUMBNAIL_FILE, $content = null) + public function setThumbnailPath(string $path = '', string $type = self::THUMBNAIL_FILE, ?string $content = null): self { - if (file_exists($path) && ($type == self::THUMBNAIL_FILE)) { + if (file_exists($path) && $type == self::THUMBNAIL_FILE) { $this->thumbnailPath = $path; $this->thumbnailType = $type; } - if (($path != '') && ($type == self::THUMBNAIL_ZIP)) { - $this->thumbnailPath = $path; + if ($content != '' && $type == self::THUMBNAIL_DATA) { + $this->thumbnailPath = ''; $this->thumbnailType = $type; $this->thumbnail = $content; } @@ -168,16 +170,15 @@ public function setThumbnailPath(string $path = '', $type = self::THUMBNAIL_FILE } /** - * Return the thumbnail type - * @return string + * Return the thumbnail type. */ - public function getThumbnailType() + public function getThumbnailType(): string { return $this->thumbnailType; } - + /** - * Mark a document as final + * Mark a document as final. */ public function markAsFinal(bool $state = true): self { diff --git a/src/PhpPresentation/Reader/ODPresentation.php b/src/PhpPresentation/Reader/ODPresentation.php index 0261b3689..579fab676 100644 --- a/src/PhpPresentation/Reader/ODPresentation.php +++ b/src/PhpPresentation/Reader/ODPresentation.php @@ -32,6 +32,7 @@ use PhpOffice\PhpPresentation\Shape\Drawing\Gd; use PhpOffice\PhpPresentation\Shape\RichText; use PhpOffice\PhpPresentation\Shape\RichText\Paragraph; +use PhpOffice\PhpPresentation\Slide\Background\Color as BackgroundColor; use PhpOffice\PhpPresentation\Slide\Background\Image; use PhpOffice\PhpPresentation\Style\Alignment; use PhpOffice\PhpPresentation\Style\Bullet; @@ -71,7 +72,7 @@ class ODPresentation implements ReaderInterface protected $arrayCommonStyles = []; /** - * @var \PhpOffice\Common\XMLReader + * @var XMLReader */ protected $oXMLReader; @@ -258,7 +259,7 @@ protected function loadStyle(DOMElement $nodeStyle): bool if ($nodeDrawingPageProps instanceof DOMElement) { // Read Background Color if ($nodeDrawingPageProps->hasAttribute('draw:fill-color') && 'solid' == $nodeDrawingPageProps->getAttribute('draw:fill')) { - $oBackground = new \PhpOffice\PhpPresentation\Slide\Background\Color(); + $oBackground = new BackgroundColor(); $oColor = new Color(); $oColor->setRGB(substr($nodeDrawingPageProps->getAttribute('draw:fill-color'), -6)); $oBackground->setColor($oColor); diff --git a/src/PhpPresentation/Reader/PowerPoint2007.php b/src/PhpPresentation/Reader/PowerPoint2007.php index e619a2607..140c2f4a5 100644 --- a/src/PhpPresentation/Reader/PowerPoint2007.php +++ b/src/PhpPresentation/Reader/PowerPoint2007.php @@ -51,6 +51,7 @@ use PhpOffice\PhpPresentation\Style\Fill; use PhpOffice\PhpPresentation\Style\Font; use PhpOffice\PhpPresentation\Style\SchemeColor; +use PhpOffice\PhpPresentation\Style\Shadow; use PhpOffice\PhpPresentation\Style\TextStyle; use ZipArchive; @@ -230,7 +231,7 @@ protected function loadDocumentProperties(string $sPart): void '/cp:coreProperties/dcterms:modified' => 'setModified', '/cp:coreProperties/cp:revision' => 'setRevision', '/cp:coreProperties/cp:contentStatus' => 'setStatus', - ); + ]; $oProperties = $this->oPhpPresentation->getDocumentProperties(); foreach ($arrayProperties as $path => $property) { $oElement = $xmlReader->getElement($path); @@ -247,28 +248,24 @@ protected function loadDocumentProperties(string $sPart): void } /** - * Read information of the document thumbnail - * @param string $sPart Content of XML file for retrieving data + * Read information of the document thumbnail. */ - protected function loadThumbnailProperties($sPart) + protected function loadThumbnailProperties(string $sPart): void { $xmlReader = new XMLReader(); - if ($xmlReader->getDomFromString($sPart)) { - $oElement = $xmlReader->getElement('*[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); - if ($oElement instanceof \DOMElement) { + $xmlReader->getDomFromString($sPart); + + $oElement = $xmlReader->getElement('*[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); + if ($oElement instanceof DOMElement) { $path = $oElement->getAttribute('Target'); $this->oPhpPresentation - ->getPresentationProperties() - ->setThumbnailPath($path - , \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP - , $this->oZip->getFromName($path)); - } + ->getPresentationProperties() + ->setThumbnailPath('', PresentationProperties::THUMBNAIL_DATA, $this->oZip->getFromName($path)); } } /** - * Read Custom Properties - * @param string $sPart + * Read Custom Properties. */ protected function loadCustomProperties(string $sPart): void { @@ -878,79 +875,62 @@ protected function loadShapeDrawing(XMLReader $document, DOMElement $node, Abstr } } // Load shape effects - $oEffect = $document->getElement('p:spPr/a:effectLst', $node); - if ($oEffect instanceof \DOMElement) { - $aEffect = $this->loadEffect($document, $oEffect); - if (isset($aEffect) && is_array($aEffect)) { - $oShape->setEffectCollection($aEffect); - } + $oElement = $document->getElement('p:spPr/a:effectLst', $node); + if ($oElement instanceof DOMElement) { + $oShape->setShadow( + $this->loadShadow($document, $oElement) + ); } $oSlide->addShape($oShape); } - + /** - * Load Effect for shape or paragraph - * - * @param XMLReader $document - * @param \DOMElement $node - * @return array \PhpOffice\PhpPresentation\Style\Effect[] + * Load Shadow for shape or paragraph. */ - protected function loadEffect(XMLReader $document, \DOMElement $nodeEffect) + protected function loadShadow(XMLReader $document, DOMElement $node): ?Shadow { - $aEffect = null; - if ($nodeEffect instanceof \DOMElement) { - - $aNodes = $document->getElements('*', $nodeEffect); - foreach ($aNodes as $node) { - - $type = explode(':', $node->tagName); - $type = array_pop($type); - if ( $type == 'outerShdw' - || $type == 'innerShdw') { -// @TODO || $type == 'reflection') { - - // Create a new effect - $effect = new \PhpOffice\PhpPresentation\Style\Effect($type); - // load blur radius - if ($node->hasAttribute('blurRad')) { - $effect->setBlurRadius(CommonDrawing::emuToPixels($node->getAttribute('blurRad'))); - } - // load distance - if ($node->hasAttribute('dist')) { - $effect->setDistance(CommonDrawing::emuToPixels($node->getAttribute('dist'))); - } - // load direction - if ($node->hasAttribute('dir')) { - $effect->setDirection(CommonDrawing::angleToDegrees($node->getAttribute('dir'))); - } - // load alignment - if ($node->hasAttribute('algn')) { - $effect->setAlignment($node->getAttribute('algn')); - } - - // Get color define by prstClr - $oSubElement = $document->getElement('a:prstClr', $node); - if ($oSubElement instanceof \DOMElement && $oSubElement->hasAttribute('val')) { - $oColor = new Color(); - $oColor->setRGB($oSubElement->getAttribute('val')); - $effect->setColor($oColor); - // Get Alpha - $oSubElt = $document->getElement('a:alpha', $oSubElement); - if ($oSubElt instanceof \DOMElement && $oSubElt->hasAttribute('val')) { - $effect->setAlpha((int)$oSubElt->getAttribute('val') / 1000); - } - } - // Load reflection atributs -// @TODO future implementation - if ($node->tagName == 'a:reflection') { - } - - if (!isset($aEffect)) $aEffect = array(); - $aEffect[] = $effect; - } - } - } - return $aEffect; + if ($node instanceof DOMElement) { + $aNodes = $document->getElements('*', $node); + foreach ($aNodes as $nodeShadow) { + $type = explode(':', $nodeShadow->tagName); + $type = array_pop($type); + if ($type == Shadow::TYPE_SHADOW_INNER || $type == Shadow::TYPE_SHADOW_OUTER || $type == Shadow::TYPE_REFLECTION) { + $oShadow = new Shadow(); + $oShadow->setVisible(true); + $oShadow->setType($type); + if ($nodeShadow->hasAttribute('blurRad')) { + $oShadow->setBlurRadius(CommonDrawing::emuToPixels((int) $nodeShadow->getAttribute('blurRad'))); + } + if ($nodeShadow->hasAttribute('dist')) { + $oShadow->setDistance(CommonDrawing::emuToPixels((int) $nodeShadow->getAttribute('dist'))); + } + if ($nodeShadow->hasAttribute('dir')) { + $oShadow->setDirection((int) CommonDrawing::angleToDegrees((int) $nodeShadow->getAttribute('dir'))); + } + if ($nodeShadow->hasAttribute('algn')) { + $oShadow->setAlignment($node->getAttribute('algn')); + } + + // Get color define by prstClr + $oSubElement = $document->getElement('a:prstClr', $nodeShadow); + if ($oSubElement instanceof DOMElement && $oSubElement->hasAttribute('val')) { + $oColor = new Color(); + $oColor->setRGB($oSubElement->getAttribute('val')); + + $oSubElt = $document->getElement('a:alpha', $oSubElement); + if ($oSubElt instanceof DOMElement && $oSubElt->hasAttribute('val')) { + $oColor->setAlpha((int) $oSubElt->getAttribute('val') / 1000); + } + + $oShadow->setColor($oColor); + } + + return $oShadow; + } + } + } + + return null; } /** @@ -967,8 +947,9 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl } $oElement = $document->getElement('p:nvSpPr/p:cNvPr', $node); - if ($oElement instanceof \DOMElement) + if ($oElement instanceof DOMElement) { $oShape->setName($oElement->hasAttribute('name') ? $oElement->getAttribute('name') : ''); + } $oElement = $document->getElement('p:spPr/a:xfrm', $node); if ($oElement instanceof DOMElement && $oElement->hasAttribute('rot')) { @@ -1004,33 +985,31 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl } // Load shape effects - $oEffect = $document->getElement('p:spPr/a:effectLst', $node); - if ($oEffect instanceof \DOMElement) { - $aEffect = $this->loadEffect($document, $oEffect); - if (isset($aEffect) && is_array($aEffect)) { - $oShape->setEffectCollection($aEffect); - } + $oElement = $document->getElement('p:spPr/a:effectLst', $node); + if ($oElement instanceof DOMElement) { + $oShape->setShadow( + $this->loadShadow($document, $oElement) + ); } -// FBU-20210202+ Read body definitions + // FBU-20210202+ Read body definitions $bodyPr = $document->getElement('p:txBody/a:bodyPr', $node); - if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('lIns')) { - $oShape->setInsetLeft((int)$bodyPr->getAttribute('lIns')); - } - if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('tIns')) { - $oShape->setInsetTop((int)$bodyPr->getAttribute('tIns')); - } - if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('rIns')) { - $oShape->setInsetRight((int)$bodyPr->getAttribute('rIns')); - } - if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('bIns')) { - $oShape->setInsetBottom((int)$bodyPr->getAttribute('bIns')); - } - if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('anchor')) { - $oShape->setVerticalAlignment($bodyPr->getAttribute('anchor')); - } - if (($bodyPr instanceof \DOMElement) && $bodyPr->hasAttribute('anchorCtr')) { - $oShape->setVerticalAlignCenter((int)$bodyPr->getAttribute('anchorCtr')); + if ($bodyPr instanceof DOMElement) { + if ($bodyPr->hasAttribute('lIns')) { + $oShape->setInsetLeft((int) $bodyPr->getAttribute('lIns')); + } + if ($bodyPr->hasAttribute('tIns')) { + $oShape->setInsetTop((int) $bodyPr->getAttribute('tIns')); + } + if ($bodyPr->hasAttribute('rIns')) { + $oShape->setInsetRight((int) $bodyPr->getAttribute('rIns')); + } + if ($bodyPr->hasAttribute('bIns')) { + $oShape->setInsetBottom((int) $bodyPr->getAttribute('bIns')); + } + if ($bodyPr->hasAttribute('anchorCtr')) { + $oShape->setVerticalAlignCenter((int) $bodyPr->getAttribute('anchorCtr')); + } } $arrayElements = $document->getElements('p:txBody/a:p', $node); @@ -1041,9 +1020,10 @@ protected function loadShapeRichText(XMLReader $document, DOMElement $node, $oSl } $oElement = $document->getElement('p:spPr', $node); - if ($oElement instanceof \DOMElement) { - $oFill = $this->loadStyleFill($document, $oElement); - $oShape->setFill($oFill); + if ($oElement instanceof DOMElement) { + $oShape->setFill( + $this->loadStyleFill($document, $oElement) + ); } if (count($oShape->getParagraphs()) > 0) { @@ -1316,11 +1296,7 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh $oText->setLanguage($oElementrPr->getAttribute('lang')); } if ($oElementrPr->hasAttribute('baseline')) { - if ((int)$oElementrPr->getAttribute('baseline')>0) { - $oText->getFont()->setSuperScript((int)$oElementrPr->getAttribute('baseline')); - } else if ((int)$oElementrPr->getAttribute('baseline')<0) { - $oText->getFont()->setSubScript((int)$oElementrPr->getAttribute('baseline')); - } + $oText->getFont()->setBaseline((int) $oElementrPr->getAttribute('baseline')); } // Color $oElementSrgbClr = $document->getElement('a:solidFill/a:srgbClr', $oElementrPr); @@ -1358,28 +1334,20 @@ protected function loadParagraph(XMLReader $document, DOMElement $oElement, $oSh } // Font definition $oElementFont = $document->getElement('a:latin', $oElementrPr); - if (is_object($oElementFont) && $oElementFont->hasAttribute('typeface')) { - $oText->getFont()->setName($oElementFont->getAttribute('typeface')); - } - if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('panose')) { - $oText->getFont()->setPanose($oElementFont->getAttribute('panose')); - } - if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('pitchFamily')) { - $oText->getFont()->setPitchFamily($oElementFont->getAttribute('pitchFamily')); - } - if (($oElementFont instanceof \DOMElement) && $oElementFont->hasAttribute('charset')) { - $oText->getFont()->setCharset($oElementFont->getAttribute('charset')); - } - // Load shape effects - $oEffect = $document->getElement('a:effectLst', $oElementrPr); - if ($oEffect instanceof \DOMElement) { - $aEffect = $this->loadEffect($document, $oEffect); - if (isset($aEffect) && is_array($aEffect)) { - $oText->setEffectCollection($aEffect); - } + if ($oElementFont instanceof DOMElement) { + if ($oElementFont->hasAttribute('typeface')) { + $oText->getFont()->setName($oElementFont->getAttribute('typeface')); + } + if ($oElementFont->hasAttribute('panose')) { + $oText->getFont()->setPanose($oElementFont->getAttribute('panose')); + } + if ($oElementFont->hasAttribute('pitchFamily')) { + $oText->getFont()->setPitchFamily((int) $oElementFont->getAttribute('pitchFamily')); + } + if ($oElementFont->hasAttribute('charset')) { + $oText->getFont()->setCharset((int) $oElementFont->getAttribute('charset')); + } } - //} else { - // $oText = $oParagraph->createText(); $oSubSubElement = $document->getElement('a:t', $oSubElement); $oText->setText($oSubSubElement->nodeValue); diff --git a/src/PhpPresentation/Reader/PowerPoint97.php b/src/PhpPresentation/Reader/PowerPoint97.php index 6189edb08..4ef8fc91c 100644 --- a/src/PhpPresentation/Reader/PowerPoint97.php +++ b/src/PhpPresentation/Reader/PowerPoint97.php @@ -1796,7 +1796,7 @@ private function readRecordOfficeArtSpgrContainer($stream, $pos, $bInGroup = fal $arrayIdxSlide = array_flip($this->arrayNotes); if ($this->currentNote > 0 && isset($arrayIdxSlide[$this->currentNote])) { $oSlide = $this->oPhpPresentation->getSlide($arrayIdxSlide[$this->currentNote]); - if (0 == $oSlide->getNote()->getShapeCollection()->count()) { + if (0 == count($oSlide->getNote()->getShapeCollection())) { $oSlide->getNote()->addShape($fileBlock['shape']); } } diff --git a/src/PhpPresentation/Reader/Serialized.php b/src/PhpPresentation/Reader/Serialized.php index 208c28325..df58d9551 100644 --- a/src/PhpPresentation/Reader/Serialized.php +++ b/src/PhpPresentation/Reader/Serialized.php @@ -92,14 +92,13 @@ private function loadSerialized(string $pFilename): PhpPresentation // Update media links for ($i = 0; $i < $file->getSlideCount(); ++$i) { - for ($j = 0; $j < $file->getSlide($i)->getShapeCollection()->count(); ++$j) { - if ($file->getSlide($i)->getShapeCollection()->offsetGet($j) instanceof AbstractDrawingAdapter) { - $imgTemp = $file->getSlide($i)->getShapeCollection()->offsetGet($j); - $imgPath = 'zip://' . $pFilename . '#media/' . $imgTemp->getImageIndex() . '/' . pathinfo($imgTemp->getPath(), PATHINFO_BASENAME); - if ($imgTemp instanceof DrawingFile) { - $imgTemp->setPath($imgPath, false); + foreach ($file->getSlide($i)->getShapeCollection() as $shape) { + if ($shape instanceof AbstractDrawingAdapter) { + $imgPath = 'zip://' . $pFilename . '#media/' . $shape->getImageIndex() . '/' . pathinfo($shape->getPath(), PATHINFO_BASENAME); + if ($shape instanceof DrawingFile) { + $shape->setPath($imgPath, false); } else { - $imgTemp->setPath($imgPath); + $shape->setPath($imgPath); } } } diff --git a/src/PhpPresentation/Shape/AbstractGraphic.php b/src/PhpPresentation/Shape/AbstractGraphic.php index f8b464f51..064e32a9e 100644 --- a/src/PhpPresentation/Shape/AbstractGraphic.php +++ b/src/PhpPresentation/Shape/AbstractGraphic.php @@ -41,13 +41,6 @@ abstract class AbstractGraphic extends AbstractShape implements ComparableInterf */ private $imageIndex = 0; - /** - * Name. - * - * @var string - */ - protected $name; - /** * Description. * @@ -105,30 +98,6 @@ public function getImageIndex() return $this->imageIndex; } - /** - * Get Name. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Set Name. - * - * @param string $pValue - * - * @return $this - */ - public function setName($pValue = '') - { - $this->name = $pValue; - - return $this; - } - /** * Get Description. * diff --git a/src/PhpPresentation/Shape/Chart/Legend.php b/src/PhpPresentation/Shape/Chart/Legend.php index 8798ea555..2d31708fc 100644 --- a/src/PhpPresentation/Shape/Chart/Legend.php +++ b/src/PhpPresentation/Shape/Chart/Legend.php @@ -89,21 +89,21 @@ class Legend implements ComparableInterface /** * Border. * - * @var \PhpOffice\PhpPresentation\Style\Border + * @var Border */ private $border; /** * Fill. * - * @var \PhpOffice\PhpPresentation\Style\Fill + * @var Fill */ private $fill; /** * Alignment. * - * @var \PhpOffice\PhpPresentation\Style\Alignment + * @var Alignment */ private $alignment; @@ -133,7 +133,7 @@ public function isVisible() * * @param bool $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Legend + * @return Legend */ public function setVisible($value = true) { @@ -157,7 +157,7 @@ public function getPosition() * * @param string $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Legend + * @return Legend */ public function setPosition($value = self::POSITION_RIGHT) { @@ -261,7 +261,7 @@ public function setFont(?Font $pFont = null): self /** * Get Border. * - * @return \PhpOffice\PhpPresentation\Style\Border + * @return Border */ public function getBorder() { @@ -271,7 +271,7 @@ public function getBorder() /** * Set Border. * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Legend + * @return Legend */ public function setBorder(Border $border) { @@ -283,7 +283,7 @@ public function setBorder(Border $border) /** * Get Fill. * - * @return \PhpOffice\PhpPresentation\Style\Fill + * @return Fill */ public function getFill() { @@ -293,7 +293,7 @@ public function getFill() /** * Set Fill. * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Legend + * @return Legend */ public function setFill(Fill $fill) { @@ -305,7 +305,7 @@ public function setFill(Fill $fill) /** * Get alignment. * - * @return \PhpOffice\PhpPresentation\Style\Alignment + * @return Alignment */ public function getAlignment() { @@ -315,7 +315,7 @@ public function getAlignment() /** * Set alignment. * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Legend + * @return Legend */ public function setAlignment(Alignment $alignment) { diff --git a/src/PhpPresentation/Shape/Chart/Title.php b/src/PhpPresentation/Shape/Chart/Title.php index 69494b785..a06c74468 100644 --- a/src/PhpPresentation/Shape/Chart/Title.php +++ b/src/PhpPresentation/Shape/Chart/Title.php @@ -73,14 +73,14 @@ class Title implements ComparableInterface /** * Alignment. * - * @var \PhpOffice\PhpPresentation\Style\Alignment + * @var Alignment */ private $alignment; /** * Font. * - * @var \PhpOffice\PhpPresentation\Style\Font + * @var Font */ private $font; @@ -117,7 +117,7 @@ public function isVisible() * * @param bool $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Title + * @return Title */ public function setVisible($value = true) { @@ -141,7 +141,7 @@ public function getText() * * @param string $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Title + * @return Title */ public function setText($value = null) { @@ -245,7 +245,7 @@ public function setFont(?Font $pFont = null): self /** * Get alignment. * - * @return \PhpOffice\PhpPresentation\Style\Alignment + * @return Alignment */ public function getAlignment() { @@ -255,7 +255,7 @@ public function getAlignment() /** * Set alignment. * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Title + * @return Title */ public function setAlignment(Alignment $alignment) { diff --git a/src/PhpPresentation/Shape/Chart/Type/AbstractTypeBar.php b/src/PhpPresentation/Shape/Chart/Type/AbstractTypeBar.php index 751b23371..8b671c74e 100644 --- a/src/PhpPresentation/Shape/Chart/Type/AbstractTypeBar.php +++ b/src/PhpPresentation/Shape/Chart/Type/AbstractTypeBar.php @@ -67,7 +67,7 @@ abstract class AbstractTypeBar extends AbstractType * * @param string $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Type\AbstractTypeBar + * @return AbstractTypeBar */ public function setBarDirection($value = self::DIRECTION_VERTICAL) { @@ -91,7 +91,7 @@ public function getBarDirection() * * @param string $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\Type\AbstractTypeBar + * @return AbstractTypeBar */ public function setBarGrouping($value = self::GROUPING_CLUSTERED) { diff --git a/src/PhpPresentation/Shape/Chart/View3D.php b/src/PhpPresentation/Shape/Chart/View3D.php index b6c0a4996..64111db63 100644 --- a/src/PhpPresentation/Shape/Chart/View3D.php +++ b/src/PhpPresentation/Shape/Chart/View3D.php @@ -97,7 +97,7 @@ public function getRotationX() * * @param int $pValue * - * @return \PhpOffice\PhpPresentation\Shape\Chart\View3D + * @return View3D */ public function setRotationX($pValue = 0) { @@ -121,7 +121,7 @@ public function getRotationY() * * @param int $pValue * - * @return \PhpOffice\PhpPresentation\Shape\Chart\View3D + * @return View3D */ public function setRotationY($pValue = 0) { @@ -145,7 +145,7 @@ public function hasRightAngleAxes() * * @param bool $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\View3D + * @return View3D */ public function setRightAngleAxes($value = true) { @@ -169,7 +169,7 @@ public function getPerspective() * * @param int $value * - * @return \PhpOffice\PhpPresentation\Shape\Chart\View3D + * @return View3D */ public function setPerspective($value = 30) { diff --git a/src/PhpPresentation/Shape/Drawing/Gd.php b/src/PhpPresentation/Shape/Drawing/Gd.php index 690966608..16fa6fe16 100644 --- a/src/PhpPresentation/Shape/Drawing/Gd.php +++ b/src/PhpPresentation/Shape/Drawing/Gd.php @@ -93,8 +93,8 @@ public function setImageResource($value = null) if (null !== $this->imageResource) { // Get width/height - $this->width = (int)@imagesx($this->imageResource); - $this->height = (int)@imagesy($this->imageResource); + $this->width = imagesx($this->imageResource); + $this->height = imagesy($this->imageResource); } return $this; diff --git a/src/PhpPresentation/Shape/Group.php b/src/PhpPresentation/Shape/Group.php index 4945f1561..1ceaf55e5 100644 --- a/src/PhpPresentation/Shape/Group.php +++ b/src/PhpPresentation/Shape/Group.php @@ -19,19 +19,14 @@ namespace PhpOffice\PhpPresentation\Shape; -use ArrayObject; use PhpOffice\PhpPresentation\AbstractShape; use PhpOffice\PhpPresentation\GeometryCalculator; use PhpOffice\PhpPresentation\ShapeContainerInterface; +use PhpOffice\PhpPresentation\Traits\ShapeCollection; class Group extends AbstractShape implements ShapeContainerInterface { - /** - * Collection of shapes. - * - * @var array|ArrayObject - */ - private $shapeCollection; + use ShapeCollection; /** * Extent X. @@ -50,29 +45,6 @@ class Group extends AbstractShape implements ShapeContainerInterface public function __construct() { parent::__construct(); - - // Shape collection - $this->shapeCollection = new ArrayObject(); - } - - /** - * Get collection of shapes. - * - * @return array|ArrayObject - */ - public function getShapeCollection() - { - return $this->shapeCollection; - } - - /** - * Add shape to slide. - */ - public function addShape(AbstractShape $shape): AbstractShape - { - $shape->setContainer($this); - - return $shape; } /** diff --git a/src/PhpPresentation/Shape/RichText.php b/src/PhpPresentation/Shape/RichText.php index 86f75c924..7aafe3c10 100644 --- a/src/PhpPresentation/Shape/RichText.php +++ b/src/PhpPresentation/Shape/RichText.php @@ -21,6 +21,7 @@ use PhpOffice\PhpPresentation\AbstractShape; use PhpOffice\PhpPresentation\ComparableInterface; +use PhpOffice\PhpPresentation\Exception\NotAllowedValueException; use PhpOffice\PhpPresentation\Exception\OutOfBoundsException; use PhpOffice\PhpPresentation\Shape\RichText\Paragraph; use PhpOffice\PhpPresentation\Shape\RichText\TextElementInterface; @@ -43,22 +44,17 @@ class RichText extends AbstractShape implements ComparableInterface /** Overflow */ public const OVERFLOW_CLIP = 'clip'; public const OVERFLOW_OVERFLOW = 'overflow'; - - /** Vertical alignment */ - const VALIGN_TOP = 't'; - const VALIGN_MIDDLE = 'ctr'; - const VALIGN_BOTTOM = 'b'; - + /** Vertical alignment center */ - const VALIGN_CENTER = 1; - const VALIGN_NOTCENTER = 0; + public const VALIGN_CENTER = 1; + public const VALIGN_NOTCENTER = 0; /** * Rich text paragraphs. * * @var array */ - private $richTextParagraphs; + private $richTextParagraphs = []; /** * Active paragraph. @@ -178,14 +174,10 @@ class RichText extends AbstractShape implements ComparableInterface * @var null|float */ private $lnSpcReduction; - - /** - * Define vertical text position into shape (top,center,bottom) - * @var string - */ - private $verticalAlign = self::VALIGN_TOP; + /** - * Define vertical text center position into shape (center,not center) + * Define vertical text center position into shape (center,not center). + * * @var int */ private $verticalAlignCenter = self::VALIGN_NOTCENTER; @@ -205,23 +197,20 @@ public function __construct() } /** - * Magic Method : clone + * Magic Method : clone. */ public function __clone() { // Call perent clonage for heritage parent::__clone(); // Clone each paragraph - if (isset($this->richTextParagraphs)) { - foreach ($this->richTextParagraphs as &$paragraph) { + foreach ($this->richTextParagraphs as &$paragraph) { $paragraph = clone $paragraph; - }} + } } /** - * Get active paragraph index - * - * @return int + * Get active paragraph index. */ public function getActiveParagraphIndex(): int { @@ -506,58 +495,34 @@ public function setVertical(bool $value = false): self return $this; } - - /** - * Define the vertical alignment - * - * @param string|null $value top,center,bottom - * @return $this - * @see self::VALIGN_TOP, self::VALIGN_MIDLE, self::VALIGN_BOTTOM - */ - public function setVerticalAlignment(?string $value) - { - if (isset($value)) { - $this->verticalAlign = $value; - } else { - $this->verticalAlign = self::VALIGN_TOP; - } - return $this; - } - - /** - * Get the vertical alignment - * - * @return string - * @see self::VALIGN_TOP, self::VALIGN_MIDLE, self::VALIGN_BOTTOM - */ - public function getVerticalAlignment():string - { - return $this->verticalAlign; - } /** - * Define the vertical alignment if centered or not - * @param int|null $value 1=center 0=not center - * @return $this + * Define the vertical alignment if centered or not. + * + * @param int $value 1=center 0=not + * * @see self::VALIGN_CENTER, self::VALIGN_NOTCENTER */ - public function setVerticalAlignCenter(?int $value) + public function setVerticalAlignCenter(int $value): self { - if (isset($value)) { + if (!in_array( + $value, + [self::VALIGN_CENTER, self::VALIGN_NOTCENTER] + )) { + throw new NotAllowedValueException((string) $value, [(string) self::VALIGN_CENTER, (string) self::VALIGN_NOTCENTER]); + } + $this->verticalAlignCenter = $value; - } else { - $this->verticalAlignCenter = self::VALIGN_NOTCENTER; - } - return $this; + + return $this; } /** - * Get the vertical alignment center - * @return int + * Get the vertical alignment center. */ - public function getVerticalAlignCenter():int + public function getVerticalAlignCenter(): int { - return $this->verticalAlignCenter; + return $this->verticalAlignCenter; } /** @@ -730,6 +695,7 @@ public function getHashCode(): string . $this->leftInset . $this->rightInset . $this->topInset + . $this->verticalAlignCenter . parent::getHashCode() . __CLASS__ ); diff --git a/src/PhpPresentation/Shape/RichText/Paragraph.php b/src/PhpPresentation/Shape/RichText/Paragraph.php index 95c9004ce..2eb173a62 100644 --- a/src/PhpPresentation/Shape/RichText/Paragraph.php +++ b/src/PhpPresentation/Shape/RichText/Paragraph.php @@ -66,14 +66,6 @@ class Paragraph implements ComparableInterface private $lineSpacing = 100; /** - * List of effect apply to paragraph - * @var array \PhpOffice\PhpPresentation\Style\Effect[] - */ - protected ?array $effectCollection = null; - - /** - * Hash index - * * @var string */ private $lineSpacingMode = self::LINE_SPACING_MODE_PERCENT; @@ -103,30 +95,21 @@ public function __construct() $this->alignment = new Alignment(); $this->font = new Font(); $this->bulletStyle = new Bullet(); - $this->effectCollection = null; } /** - * Magic Method : clone + * Magic Method : clone. */ public function __clone() { - // Clone each text - if (isset($this->richTextElements)) { - foreach ($this->richTextElements as &$txtElt) { - $txtElt = clone $txtElt; - }} - // Clone each effect - if (isset($this->effectCollection)) { - foreach ($this->effectCollection as &$effect) { - $effect = clone $effect; - }} + // Clone each text + foreach ($this->richTextElements as &$rtElement) { + $rtElement = clone $rtElement; + } } /** - * Get alignment - * - * @return \PhpOffice\PhpPresentation\Style\Alignment + * Get alignment. */ public function getAlignment(): Alignment { @@ -283,47 +266,7 @@ public function setRichTextElements(array $pElements = []): self } /** - * Add an effect to the shpae - * - * @param \PhpOffice\PhpPresentation\Style\Effect $effect - * @return $this - */ - public function addEffect(Shape\Effect $effect) - { - if (!isset($this->effectCollection)) { - $this->effectCollection = array(); - } - $this->effectCollection[] = $effect; - return $this; - } - - /** - * Get the effect collection - * - * @return array \PhpOffice\PhpPresentation\Style\Effect[] - */ - public function getEffectCollection():?array - { - return $this->effectCollection; - } - - /** - * Set the effect collection - * - * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection - * @return $this - */ - public function setEffectCollection(array $effectCollection) - { - if ( isset($effectCollection) - && is_array($effectCollection)) { - $this->effectCollection = $effectCollection; - } - return $this; - } - - /** - * Get hash code + * Get hash code. * * @return string Hash code */ diff --git a/src/PhpPresentation/Shape/RichText/Run.php b/src/PhpPresentation/Shape/RichText/Run.php index e4528acb6..a9f99fe3e 100644 --- a/src/PhpPresentation/Shape/RichText/Run.php +++ b/src/PhpPresentation/Shape/RichText/Run.php @@ -29,27 +29,18 @@ class Run extends TextElement implements TextElementInterface /** * Font. * - * @var \PhpOffice\PhpPresentation\Style\Font + * @var Font */ private $font; /** - * List of effect apply to paragraph - * @var array \PhpOffice\PhpPresentation\Style\Effect[] - */ - protected ?array $effectCollection = null; - - /** - * Create a new \PhpOffice\PhpPresentation\Shape\RichText\Run instance - * * @param string $pText Text */ public function __construct($pText = '') { - // Initialise variables + // Initialize variables $this->setText($pText); $this->font = new Font(); - $this->effectCollection = null; } /** @@ -63,9 +54,7 @@ public function getFont(): Font /** * Set font. * - * @param null|Font $pFont Font - * - * @return \PhpOffice\PhpPresentation\Shape\RichText\TextElementInterface + * @return self */ public function setFont(?Font $pFont = null) { @@ -75,49 +64,7 @@ public function setFont(?Font $pFont = null) } /** - * Add an effect to the shpae - * - * @param \PhpOffice\PhpPresentation\Style\Effect $effect - * @return $this - */ - public function addEffect(Shape\Effect $effect) - { - if (!isset($this->effectCollection)) { - $this->effectCollection = array(); - } - $this->effectCollection[] = $effect; - return $this; - } - - /** - * Get the effect collection - * - * @return array \PhpOffice\PhpPresentation\Style\Effect[] - */ - public function getEffectCollection():?array - { - return $this->effectCollection; - } - - /** - * Set the effect collection - * - * @param array \PhpOffice\PhpPresentation\Style\Effect $effectCollection - * @return $this - */ - public function setEffectCollection(array $effectCollection) - { - if ( isset($effectCollection) - && is_array($effectCollection)) { - $this->effectCollection = $effectCollection; - } - return $this; - } - - /** - * Get hash code - * - * @return string Hash code + * Get hash code. */ public function getHashCode(): string { diff --git a/src/PhpPresentation/Shape/RichText/TextElement.php b/src/PhpPresentation/Shape/RichText/TextElement.php index 709860ffb..e240a01e2 100644 --- a/src/PhpPresentation/Shape/RichText/TextElement.php +++ b/src/PhpPresentation/Shape/RichText/TextElement.php @@ -72,7 +72,7 @@ public function getText() * * @param string $pText Text value * - * @return \PhpOffice\PhpPresentation\Shape\RichText\TextElementInterface + * @return TextElementInterface */ public function setText($pText = '') { @@ -106,7 +106,7 @@ public function getHyperlink(): Hyperlink /** * Set Hyperlink. * - * @return \PhpOffice\PhpPresentation\Shape\RichText\TextElement + * @return TextElement */ public function setHyperlink(?Hyperlink $pHyperlink = null) { diff --git a/src/PhpPresentation/Shape/RichText/TextElementInterface.php b/src/PhpPresentation/Shape/RichText/TextElementInterface.php index af2485bb0..f0edad48c 100644 --- a/src/PhpPresentation/Shape/RichText/TextElementInterface.php +++ b/src/PhpPresentation/Shape/RichText/TextElementInterface.php @@ -36,7 +36,7 @@ public function getText(); * * @param string $pText Text value * - * @return \PhpOffice\PhpPresentation\Shape\RichText\TextElementInterface + * @return TextElementInterface */ public function setText($pText = ''); @@ -55,7 +55,7 @@ public function getLanguage(); /** * @param string $lang * - * @return \PhpOffice\PhpPresentation\Shape\RichText\TextElementInterface + * @return TextElementInterface */ public function setLanguage($lang); diff --git a/src/PhpPresentation/Shape/Table/Cell.php b/src/PhpPresentation/Shape/Table/Cell.php index 47bf1e6e6..d5e5251c8 100644 --- a/src/PhpPresentation/Shape/Table/Cell.php +++ b/src/PhpPresentation/Shape/Table/Cell.php @@ -48,14 +48,14 @@ class Cell implements ComparableInterface /** * Fill. * - * @var \PhpOffice\PhpPresentation\Style\Fill + * @var Fill */ private $fill; /** * Borders. * - * @var \PhpOffice\PhpPresentation\Style\Borders + * @var Borders */ private $borders; @@ -178,7 +178,7 @@ public function createParagraph(): Paragraph * * @param TextElementInterface $pText Rich text element * - * @return \PhpOffice\PhpPresentation\Shape\Table\Cell + * @return Cell */ public function addText(?TextElementInterface $pText = null) { @@ -276,7 +276,7 @@ public function setParagraphs(array $paragraphs = []): self /** * Get fill. * - * @return \PhpOffice\PhpPresentation\Style\Fill + * @return Fill */ public function getFill() { @@ -286,7 +286,7 @@ public function getFill() /** * Set fill. * - * @return \PhpOffice\PhpPresentation\Shape\Table\Cell + * @return Cell */ public function setFill(Fill $fill) { @@ -298,7 +298,7 @@ public function setFill(Fill $fill) /** * Get borders. * - * @return \PhpOffice\PhpPresentation\Style\Borders + * @return Borders */ public function getBorders() { @@ -308,7 +308,7 @@ public function getBorders() /** * Set borders. * - * @return \PhpOffice\PhpPresentation\Shape\Table\Cell + * @return Cell */ public function setBorders(Borders $borders) { diff --git a/src/PhpPresentation/ShapeContainerInterface.php b/src/PhpPresentation/ShapeContainerInterface.php index a347c358e..5fde0573d 100644 --- a/src/PhpPresentation/ShapeContainerInterface.php +++ b/src/PhpPresentation/ShapeContainerInterface.php @@ -36,10 +36,17 @@ public function getShapeCollection(); /** * Add shape to slide. * - * @return AbstractShape + * @return static */ public function addShape(AbstractShape $shape); + /** + * Unset shape from the collection. + * + * @return static + */ + public function unsetShape(int $key); + /** * Get X Offset. */ diff --git a/src/PhpPresentation/Slide.php b/src/PhpPresentation/Slide.php index 150e14426..3b0a9218f 100644 --- a/src/PhpPresentation/Slide.php +++ b/src/PhpPresentation/Slide.php @@ -19,7 +19,6 @@ namespace PhpOffice\PhpPresentation; -use ArrayObject; use PhpOffice\PhpPresentation\Slide\AbstractSlide; use PhpOffice\PhpPresentation\Slide\Note; use PhpOffice\PhpPresentation\Slide\SlideLayout; @@ -74,8 +73,6 @@ public function __construct(?PhpPresentation $pParent = null) { // Set parent $this->parent = $pParent; - // Shape collection - $this->shapeCollection = new ArrayObject(); // Set identifier $this->identifier = md5(mt_rand(0, mt_getrandmax()) . time()); // Set Slide Layout @@ -123,7 +120,7 @@ public function getSlideMasterId() * * @param int $masterId * - * @return \PhpOffice\PhpPresentation\Slide + * @return Slide */ public function setSlideMasterId($masterId = 1) { @@ -132,33 +129,26 @@ public function setSlideMasterId($masterId = 1) return $this; } - public function __clone() { - // Set parent - $this->parent = clone $this->parent; - // Shape collection - if (isset($this->shapeCollection)) { - $this->shapeCollection = clone $this->shapeCollection; + // Set parent + $this->parent = clone $this->parent; + // Shape collection foreach ($this->shapeCollection as &$shape) { - $shape = clone $shape; + $shape = clone $shape; + } + // Transition + if (isset($this->slideTransition)) { + $this->slideTransition = clone $this->slideTransition; } - } - // Transition object - if (isset($this->slideTransition)) { - $this->slideTransition = clone $this->slideTransition; - } - // Note object - if (isset($this->slideNote)) { + // Note $this->slideNote = clone $this->slideNote; - } - } /** * Copy slide (!= clone!). * - * @return \PhpOffice\PhpPresentation\Slide + * @return Slide */ public function copy() { @@ -221,7 +211,7 @@ public function setIsVisible($value = true) /** * Add an animation to the slide. * - * @param \PhpOffice\PhpPresentation\Slide\Animation $animation + * @param Slide\Animation $animation * * @return Slide */ diff --git a/src/PhpPresentation/Slide/AbstractSlide.php b/src/PhpPresentation/Slide/AbstractSlide.php index d67d51b16..9c93c3283 100644 --- a/src/PhpPresentation/Slide/AbstractSlide.php +++ b/src/PhpPresentation/Slide/AbstractSlide.php @@ -19,8 +19,6 @@ namespace PhpOffice\PhpPresentation\Slide; -use ArrayObject; -use PhpOffice\PhpPresentation\AbstractShape; use PhpOffice\PhpPresentation\ComparableInterface; use PhpOffice\PhpPresentation\GeometryCalculator; use PhpOffice\PhpPresentation\PhpPresentation; @@ -31,9 +29,12 @@ use PhpOffice\PhpPresentation\Shape\RichText; use PhpOffice\PhpPresentation\Shape\Table; use PhpOffice\PhpPresentation\ShapeContainerInterface; +use PhpOffice\PhpPresentation\Traits\ShapeCollection; abstract class AbstractSlide implements ComparableInterface, ShapeContainerInterface { + use ShapeCollection; + /** * @var string */ @@ -44,13 +45,6 @@ abstract class AbstractSlide implements ComparableInterface, ShapeContainerInter */ protected $slideTransition; - /** - * Collection of shapes. - * - * @var array|ArrayObject - */ - protected $shapeCollection = []; - /** * Extent Y. * @@ -107,56 +101,6 @@ abstract class AbstractSlide implements ComparableInterface, ShapeContainerInter */ protected $background; - /** - * Get collection of shapes. - * - * @return array|ArrayObject - */ - public function getShapeCollection() - { - return $this->shapeCollection; - } - - /** - * Search into collection of shapes for a name (eventually filtered by type ex: RichText) - * - * @param string $name The name to find into the shape collection - * @param PhpOffice\PhpPresentation\Shape\RichText | PhpOffice\PhpPresentation\Shape\... $type Type of the class - * @return \ArrayObject|\PhpOffice\PhpPresentation\AbstractShape[] - */ - public function searchShapeByName(string $name, ?string $type=null) - { - if (isset($this->shapeCollection)) { - foreach ($this->shapeCollection as $shape) { - if ($shape->getName() == $name) { - if (!isset($type) || get_class($shape) == $type) { - return $shape; - }}}} - return null; - } - - /** - * Get collection of shapes - * - * @return AbstractSlide - */ - public function setShapeCollection($shapeCollection = []) - { - $this->shapeCollection = $shapeCollection; - - return $this; - } - - /** - * Add shape to slide. - */ - public function addShape(AbstractShape $shape): AbstractShape - { - $shape->setContainer($this); - - return $shape; - } - /** * Get X Offset. */ diff --git a/src/PhpPresentation/Slide/Animation.php b/src/PhpPresentation/Slide/Animation.php index f5215ac2a..e32a4c71b 100644 --- a/src/PhpPresentation/Slide/Animation.php +++ b/src/PhpPresentation/Slide/Animation.php @@ -19,42 +19,9 @@ namespace PhpOffice\PhpPresentation\Slide; -use PhpOffice\PhpPresentation\AbstractShape; +use PhpOffice\PhpPresentation\Traits\ShapeCollection; class Animation { - /** - * @var array - */ - protected $shapeCollection = []; - - /** - * @return Animation - */ - public function addShape(AbstractShape $shape) - { - $this->shapeCollection[] = $shape; - - return $this; - } - - /** - * @return array - */ - public function getShapeCollection(): array - { - return $this->shapeCollection; - } - - /** - * @param array $array - * - * @return Animation - */ - public function setShapeCollection(array $array = []) - { - $this->shapeCollection = $array; - - return $this; - } + use ShapeCollection; } diff --git a/src/PhpPresentation/Slide/Iterator.php b/src/PhpPresentation/Slide/Iterator.php index 2b621b7ff..f718728ec 100644 --- a/src/PhpPresentation/Slide/Iterator.php +++ b/src/PhpPresentation/Slide/Iterator.php @@ -21,6 +21,7 @@ use IteratorIterator; use PhpOffice\PhpPresentation\PhpPresentation; +use ReturnTypeWillChange; // @phpstan-ignore-next-line class Iterator extends IteratorIterator @@ -50,7 +51,7 @@ public function __construct(PhpPresentation $subject) /** * Rewind iterator. */ - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function rewind(): void { $this->position = 0; @@ -61,7 +62,7 @@ public function rewind(): void * * @return \PhpOffice\PhpPresentation\Slide */ - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function current() { return $this->subject->getSlide($this->position); @@ -72,7 +73,7 @@ public function current() * * @return int */ - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function key() { return $this->position; @@ -81,7 +82,7 @@ public function key() /** * Next value. */ - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function next(): void { ++$this->position; @@ -92,7 +93,7 @@ public function next(): void * * @return bool */ - #[\ReturnTypeWillChange] + #[ReturnTypeWillChange] public function valid() { return $this->position < $this->subject->getSlideCount(); diff --git a/src/PhpPresentation/Slide/Note.php b/src/PhpPresentation/Slide/Note.php index d60542813..b7a323c67 100644 --- a/src/PhpPresentation/Slide/Note.php +++ b/src/PhpPresentation/Slide/Note.php @@ -19,16 +19,17 @@ namespace PhpOffice\PhpPresentation\Slide; -use ArrayObject; -use PhpOffice\PhpPresentation\AbstractShape; use PhpOffice\PhpPresentation\ComparableInterface; use PhpOffice\PhpPresentation\GeometryCalculator; use PhpOffice\PhpPresentation\Shape\RichText; use PhpOffice\PhpPresentation\ShapeContainerInterface; use PhpOffice\PhpPresentation\Slide; +use PhpOffice\PhpPresentation\Traits\ShapeCollection; class Note implements ComparableInterface, ShapeContainerInterface { + use ShapeCollection; + /** * Parent slide. * @@ -36,13 +37,6 @@ class Note implements ComparableInterface, ShapeContainerInterface */ private $parent; - /** - * Collection of shapes. - * - * @var array|ArrayObject - */ - private $shapeCollection; - /** * Note identifier. * @@ -93,33 +87,10 @@ public function __construct(?Slide $pParent = null) // Set parent $this->parent = $pParent; - // Shape collection - $this->shapeCollection = new ArrayObject(); - // Set identifier $this->identifier = md5(mt_rand(0, 9999) . time()); } - /** - * Get collection of shapes. - * - * @return array|ArrayObject - */ - public function getShapeCollection() - { - return $this->shapeCollection; - } - - /** - * Add shape to slide. - */ - public function addShape(AbstractShape $shape): AbstractShape - { - $shape->setContainer($this); - - return $shape; - } - /** * Create rich text shape. */ diff --git a/src/PhpPresentation/Slide/SlideLayout.php b/src/PhpPresentation/Slide/SlideLayout.php index 6393ca7e2..24c34544b 100644 --- a/src/PhpPresentation/Slide/SlideLayout.php +++ b/src/PhpPresentation/Slide/SlideLayout.php @@ -19,7 +19,6 @@ namespace PhpOffice\PhpPresentation\Slide; -use ArrayObject; use PhpOffice\PhpPresentation\ComparableInterface; use PhpOffice\PhpPresentation\ShapeContainerInterface; use PhpOffice\PhpPresentation\Style\ColorMap; @@ -62,7 +61,7 @@ class SlideLayout extends AbstractSlide implements ComparableInterface, ShapeCon /** * Mapping of colors to the theme. * - * @var \PhpOffice\PhpPresentation\Style\ColorMap + * @var ColorMap */ public $colorMap; @@ -73,8 +72,6 @@ public function __construct(SlideMaster $pSlideMaster) { // Set parent $this->slideMaster = $pSlideMaster; - // Shape collection - $this->shapeCollection = new ArrayObject(); // Set identifier $this->identifier = md5(mt_rand(0, 9999) . time()); // Set a basic colorMap diff --git a/src/PhpPresentation/Slide/SlideMaster.php b/src/PhpPresentation/Slide/SlideMaster.php index 9d877d3f2..1d30e539a 100644 --- a/src/PhpPresentation/Slide/SlideMaster.php +++ b/src/PhpPresentation/Slide/SlideMaster.php @@ -19,7 +19,6 @@ namespace PhpOffice\PhpPresentation\Slide; -use ArrayObject; use PhpOffice\PhpPresentation\ComparableInterface; use PhpOffice\PhpPresentation\PhpPresentation; use PhpOffice\PhpPresentation\ShapeContainerInterface; @@ -80,8 +79,6 @@ public function __construct(?PhpPresentation $pParent = null) { // Set parent $this->parent = $pParent; - // Shape collection - $this->shapeCollection = new ArrayObject(); // Set identifier $this->identifier = md5(mt_rand(0, 9999) . time()); // Set a basic colorMap diff --git a/src/PhpPresentation/Style/Borders.php b/src/PhpPresentation/Style/Borders.php index efdc2867b..f2aefa5b8 100644 --- a/src/PhpPresentation/Style/Borders.php +++ b/src/PhpPresentation/Style/Borders.php @@ -29,42 +29,42 @@ class Borders implements ComparableInterface /** * Left. * - * @var \PhpOffice\PhpPresentation\Style\Border + * @var Border */ private $left; /** * Right. * - * @var \PhpOffice\PhpPresentation\Style\Border + * @var Border */ private $right; /** * Top. * - * @var \PhpOffice\PhpPresentation\Style\Border + * @var Border */ private $top; /** * Bottom. * - * @var \PhpOffice\PhpPresentation\Style\Border + * @var Border */ private $bottom; /** * Diagonal up. * - * @var \PhpOffice\PhpPresentation\Style\Border + * @var Border */ private $diagonalUp; /** * Diagonal down. * - * @var \PhpOffice\PhpPresentation\Style\Border + * @var Border */ private $diagonalDown; @@ -94,7 +94,7 @@ public function __construct() /** * Get Left. * - * @return \PhpOffice\PhpPresentation\Style\Border + * @return Border */ public function getLeft() { @@ -104,7 +104,7 @@ public function getLeft() /** * Get Right. * - * @return \PhpOffice\PhpPresentation\Style\Border + * @return Border */ public function getRight() { @@ -114,7 +114,7 @@ public function getRight() /** * Get Top. * - * @return \PhpOffice\PhpPresentation\Style\Border + * @return Border */ public function getTop() { @@ -124,7 +124,7 @@ public function getTop() /** * Get Bottom. * - * @return \PhpOffice\PhpPresentation\Style\Border + * @return Border */ public function getBottom() { @@ -134,7 +134,7 @@ public function getBottom() /** * Get Diagonal Up. * - * @return \PhpOffice\PhpPresentation\Style\Border + * @return Border */ public function getDiagonalUp() { @@ -144,7 +144,7 @@ public function getDiagonalUp() /** * Get Diagonal Down. * - * @return \PhpOffice\PhpPresentation\Style\Border + * @return Border */ public function getDiagonalDown() { diff --git a/src/PhpPresentation/Style/Bullet.php b/src/PhpPresentation/Style/Bullet.php index e31a06c55..1222cc1f4 100644 --- a/src/PhpPresentation/Style/Bullet.php +++ b/src/PhpPresentation/Style/Bullet.php @@ -149,7 +149,7 @@ public function getBulletType() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\Style\Bullet + * @return Bullet */ public function setBulletType($pValue = self::TYPE_NONE) { @@ -173,7 +173,7 @@ public function getBulletFont() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\Style\Bullet + * @return Bullet */ public function setBulletFont($pValue = 'Calibri') { @@ -200,7 +200,7 @@ public function getBulletChar() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\Style\Bullet + * @return Bullet */ public function setBulletChar($pValue = '-') { @@ -224,7 +224,7 @@ public function getBulletNumericStyle() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\Style\Bullet + * @return Bullet */ public function setBulletNumericStyle($pValue = self::NUMERIC_DEFAULT) { @@ -248,7 +248,7 @@ public function getBulletNumericStartAt() * * @param int|string $pValue * - * @return \PhpOffice\PhpPresentation\Style\Bullet + * @return Bullet */ public function setBulletNumericStartAt($pValue = 1) { diff --git a/src/PhpPresentation/Style/Color.php b/src/PhpPresentation/Style/Color.php index a10ffdc73..6e1f54da6 100644 --- a/src/PhpPresentation/Style/Color.php +++ b/src/PhpPresentation/Style/Color.php @@ -78,7 +78,7 @@ public function getARGB() * * @param string $pValue * - * @return \PhpOffice\PhpPresentation\Style\Color + * @return Color */ public function setARGB($pValue = self::COLOR_BLACK) { @@ -146,7 +146,7 @@ public function getRGB() * @param string $pValue * @param string $pAlpha * - * @return \PhpOffice\PhpPresentation\Style\Color + * @return Color */ public function setRGB($pValue = '000000', $pAlpha = 'FF') { diff --git a/src/PhpPresentation/Style/Effect.php b/src/PhpPresentation/Style/Effect.php deleted file mode 100644 index 5c25ca4f4..000000000 --- a/src/PhpPresentation/Style/Effect.php +++ /dev/null @@ -1,310 +0,0 @@ -effectType = $type; - $this->blurRadius = 6; - $this->distance = 2; - $this->direction = 0; - $this->alignment = self::SHADOW_BOTTOM_RIGHT; - $this->color = new Color(Color::COLOR_BLACK); - $this->alpha = 50; - } - - /** - * Define the type effect - * - * @param string $type - * @return $this - * @see self::EFFECT_SHADOW_INNER, self::EFFECT_SHADOW_OUTER, self::EFFECT_REFLECTION - */ - public function setEffectType(string $type) - { - $this->effectType = $type; - return $this; - } - - /** - * Get the effect type - * - * @return string - */ - public function getEffectType():string - { - return $this->effectType; - } - - /** - * Set the direction - * - * @param int $dir - * @return $this - */ - public function setDirection(?int $dir) - { - if (!isset($dir)) $dir = 0; - $this->direction = (int)$dir; - return $this; - } - - /** - * Get the direction - * - * @return int - */ - public function getDirection():int - { - return $this->direction; - } - - /** - * Set the blur radius - * - * @param int $radius - * @return $this - */ - public function setBlurRadius(?int $radius) - { - if (!isset($radius)) $radius = 6; - $this->blurRadius = $radius; - return $this; - } - - /** - * Get the blur radius - * - * @return int - */ - public function getBlurRadius():int - { - return $this->blurRadius; - } - - /** - * Get Shadow distance - * - * @return int - */ - public function getDistance():int - { - return $this->distance; - } - - /** - * Set Shadow distance - * - * @param int $distance - * @return $this - */ - public function setDistance(int $distance = 2) - { - $this->distance = $distance; - - return $this; - } - - /** - * Set the effect alignment - * - * @param string $align - * @return $this - */ - public function setAlignment(?string $align) - { - if (!isset($align)) $align = self::SHADOW_BOTTOM_RIGHT; - $this->align = $align; - return $this; - } - - /** - * Get the effect alignment - * - * @return string - */ - public function getAlignment():string - { - return $this->align; - } - - /** - * Set Color - * - * @param \PhpOffice\PhpPresentation\Style\Color $color - * @return $this - */ - public function setColor(Color $color = null) - { - $this->color = $color; - - return $this; - } - - /** - * Get Color - * - * @return \PhpOffice\PhpPresentation\Style\Color - */ - public function getColor() - { - return $this->color; - } - - /** - * Set Alpha - * - * @param int $alpha - * @return $this - */ - public function setAlpha(?int $alpha) - { - if (!isset($alpha)) $alpha = 0; - $this->alpha = $alpha; - - return $this; - } - - /** - * Get Alpha - * - * @return int - */ - public function getAlpha():int - { - return $this->alpha; - } - - /** - * Get hash code - * - * @return string Hash code - */ - public function getHashCode() - { - return md5($this->effectType . $this->blurRadius . $this->distance . $this->direction . $this->alignment . $this->color->getHashCode() . $this->alpha . __CLASS__); - } - - /** - * Get hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @return string Hash index - */ - public function getHashIndex() - { - return $this->hashIndex; - } - - /** - * Set hash index - * - * Note that this index may vary during script execution! Only reliable moment is - * while doing a write of a workbook and when changes are not allowed. - * - * @param string $value Hash index - */ - public function setHashIndex($value) - { - $this->hashIndex = $value; - } - -} diff --git a/src/PhpPresentation/Style/Font.php b/src/PhpPresentation/Style/Font.php index 474d3e0e3..2975df4ef 100644 --- a/src/PhpPresentation/Style/Font.php +++ b/src/PhpPresentation/Style/Font.php @@ -20,6 +20,7 @@ namespace PhpOffice\PhpPresentation\Style; use PhpOffice\PhpPresentation\ComparableInterface; +use PhpOffice\PhpPresentation\Exception\InvalidParameterException; use PhpOffice\PhpPresentation\Exception\NotAllowedValueException; /** @@ -27,6 +28,24 @@ */ class Font implements ComparableInterface { + // Capitalization type + public const CAPITALIZATION_NONE = 'none'; + public const CAPITALIZATION_SMALL = 'small'; + public const CAPITALIZATION_ALL = 'all'; + + // Charset type + public const CHARSET_DEFAULT = 0x01; + + // Format type + public const FORMAT_LATIN = 'latin'; + public const FORMAT_EAST_ASIAN = 'ea'; + public const FORMAT_COMPLEX_SCRIPT = 'cs'; + + // Strike type + public const STRIKE_NONE = 'noStrike'; + public const STRIKE_SINGLE = 'sngStrike'; + public const STRIKE_DOUBLE = 'dblStrike'; + // Underline types public const UNDERLINE_NONE = 'none'; public const UNDERLINE_DASH = 'dash'; @@ -46,23 +65,10 @@ class Font implements ComparableInterface public const UNDERLINE_WAVYDOUBLE = 'wavyDbl'; public const UNDERLINE_WAVYHEAVY = 'wavyHeavy'; public const UNDERLINE_WORDS = 'words'; - - /* Strike types */ - public const STRIKE_NONE = 'noStrike'; - public const STRIKE_SINGLE = 'sngStrike'; - public const STRIKE_DOUBLE = 'dblStrike'; - public const FORMAT_LATIN = 'latin'; - public const FORMAT_EAST_ASIAN = 'ea'; - public const FORMAT_COMPLEX_SCRIPT = 'cs'; - - public const CAPITALIZATION_NONE = 'none'; - public const CAPITALIZATION_SMALL = 'small'; - public const CAPITALIZATION_ALL = 'all'; - - /* Script sub and super values */ - const SCRIPT_SUPER = 30000; - const SCRIPT_SUB = -25000; + // Script sub and super values + public const BASELINE_SUPERSCRIPT = 300000; + public const BASELINE_SUBSCRIPT = -250000; /** * Name. @@ -72,26 +78,28 @@ class Font implements ComparableInterface private $name = 'Calibri'; /** - * panose + * Panose. * * @var string */ - private $panose; + private $panose = ''; + /** - * pitchFamily + * Pitch Family. * - * @var string + * @var int */ - private $pitchFamily; + private $pitchFamily = 0; + /** - * charset + * Charset. * - * @var string + * @var int */ - private $charset; - + private $charset = self::CHARSET_DEFAULT; + /** - * Font Size + * Font Size. * * @var int */ @@ -112,18 +120,11 @@ class Font implements ComparableInterface private $italic = false; /** - * Superscript. - * - * @var bool - */ - private $superScript = false; - - /** - * Subscript. + * Baseline. * - * @var bool + * @var int */ - private $subScript = false; + private $baseline = 0; /** * Capitalization. @@ -142,9 +143,9 @@ class Font implements ComparableInterface /** * Strikethrough. * - * @var bool + * @var string */ - private $strikethrough = false; + private $strikethrough = self::STRIKE_NONE; /** * Foreground color. @@ -177,9 +178,6 @@ class Font implements ComparableInterface public function __construct() { $this->color = new Color(Color::COLOR_BLACK); - $this->superScript = 0; - $this->subScript = 0; - $this->strikethrough = self::STRIKE_NONE; } /** @@ -199,80 +197,74 @@ public function setName(string $pValue = 'Calibri'): self $pValue = 'Calibri'; } $this->name = $pValue; + return $this; } - + /** - * Get panose - * - * @return string + * Get panose. */ - public function getPanose() + public function getPanose(): string { return $this->panose; } /** - * Set panose - * - * @param string $pValue - * @return \PhpOffice\PhpPresentation\Style\Font + * Set panose. */ - public function setPanose($pValue) + public function setPanose(string $pValue): self { - if ($pValue == '') { - $pValue = ''; + if (mb_strlen($pValue) !== 10) { + throw new InvalidParameterException('pValue', $pValue, 'The length is not equals to 10'); } + + $allowedChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']; + foreach (mb_str_split($pValue) as $char) { + if (!in_array($char, $allowedChars)) { + throw new InvalidParameterException( + 'pValue', + $pValue, + sprintf('The character "%s" is not allowed', $char) + ); + } + } + $this->panose = $pValue; return $this; } + /** - * Get pitchFamily - * - * @return string + * Get pitchFamily. */ - public function getPitchFamily() + public function getPitchFamily(): int { return $this->pitchFamily; } /** - * Set pitchFamily - * - * @param string $pValue - * @return \PhpOffice\PhpPresentation\Style\Font + * Set pitchFamily. */ - public function setPitchFamily($pValue) + public function setPitchFamily(int $pValue): self { - if ($pValue == '') { - $pValue = ''; - } $this->pitchFamily = $pValue; return $this; } + /** - * Get charset - * - * @return string + * Get charset. */ - public function getCharset() + public function getCharset(): int { return $this->charset; } /** - * Set charset - * - * @param string $pValue - * @return \PhpOffice\PhpPresentation\Style\Font + * Set charset. */ - public function setCharset($pValue) + public function setCharset(int $pValue): self { - if ($pValue == '') { - $pValue = ''; - } $this->charset = $pValue; return $this; @@ -352,65 +344,61 @@ public function setItalic(bool $pValue = false): self } /** - * Get SuperScript. + * Set Baseline. */ - public function isSuperScript(): int + public function setBaseline(int $pValue): self { - return $this->superScript; + $this->baseline = $pValue; + + return $this; } /** - * Set SuperScript - * - * @param integer $pValue - * @return \PhpOffice\PhpPresentation\Style\Font + * Get Baseline. */ - public function setSuperScript($pValue = 0) + public function getBaseline(): int { - if ($pValue == '') { - $pValue = 0; - } - - $this->superScript = $pValue; - - // Set SubScript at false only if SuperScript is true - if ($pValue != 0) { - $this->subScript = 0; - } - - return $this; + return $this->baseline; } /** - * Get SubScript + * Get SuperScript. * - * @return integer + * @deprecated getBaseline() === self::BASELINE_SUPERSCRIPT */ - public function isSubScript() + public function isSuperScript(): bool { - return $this->subScript; + return $this->getBaseline() === self::BASELINE_SUPERSCRIPT; } /** - * Set SubScript + * Set SuperScript. * - * @param integer $pValue - * @return \PhpOffice\PhpPresentation\Style\Font + * @deprecated setBaseline(self::BASELINE_SUPERSCRIPT) */ - public function setSubScript($pValue = 0) + public function setSuperScript(bool $pValue = false): self { - if ($pValue == '') { - $pValue = 0; - } - - $this->subScript = $pValue; + return $this->setBaseline($pValue ? self::BASELINE_SUPERSCRIPT : ($this->getBaseline() == self::BASELINE_SUBSCRIPT ? $this->getBaseline() : 0)); + } - // Set SuperScript at false only if SubScript is true - if ($pValue != 0) { - $this->superScript = 0; - } + /** + * Get SubScript. + * + * @deprecated getBaseline() === self::BASELINE_SUBSCRIPT + */ + public function isSubScript(): bool + { + return $this->getBaseline() === self::BASELINE_SUBSCRIPT; + } - return $this; + /** + * Set SubScript. + * + * @deprecated setBaseline(self::BASELINE_SUBSCRIPT) + */ + public function setSubScript(bool $pValue = false): self + { + return $this->setBaseline($pValue ? self::BASELINE_SUBSCRIPT : ($this->getBaseline() == self::BASELINE_SUPERSCRIPT ? $this->getBaseline() : 0)); } /** @@ -463,21 +451,43 @@ public function setUnderline(string $pValue = self::UNDERLINE_NONE): self /** * Get Strikethrough. + * + * @deprecated Use `getStrikethrough` */ public function isStrikethrough(): bool + { + return $this->strikethrough !== self::STRIKE_NONE; + } + + /** + * Get Strikethrough. + */ + public function getStrikethrough(): string { return $this->strikethrough; } /** * Set Strikethrough. + * + * @deprecated $pValue as boolean + * + * @param bool|string $pValue + * + * @return self */ - public function setStrikethrough($pValue = self::STRIKE_NONE) + public function setStrikethrough($pValue = false) { - if ($pValue == '') { - $pValue = self::STRIKE_NONE; + if (is_bool($pValue)) { + $pValue = $pValue ? self::STRIKE_SINGLE : self::STRIKE_NONE; + } + if (in_array($pValue, [ + self::STRIKE_NONE, + self::STRIKE_SINGLE, + self::STRIKE_DOUBLE, + ])) { + $this->strikethrough = $pValue; } - $this->strikethrough = $pValue; return $this; } @@ -536,8 +546,7 @@ public function getHashCode(): string . $this->size . ($this->bold ? 't' : 'f') . ($this->italic ? 't' : 'f') - . ($this->superScript ? 't' : 'f') - . ($this->subScript ? 't' : 'f') + . $this->baseline . $this->underline . ($this->strikethrough ? 't' : 'f') . $this->format diff --git a/src/PhpPresentation/Style/Shadow.php b/src/PhpPresentation/Style/Shadow.php index bdbae7e04..af3b3e1c3 100644 --- a/src/PhpPresentation/Style/Shadow.php +++ b/src/PhpPresentation/Style/Shadow.php @@ -20,12 +20,17 @@ namespace PhpOffice\PhpPresentation\Style; use PhpOffice\PhpPresentation\ComparableInterface; +use PhpOffice\PhpPresentation\Exception\NotAllowedValueException; /** * \PhpOffice\PhpPresentation\Style\Shadow. */ class Shadow implements ComparableInterface { + public const TYPE_SHADOW_INNER = 'innerShdw'; + public const TYPE_SHADOW_OUTER = 'outerShdw'; + public const TYPE_REFLECTION = 'reflection'; + // Shadow alignment public const SHADOW_BOTTOM = 'b'; public const SHADOW_BOTTOM_LEFT = 'bl'; @@ -81,6 +86,11 @@ class Shadow implements ComparableInterface */ private $alpha = 50; + /** + * @var string + */ + private $type = self::TYPE_SHADOW_OUTER; + /** * Hash index. * @@ -224,6 +234,31 @@ public function setAlpha(int $pValue = 0): self return $this; } + /** + * Get Type. + */ + public function getType(): string + { + return $this->type; + } + + /** + * Set Type. + */ + public function setType(string $pValue = self::TYPE_SHADOW_OUTER): self + { + if (!in_array( + $pValue, + [self::TYPE_REFLECTION, self::TYPE_SHADOW_INNER, self::TYPE_SHADOW_OUTER] + )) { + throw new NotAllowedValueException($pValue, [self::TYPE_REFLECTION, self::TYPE_SHADOW_INNER, self::TYPE_SHADOW_OUTER]); + } + + $this->type = $pValue; + + return $this; + } + /** * Get hash code. * @@ -231,7 +266,7 @@ public function setAlpha(int $pValue = 0): self */ public function getHashCode(): string { - return md5(($this->visible ? 't' : 'f') . $this->blurRadius . $this->distance . $this->direction . $this->alignment . $this->color->getHashCode() . $this->alpha . __CLASS__); + return md5(($this->visible ? 't' : 'f') . $this->blurRadius . $this->distance . $this->direction . $this->alignment . $this->type . $this->color->getHashCode() . $this->alpha . __CLASS__); } /** diff --git a/src/PhpPresentation/Traits/ShapeCollection.php b/src/PhpPresentation/Traits/ShapeCollection.php new file mode 100644 index 000000000..6c7582cb1 --- /dev/null +++ b/src/PhpPresentation/Traits/ShapeCollection.php @@ -0,0 +1,96 @@ + + */ + protected $shapeCollection = []; + + /** + * Get collection of shapes. + * + * @return array + */ + public function getShapeCollection(): array + { + return $this->shapeCollection; + } + + /** + * Search into collection of shapes for a name or/and a type. + * + * @return array + */ + public function searchShapes(?string $name = null, ?string $type = null): array + { + $found = []; + foreach ($this->getShapeCollection() as $shape) { + if ($name && $shape->getName() !== $name) { + continue; + } + if ($type && get_class($shape) !== $type) { + continue; + } + + $found[] = $shape; + } + + return $found; + } + + /** + * Get collection of shapes. + * + * @param array $shapeCollection + */ + public function setShapeCollection(array $shapeCollection = []): self + { + $this->shapeCollection = $shapeCollection; + + return $this; + } + + /** + * @return static + */ + public function addShape(AbstractShape $shape) + { + $this->shapeCollection[] = $shape; + + return $this; + } + + /** + * @return static + */ + public function unsetShape(int $key) + { + unset($this->shapeCollection[$key]); + + return $this; + } +} diff --git a/src/PhpPresentation/Writer/AbstractDecoratorWriter.php b/src/PhpPresentation/Writer/AbstractDecoratorWriter.php index aab1d0eda..ddcce2a31 100644 --- a/src/PhpPresentation/Writer/AbstractDecoratorWriter.php +++ b/src/PhpPresentation/Writer/AbstractDecoratorWriter.php @@ -28,7 +28,7 @@ abstract class AbstractDecoratorWriter abstract public function render(): ZipInterface; /** - * @var \PhpOffice\PhpPresentation\HashTable + * @var HashTable */ protected $oHashTable; diff --git a/src/PhpPresentation/Writer/AbstractWriter.php b/src/PhpPresentation/Writer/AbstractWriter.php index 3d935c417..edbfb89c8 100644 --- a/src/PhpPresentation/Writer/AbstractWriter.php +++ b/src/PhpPresentation/Writer/AbstractWriter.php @@ -19,7 +19,6 @@ namespace PhpOffice\PhpPresentation\Writer; -use ArrayIterator; use PhpOffice\Common\Adapter\Zip\ZipInterface; use PhpOffice\PhpPresentation\AbstractShape; use PhpOffice\PhpPresentation\HashTable; @@ -116,7 +115,7 @@ protected function allDrawings(): array // Loop through PhpPresentation foreach (array_merge($this->getPhpPresentation()->getAllSlides(), $aSlideMasters, $aSlideLayouts) as $oSlide) { - $arrayReturn = $this->iterateCollection($oSlide->getShapeCollection()->getIterator()); + $arrayReturn = $this->iterateCollection($oSlide->getShapeCollection()); $aDrawings = array_merge($aDrawings, $arrayReturn); } @@ -124,28 +123,23 @@ protected function allDrawings(): array } /** - * @param ArrayIterator $oIterator + * @param array $collection * * @return array */ - private function iterateCollection(ArrayIterator $oIterator): array + private function iterateCollection(array $collection): array { $arrayReturn = []; - if ($oIterator->count() <= 0) { - return $arrayReturn; - } - while ($oIterator->valid()) { - $oShape = $oIterator->current(); + foreach ($collection as $oShape) { if ($oShape instanceof AbstractDrawingAdapter) { $arrayReturn[] = $oShape; } elseif ($oShape instanceof Chart) { $arrayReturn[] = $oShape; } elseif ($oShape instanceof Group) { - $arrayGroup = $this->iterateCollection($oShape->getShapeCollection()->getIterator()); + $arrayGroup = $this->iterateCollection($oShape->getShapeCollection()); $arrayReturn = array_merge($arrayReturn, $arrayGroup); } - $oIterator->next(); } return $arrayReturn; diff --git a/src/PhpPresentation/Writer/ODPresentation.php b/src/PhpPresentation/Writer/ODPresentation.php index 5c8432fac..f142fe06c 100644 --- a/src/PhpPresentation/Writer/ODPresentation.php +++ b/src/PhpPresentation/Writer/ODPresentation.php @@ -156,7 +156,7 @@ public function hasDiskCaching() * * @param string $directory Disk caching directory * - * @return \PhpOffice\PhpPresentation\Writer\ODPresentation + * @return ODPresentation */ public function setUseDiskCaching(bool $pValue = false, ?string $directory = null) { diff --git a/src/PhpPresentation/Writer/ODPresentation/Content.php b/src/PhpPresentation/Writer/ODPresentation/Content.php index c12a2fc11..33de96a40 100644 --- a/src/PhpPresentation/Writer/ODPresentation/Content.php +++ b/src/PhpPresentation/Writer/ODPresentation/Content.php @@ -27,7 +27,6 @@ use PhpOffice\PhpPresentation\Shape\Chart; use PhpOffice\PhpPresentation\Shape\Comment; use PhpOffice\PhpPresentation\Shape\Drawing\AbstractDrawingAdapter; -use PhpOffice\PhpPresentation\Shape\Drawing as ShapeDrawing; use PhpOffice\PhpPresentation\Shape\Group; use PhpOffice\PhpPresentation\Shape\Line; use PhpOffice\PhpPresentation\Shape\Media; @@ -448,10 +447,8 @@ protected function writeShapeMedia(XMLWriter $objWriter, Media $shape): void /** * Write picture. - * - * @param AbstractDrawingAdapter $shape */ - protected function writeShapeDrawing(XMLWriter $objWriter, ShapeDrawing\AbstractDrawingAdapter $shape): void + protected function writeShapeDrawing(XMLWriter $objWriter, AbstractDrawingAdapter $shape): void { // draw:frame $objWriter->startElement('draw:frame'); @@ -565,9 +562,9 @@ protected function writeShapeTxt(XMLWriter $objWriter, RichText $shape): void } } $objWriter->endElement(); - //=============================================== - // Bullet list - //=============================================== + //=============================================== + // Bullet list + //=============================================== } elseif ('bullet' == $paragraph->getBulletStyle()->getBulletType()) { $bCstShpHasBullet = true; // Open the bullet list diff --git a/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php b/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php index c58b25d60..e2f896c2a 100644 --- a/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php +++ b/src/PhpPresentation/Writer/ODPresentation/ObjectsChart.php @@ -311,7 +311,7 @@ protected function writeAxisStyle(Chart $chart): void $this->writeGridlineStyle($chart->getPlotArea()->getAxisY()->getMinorGridlines(), 'styleAxisYGridlinesMinor'); } - protected function writeAxisMainStyle(Chart\Axis $axis, string $styleName, AbstractType $chartType): void + protected function writeAxisMainStyle(Axis $axis, string $styleName, AbstractType $chartType): void { // style:style $this->xmlContent->startElement('style:style'); @@ -363,7 +363,7 @@ protected function writeAxisMainStyle(Chart\Axis $axis, string $styleName, Abstr $this->xmlContent->endElement(); } - protected function writeAxisTitleStyle(Chart\Axis $axis, string $styleName): void + protected function writeAxisTitleStyle(Axis $axis, string $styleName): void { // style:style $this->xmlContent->startElement('style:style'); diff --git a/src/PhpPresentation/Writer/PowerPoint2007.php b/src/PhpPresentation/Writer/PowerPoint2007.php index a116ca8a3..dd46c37ee 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007.php +++ b/src/PhpPresentation/Writer/PowerPoint2007.php @@ -147,7 +147,7 @@ public function hasDiskCaching() * * @param string $directory Disk caching directory * - * @return \PhpOffice\PhpPresentation\Writer\PowerPoint2007 + * @return PowerPoint2007 */ public function setUseDiskCaching(bool $useDiskCaching = false, ?string $directory = null) { diff --git a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php index 79ea0c22a..58ef3b244 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/AbstractSlide.php @@ -49,6 +49,7 @@ use PhpOffice\PhpPresentation\Style\Border; use PhpOffice\PhpPresentation\Style\Bullet; use PhpOffice\PhpPresentation\Style\Color; +use PhpOffice\PhpPresentation\Style\Font; use PhpOffice\PhpPresentation\Style\Shadow; abstract class AbstractSlide extends AbstractDecoratorWriter @@ -58,60 +59,56 @@ abstract class AbstractSlide extends AbstractDecoratorWriter */ protected function writeDrawingRelations(AbstractSlideAlias $pSlideMaster, XMLWriter $objWriter, int $relId) { - if ($pSlideMaster->getShapeCollection()->count() > 0) { + if (count($pSlideMaster->getShapeCollection()) > 0) { // Loop trough images and write relationships - $iterator = $pSlideMaster->getShapeCollection()->getIterator(); - while ($iterator->valid()) { - if ($iterator->current() instanceof ShapeDrawingFile || $iterator->current() instanceof ShapeDrawingGd) { + foreach ($pSlideMaster->getShapeCollection() as $shape) { + if ($shape instanceof ShapeDrawingFile || $shape instanceof ShapeDrawingGd) { // Write relationship for image drawing $this->writeRelationship( $objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', - '../media/' . str_replace(' ', '_', $iterator->current()->getIndexedFilename()) + '../media/' . str_replace(' ', '_', $shape->getIndexedFilename()) ); - $iterator->current()->relationId = 'rId' . $relId; + $shape->relationId = 'rId' . $relId; ++$relId; - } elseif ($iterator->current() instanceof ShapeChart) { + } elseif ($shape instanceof ShapeChart) { // Write relationship for chart drawing $this->writeRelationship( $objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', - '../charts/' . $iterator->current()->getIndexedFilename() + '../charts/' . $shape->getIndexedFilename() ); - $iterator->current()->relationId = 'rId' . $relId; + $shape->relationId = 'rId' . $relId; ++$relId; - } elseif ($iterator->current() instanceof Group) { - $iterator2 = $iterator->current()->getShapeCollection()->getIterator(); - while ($iterator2->valid()) { - if ($iterator2->current() instanceof ShapeDrawingFile || - $iterator2->current() instanceof ShapeDrawingGd + } elseif ($shape instanceof Group) { + foreach ($shape->getShapeCollection() as $subShape) { + if ($subShape instanceof ShapeDrawingFile || + $subShape instanceof ShapeDrawingGd ) { // Write relationship for image drawing $this->writeRelationship( $objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', - '../media/' . str_replace(' ', '_', $iterator2->current()->getIndexedFilename()) + '../media/' . str_replace(' ', '_', $subShape->getIndexedFilename()) ); - $iterator2->current()->relationId = 'rId' . $relId; + $subShape->relationId = 'rId' . $relId; ++$relId; - } elseif ($iterator2->current() instanceof ShapeChart) { + } elseif ($subShape instanceof ShapeChart) { // Write relationship for chart drawing $this->writeRelationship( $objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', - '../charts/' . $iterator2->current()->getIndexedFilename() + '../charts/' . $subShape->getIndexedFilename() ); - $iterator2->current()->relationId = 'rId' . $relId; + $subShape->relationId = 'rId' . $relId; ++$relId; } - $iterator2->next(); } } - $iterator->next(); } } @@ -228,7 +225,7 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh $this->writeFill($objWriter, $shape->getFill()); $this->writeBorder($objWriter, $shape->getBorder(), ''); - $this->writeEffect($objWriter, $shape->getEffectCollection()); + $this->writeShadow($objWriter, $shape->getShadow()); // > p:sp\p:spPr $objWriter->endElement(); @@ -238,10 +235,12 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh //@link :http://msdn.microsoft.com/en-us/library/documentformat.openxml.drawing.bodyproperties%28v=office.14%29.aspx $objWriter->startElement('a:bodyPr'); if (!$shape->isPlaceholder()) { + // Vertical alignment $verticalAlign = $shape->getActiveParagraph()->getAlignment()->getVertical(); if (Alignment::VERTICAL_BASE != $verticalAlign && Alignment::VERTICAL_AUTO != $verticalAlign) { $objWriter->writeAttribute('anchor', $verticalAlign); } + $objWriter->writeAttribute('anchorCtr', $shape->getVerticalAlignCenter()); if (RichText::WRAP_SQUARE != $shape->getWrap()) { $objWriter->writeAttribute('wrap', $shape->getWrap()); } @@ -255,20 +254,12 @@ protected function writeShapeText(XMLWriter $objWriter, RichText $shape, int $sh if ($shape->isUpright()) { $objWriter->writeAttribute('upright', '1'); } - if ($shape->isVertical()) { - $objWriter->writeAttribute('vert', 'vert'); - } - else { - $objWriter->writeAttribute('vert', 'horz'); - } + $objWriter->writeAttribute('vert', $shape->isVertical() ? 'vert' : 'horz'); $objWriter->writeAttribute('bIns', CommonDrawing::pixelsToEmu($shape->getInsetBottom())); $objWriter->writeAttribute('lIns', CommonDrawing::pixelsToEmu($shape->getInsetLeft())); $objWriter->writeAttribute('rIns', CommonDrawing::pixelsToEmu($shape->getInsetRight())); $objWriter->writeAttribute('tIns', CommonDrawing::pixelsToEmu($shape->getInsetTop())); - // Vertical alignment - $objWriter->writeAttribute('anchor', $shape->getVerticalAlignment()); - $objWriter->writeAttribute('anchorCtr', (int)$shape->getVerticalAlignCenter()); - if ($shape->getColumns() <> 1) { + if ($shape->getColumns() != 1) { $objWriter->writeAttribute('numCol', $shape->getColumns()); $objWriter->writeAttribute('spcCol', CommonDrawing::pixelsToEmu($shape->getColumnSpacing())); } @@ -571,7 +562,7 @@ protected function writeParagraphs(XMLWriter $objWriter, array $paragraphs): voi /** * Write Paragraph Styles (a:pPr). */ - protected function writeParagraphStyles(XMLWriter $objWriter, RichText\Paragraph $paragraph, bool $isPlaceholder = false): void + protected function writeParagraphStyles(XMLWriter $objWriter, Paragraph $paragraph, bool $isPlaceholder = false): void { $objWriter->startElement('a:pPr'); $objWriter->writeAttribute('algn', $paragraph->getAlignment()->getHorizontal()); @@ -645,7 +636,7 @@ protected function writeParagraphStyles(XMLWriter $objWriter, RichText\Paragraph /** * Write RichTextElement Styles (a:pPr). */ - protected function writeRunStyles(XMLWriter $objWriter, RichText\Run $element): void + protected function writeRunStyles(XMLWriter $objWriter, Run $element): void { // a:rPr $objWriter->startElement('a:rPr'); @@ -655,7 +646,9 @@ protected function writeRunStyles(XMLWriter $objWriter, RichText\Run $element): $objWriter->writeAttributeIf($element->getFont()->isBold(), 'b', '1'); $objWriter->writeAttributeIf($element->getFont()->isItalic(), 'i', '1'); - $objWriter->writeAttributeIf($element->getFont()->isStrikethrough(), 'strike', $element->getFont()->isStrikethrough()); + + // Strikethrough + $objWriter->writeAttribute('strike', $element->getFont()->getStrikethrough()); // Size $objWriter->writeAttribute('sz', ($element->getFont()->getSize() * 100)); @@ -669,30 +662,37 @@ protected function writeRunStyles(XMLWriter $objWriter, RichText\Run $element): // Capitalization $objWriter->writeAttribute('cap', $element->getFont()->getCapitalization()); - // Superscript / subscript - $objWriter->writeAttributeIf($element->getFont()->isSuperScript() != 0, 'baseline', (int)$element->getFont()->isSuperScript()); - $objWriter->writeAttributeIf($element->getFont()->isSubScript() != 0, 'baseline', (int)$element->getFont()->isSubScript()); + // Baseline + $objWriter->writeAttributeIf($element->getFont()->getBaseline() !== 0, 'baseline', $element->getFont()->getBaseline()); // Color - a:solidFill $objWriter->startElement('a:solidFill'); $this->writeColor($objWriter, $element->getFont()->getColor()); $objWriter->endElement(); - // Write Effects - $this->writeEffect($objWriter, $element->getEffectCollection(), 'srgbClr'); - // Font // - a:latin // - a:ea // - a:cs $objWriter->startElement('a:' . $element->getFont()->getFormat()); $objWriter->writeAttribute('typeface', $element->getFont()->getName()); - if ($element->getFont()->getPanose()!="") - $objWriter->writeAttribute('panose', $element->getFont()->getPanose()); - if ($element->getFont()->getPitchFamily()!="") - $objWriter->writeAttribute('pitchFamily', $element->getFont()->getPitchFamily()); - if ($element->getFont()->getCharset()!="") - $objWriter->writeAttribute('charset', $element->getFont()->getCharset()); + if ($element->getFont()->getPanose() !== '') { + $panose = array_map(function (string $value) { + return '0' . $value; + }, str_split($element->getFont()->getPanose())); + + $objWriter->writeAttribute('panose', implode('', $panose)); + } + $objWriter->writeAttributeIf( + $element->getFont()->getPitchFamily() !== 0, + 'pitchFamily', + $element->getFont()->getPitchFamily() + ); + $objWriter->writeAttributeIf( + $element->getFont()->getCharset() !== Font::CHARSET_DEFAULT, + 'charset', + dechex($element->getFont()->getCharset()) + ); $objWriter->endElement(); // a:hlinkClick @@ -806,7 +806,7 @@ protected function writeShadow(XMLWriter $objWriter, Shadow $oShadow): void $objWriter->startElement('a:effectLst'); // a:outerShdw - $objWriter->startElement('a:outerShdw'); + $objWriter->startElement('a:' . $oShadow->getType()); $objWriter->writeAttribute('blurRad', CommonDrawing::pixelsToEmu($oShadow->getBlurRadius())); $objWriter->writeAttribute('dist', CommonDrawing::pixelsToEmu($oShadow->getDistance())); $objWriter->writeAttribute('dir', CommonDrawing::degreesToAngle((int) $oShadow->getDirection())); @@ -821,55 +821,7 @@ protected function writeShadow(XMLWriter $objWriter, Shadow $oShadow): void } /** - * Write Effect - * @param XMLWriter $objWriter - * @param array \PhpOffice\PhpPresentation\Style\Effect[] - * @param Shadow $oShadow - */ - protected function writeEffect(XMLWriter $objWriter, ?array $aEffect, ?string $tagClr=null) - { - // NO Effect => return - if (!isset($aEffect) && !is_array($aEffect)) { - return; - } - if (!isset($tagClr)) { - $tagClr = 'prstClr'; - } - - // a:effectLst - $objWriter->startElement('a:effectLst'); - // Write each effect - foreach($aEffect as $effect) { - // a: - if ( $effect->getEffectType() == 'outerShdw' - || $effect->getEffectType() == 'innerShdw') { -// @TODO || $effect->getEffectType() == 'reflection') { - - $objWriter->startElement('a:'.$effect->getEffectType()); - $objWriter->writeAttribute('blurRad', CommonDrawing::pixelsToEmu($effect->getBlurRadius())); - $objWriter->writeAttribute('dist', CommonDrawing::pixelsToEmu($effect->getDistance())); - $objWriter->writeAttribute('dir', CommonDrawing::degreesToAngle($effect->getDirection())); - $objWriter->writeAttribute('algn', $effect->getAlignment()); - $objWriter->writeAttribute('rotWithShape', '0'); - - // a:prstClr - $objWriter->startElement('a:'.$tagClr); - $objWriter->writeAttribute('val', $effect->getColor()->getRGB()); - // a:alpha - $objWriter->startElement('a:alpha'); - $objWriter->writeAttribute('val', $effect->getAlpha() * 1000); - $objWriter->endElement(); - $objWriter->endElement(); - - $objWriter->endElement(); - } - } - - $objWriter->endElement(); - } - - /** - * Write hyperlink + * Write hyperlink. * * @param XMLWriter $objWriter XML Writer * @param AbstractShape|TextElement $shape @@ -1500,7 +1452,7 @@ protected function writeShapePic(XMLWriter $objWriter, AbstractGraphic $shape, i $this->writeFill($objWriter, $shape->getFill()); $this->writeBorder($objWriter, $shape->getBorder(), ''); - $this->writeEffect($objWriter, $shape->getEffectCollection()); + $this->writeShadow($objWriter, $shape->getShadow()); $objWriter->endElement(); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php b/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php index 541e8c1d1..aa8ea2a9d 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/ContentTypes.php @@ -85,7 +85,7 @@ public function render(): ZipInterface for ($i = 0; $i < $slideCount; ++$i) { $oSlide = $this->oPresentation->getSlide($i); $this->writeOverrideContentType($objWriter, '/ppt/slides/slide' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml'); - if ($oSlide->getNote()->getShapeCollection()->count() > 0) { + if (count($oSlide->getNote()->getShapeCollection()) > 0) { $this->writeOverrideContentType($objWriter, '/ppt/notesSlides/notesSlide' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml'); } foreach ($oSlide->getShapeCollection() as $oShape) { diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php index 6df85cde0..d21f6863a 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsCore.php @@ -70,18 +70,17 @@ public function render(): ZipInterface // cp:keywords $objWriter->writeElement('cp:keywords', $this->oPresentation->getDocumentProperties()->getKeywords()); + // cp:category + $objWriter->writeElement('cp:category', $this->oPresentation->getDocumentProperties()->getCategory()); + // cp:revision $objWriter->writeElement('cp:revision', $this->oPresentation->getDocumentProperties()->getRevision()); // cp:contentStatus - $objWriter->writeElement('cp:contentStatus', $this->oPresentation->getDocumentProperties()->getStatus()); - - // cp:category - $objWriter->writeElement('cp:category', $this->oPresentation->getDocumentProperties()->getCategory()); - if ($this->oPresentation->getPresentationProperties()->isMarkedAsFinal()) { - // cp:contentStatus = Final $objWriter->writeElement('cp:contentStatus', 'Final'); + } else { + $objWriter->writeElement('cp:contentStatus', $this->oPresentation->getDocumentProperties()->getStatus()); } $objWriter->endElement(); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php index 103309e5c..aac86bc75 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/DocPropsThumbnail.php @@ -25,26 +25,9 @@ class DocPropsThumbnail extends AbstractDecoratorWriter { public function render(): ZipInterface { - $pathThumbnail = $this->getPresentation()->getPresentationProperties()->getThumbnailPath(); - $type = $this->getPresentation()->getPresentationProperties()->getThumbnailType(); - - // From local file - if ($pathThumbnail && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_FILE) { - $fileThumbnail = file_get_contents($pathThumbnail); - $gdImage = imagecreatefromstring($fileThumbnail); - if ($gdImage) { - ob_start(); - imagejpeg($gdImage); - $imageContents = ob_get_contents(); - ob_end_clean(); - imagedestroy($gdImage); - $this->getZip()->addFromString('docProps/thumbnail.jpeg', $imageContents); - } - } - - // From ZIP original file - if ($pathThumbnail && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP) { - $gdImage = imagecreatefromstring($this->getPresentation()->getPresentationProperties()->getThumbnail()); + $thumnbail = $this->getPresentation()->getPresentationProperties()->getThumbnail(); + if ($thumnbail) { + $gdImage = imagecreatefromstring($thumnbail); if ($gdImage) { ob_start(); imagejpeg($gdImage); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php b/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php index d2cd90410..f28fb74ad 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php @@ -447,11 +447,10 @@ protected function writeTitle(XMLWriter $objWriter, Title $subject): void $objWriter->writeAttribute('dirty', '0'); $objWriter->writeAttribute('b', ($subject->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($subject->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($subject->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $subject->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($subject->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $subject->getFont()->getUnderline()); - $objWriter->writeAttributeIf($subject->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($subject->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($subject->getFont()->getBaseline() !== 0, 'baseline', $subject->getFont()->getBaseline()); $objWriter->writeAttribute('cap', $subject->getFont()->getCapitalization()); // Font - a:solidFill @@ -550,7 +549,6 @@ protected function writePlotArea(XMLWriter $objWriter, PlotArea $subject, Chart * Write Legend. * * @param XMLWriter $objWriter XML Writer - * @param Chart\Legend $subject */ protected function writeLegend(XMLWriter $objWriter, Legend $subject): void { @@ -609,11 +607,10 @@ protected function writeLegend(XMLWriter $objWriter, Legend $subject): void $objWriter->writeAttribute('b', ($subject->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($subject->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($subject->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $subject->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($subject->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $subject->getFont()->getUnderline()); - $objWriter->writeAttributeIf($subject->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($subject->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($subject->getFont()->getBaseline() !== 0, 'baseline', $subject->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -703,7 +700,6 @@ protected function writeLayout(XMLWriter $objWriter, $subject): void * Write Type Area. * * @param XMLWriter $objWriter XML Writer - * @param Chart\Type\Area $subject */ protected function writeTypeArea(XMLWriter $objWriter, Area $subject, bool $includeSheet = false): void { @@ -804,7 +800,6 @@ protected function writeTypeArea(XMLWriter $objWriter, Area $subject, bool $incl * Write Type Bar. * * @param XMLWriter $objWriter XML Writer - * @param Chart\Type\Bar $subject */ protected function writeTypeBar(XMLWriter $objWriter, Bar $subject, bool $includeSheet = false): void { @@ -895,11 +890,10 @@ protected function writeTypeBar(XMLWriter $objWriter, Bar $subject, bool $includ $objWriter->startElement('a:defRPr'); $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // a:solidFill $objWriter->startElement('a:solidFill'); @@ -1018,7 +1012,6 @@ protected function writeTypeBar(XMLWriter $objWriter, Bar $subject, bool $includ * Write Type Bar3D. * * @param XMLWriter $objWriter XML Writer - * @param Chart\Type\Bar3D $subject */ protected function writeTypeBar3D(XMLWriter $objWriter, Bar3D $subject, bool $includeSheet = false): void { @@ -1102,11 +1095,10 @@ protected function writeTypeBar3D(XMLWriter $objWriter, Bar3D $subject, bool $in $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -1311,11 +1303,10 @@ protected function writeTypeDoughnut(XMLWriter $objWriter, Doughnut $subject, bo $objWriter->startElement('a:defRPr'); $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // c:dLbls\c:txPr\a:p\a:pPr\a:defRPr\a:solidFill $objWriter->startElement('a:solidFill'); @@ -1454,11 +1445,10 @@ protected function writeTypePie(XMLWriter $objWriter, Pie $subject, bool $includ $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -1618,11 +1608,10 @@ protected function writeTypePie3D(XMLWriter $objWriter, Pie3D $subject, bool $in $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -1771,11 +1760,10 @@ protected function writeTypeLine(XMLWriter $objWriter, Line $subject, bool $incl $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -1947,11 +1935,10 @@ protected function writeTypeRadar(XMLWriter $objWriter, Radar $subject, bool $in $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '30000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-25000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -2113,11 +2100,10 @@ protected function writeTypeScatter(XMLWriter $objWriter, Scatter $subject, bool $objWriter->writeAttribute('b', ($series->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($series->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($series->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $series->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($series->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $series->getFont()->getUnderline()); - $objWriter->writeAttributeIf($series->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($series->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($series->getFont()->getBaseline() !== 0, 'baseline', $series->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -2392,11 +2378,10 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty $objWriter->writeAttribute('b', ($oAxis->getFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($oAxis->getFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($oAxis->getFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $oAxis->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($oAxis->getFont()->getSize() * 100)); $objWriter->writeAttribute('u', $oAxis->getFont()->getUnderline()); - $objWriter->writeAttributeIf($oAxis->getFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($oAxis->getFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($oAxis->getFont()->getBaseline() !== 0, 'baseline', $oAxis->getFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); @@ -2496,11 +2481,10 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty $objWriter->startElement('a:defRPr'); $objWriter->writeAttribute('b', ($oAxis->getTickLabelFont()->isBold() ? 'true' : 'false')); $objWriter->writeAttribute('i', ($oAxis->getTickLabelFont()->isItalic() ? 'true' : 'false')); - $objWriter->writeAttribute('strike', ($oAxis->getTickLabelFont()->isStrikethrough() ? 'sngStrike' : 'noStrike')); + $objWriter->writeAttribute('strike', $oAxis->getFont()->getStrikethrough()); $objWriter->writeAttribute('sz', ($oAxis->getTickLabelFont()->getSize() * 100)); $objWriter->writeAttribute('u', $oAxis->getTickLabelFont()->getUnderline()); - $objWriter->writeAttributeIf($oAxis->getTickLabelFont()->isSuperScript(), 'baseline', '300000'); - $objWriter->writeAttributeIf($oAxis->getTickLabelFont()->isSubScript(), 'baseline', '-250000'); + $objWriter->writeAttributeIf($oAxis->getTickLabelFont()->getBaseline() !== 0, 'baseline', $oAxis->getTickLabelFont()->getBaseline()); // Font - a:solidFill $objWriter->startElement('a:solidFill'); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/PptSlides.php b/src/PhpPresentation/Writer/PowerPoint2007/PptSlides.php index 00da6cbf8..de600cdf1 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/PptSlides.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/PptSlides.php @@ -49,7 +49,7 @@ public function render(): ZipInterface // Add note slide if ($oSlide->getNote() instanceof Note) { - if ($oSlide->getNote()->getShapeCollection()->count() > 0) { + if (count($oSlide->getNote()->getShapeCollection()) > 0) { $this->oZip->addFromString('ppt/notesSlides/notesSlide' . ($idx + 1) . '.xml', $this->writeNote($oSlide->getNote())); } } @@ -96,16 +96,14 @@ protected function writeSlideRelationships(Slide $pSlide): string ++$relId; // Write drawing relationships? - if ($pSlide->getShapeCollection()->count() > 0) { - $collections = [$pSlide->getShapeCollection()->getIterator()]; + if (count($pSlide->getShapeCollection()) > 0) { + $collections = [$pSlide->getShapeCollection()]; // Loop trough images and write relationships while (count($collections)) { - $iterator = array_shift($collections); - - while ($iterator->valid()) { - $currentShape = $iterator->current(); + $collection = array_shift($collections); + foreach ($collection as $currentShape) { if ($currentShape instanceof Media) { // Write relationship for image drawing $currentShape->relationId = 'rId' . $relId; @@ -124,10 +122,8 @@ protected function writeSlideRelationships(Slide $pSlide): string $currentShape->relationId = 'rId' . $relId; ++$relId; } elseif ($currentShape instanceof ShapeContainerInterface) { - $collections[] = $currentShape->getShapeCollection()->getIterator(); + $collections[] = $currentShape->getShapeCollection(); } - - $iterator->next(); } } } @@ -141,14 +137,13 @@ protected function writeSlideRelationships(Slide $pSlide): string } // Write hyperlink relationships? - if ($pSlide->getShapeCollection()->count() > 0) { + if (count($pSlide->getShapeCollection()) > 0) { // Loop trough hyperlinks and write relationships - $iterator = $pSlide->getShapeCollection()->getIterator(); - while ($iterator->valid()) { + foreach ($pSlide->getShapeCollection() as $shape) { // Hyperlink on shape - if ($iterator->current()->hasHyperlink()) { + if ($shape->hasHyperlink()) { // Write relationship for hyperlink - $hyperlink = $iterator->current()->getHyperlink(); + $hyperlink = $shape->getHyperlink(); $hyperlink->relationId = 'rId' . $relId; if (!$hyperlink->isInternal()) { @@ -161,8 +156,8 @@ protected function writeSlideRelationships(Slide $pSlide): string } // Hyperlink on rich text run - if ($iterator->current() instanceof RichText) { - foreach ($iterator->current()->getParagraphs() as $paragraph) { + if ($shape instanceof RichText) { + foreach ($shape->getParagraphs() as $paragraph) { foreach ($paragraph->getRichTextElements() as $element) { if ($element instanceof Run || $element instanceof TextElement) { if ($element->hasHyperlink()) { @@ -184,14 +179,14 @@ protected function writeSlideRelationships(Slide $pSlide): string } // Hyperlink in table - if ($iterator->current() instanceof ShapeTable) { + if ($shape instanceof ShapeTable) { // Rows - $countRows = count($iterator->current()->getRows()); + $countRows = count($shape->getRows()); for ($row = 0; $row < $countRows; ++$row) { // Cells in rows - $countCells = count($iterator->current()->getRow($row)->getCells()); + $countCells = count($shape->getRow($row)->getCells()); for ($cell = 0; $cell < $countCells; ++$cell) { - $currentCell = $iterator->current()->getRow($row)->getCell($cell); + $currentCell = $shape->getRow($row)->getCell($cell); // Paragraphs in cell foreach ($currentCell->getParagraphs() as $paragraph) { // RichText in paragraph @@ -218,13 +213,12 @@ protected function writeSlideRelationships(Slide $pSlide): string } } - if ($iterator->current() instanceof Group) { - $iterator2 = $pSlide->getShapeCollection()->getIterator(); - while ($iterator2->valid()) { + if ($shape instanceof Group) { + foreach ($shape->getShapeCollection() as $subShape) { // Hyperlink on shape - if ($iterator2->current()->hasHyperlink()) { + if ($subShape->hasHyperlink()) { // Write relationship for hyperlink - $hyperlink = $iterator2->current()->getHyperlink(); + $hyperlink = $subShape->getHyperlink(); $hyperlink->relationId = 'rId' . $relId; if (!$hyperlink->isInternal()) { @@ -237,8 +231,8 @@ protected function writeSlideRelationships(Slide $pSlide): string } // Hyperlink on rich text run - if ($iterator2->current() instanceof RichText) { - foreach ($iterator2->current()->getParagraphs() as $paragraph) { + if ($subShape instanceof RichText) { + foreach ($subShape->getParagraphs() as $paragraph) { foreach ($paragraph->getRichTextElements() as $element) { if ($element instanceof Run || $element instanceof TextElement) { if ($element->hasHyperlink()) { @@ -260,14 +254,14 @@ protected function writeSlideRelationships(Slide $pSlide): string } // Hyperlink in table - if ($iterator2->current() instanceof ShapeTable) { + if ($subShape instanceof ShapeTable) { // Rows - $countRows = count($iterator2->current()->getRows()); + $countRows = count($subShape->getRows()); for ($row = 0; $row < $countRows; ++$row) { // Cells in rows - $countCells = count($iterator2->current()->getRow($row)->getCells()); + $countCells = count($subShape->getRow($row)->getCells()); for ($cell = 0; $cell < $countCells; ++$cell) { - $currentCell = $iterator2->current()->getRow($row)->getCell($cell); + $currentCell = $subShape->getRow($row)->getCell($cell); // Paragraphs in cell foreach ($currentCell->getParagraphs() as $paragraph) { // RichText in paragraph @@ -293,39 +287,30 @@ protected function writeSlideRelationships(Slide $pSlide): string } } } - - $iterator2->next(); } } - - $iterator->next(); } } // Write comment relationships - if ($pSlide->getShapeCollection()->count() > 0) { + if (count($pSlide->getShapeCollection()) > 0) { $hasSlideComment = false; // Loop trough images and write relationships - $iterator = $pSlide->getShapeCollection()->getIterator(); - while ($iterator->valid()) { - if ($iterator->current() instanceof Comment) { + foreach ($pSlide->getShapeCollection() as $shape) { + if ($shape instanceof Comment) { $hasSlideComment = true; break; - } elseif ($iterator->current() instanceof Group) { - $iterator2 = $iterator->current()->getShapeCollection()->getIterator(); - while ($iterator2->valid()) { - if ($iterator2->current() instanceof Comment) { + } elseif ($shape instanceof Group) { + foreach ($shape->getShapeCollection() as $subShape) { + if ($subShape instanceof Comment) { $hasSlideComment = true; break 2; } - $iterator2->next(); } } - - $iterator->next(); } if ($hasSlideComment) { @@ -334,7 +319,7 @@ protected function writeSlideRelationships(Slide $pSlide): string } } - if ($pSlide->getNote()->getShapeCollection()->count() > 0) { + if (count($pSlide->getNote()->getShapeCollection()) > 0) { $this->writeRelationship($objWriter, $relId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide', '../notesSlides/notesSlide' . ($idxSlide + 1) . '.xml'); } @@ -386,7 +371,7 @@ protected function writeSlide(Slide $pSlide): string $objWriter->endElement(); } - if ($oBackground instanceof Slide\Background\Image) { + if ($oBackground instanceof Image) { // a:blipFill $objWriter->startElement('a:blipFill'); diff --git a/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php b/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php index 804c175e2..7d652778c 100644 --- a/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php +++ b/src/PhpPresentation/Writer/PowerPoint2007/Relationships.php @@ -63,29 +63,18 @@ protected function writeRelationships(): string $this->writeRelationship($objWriter, 4, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties', 'docProps/custom.xml'); $idxRelation = 5; - // Thumbnail - $path = $this->getPresentation()->getPresentationProperties()->getThumbnailPath(); - $type = $this->getPresentation()->getPresentationProperties()->getThumbnailType(); - // From local file - if ($path && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_FILE) { - $pathThumbnail = file_get_contents($path); - $gdImage = imagecreatefromstring($pathThumbnail); - if ($gdImage) { - imagedestroy($gdImage); - // Relationship docProps/thumbnail.jpeg - $this->writeRelationship($objWriter, $idxRelation, 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail', 'docProps/thumbnail.jpeg'); - } - } - // From ZIP original file - if ($path && $type == \PhpOffice\PhpPresentation\PresentationProperties::THUMBNAIL_ZIP) { - $gdImage = imagecreatefromstring($this->getPresentation()->getPresentationProperties()->getThumbnail()); + + // Relationship docProps/thumbnail.jpeg + $thumnbail = $this->getPresentation()->getPresentationProperties()->getThumbnail(); + if ($thumnbail) { + $gdImage = imagecreatefromstring($thumnbail); if ($gdImage) { imagedestroy($gdImage); // Relationship docProps/thumbnail.jpeg $this->writeRelationship($objWriter, $idxRelation, 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail', 'docProps/thumbnail.jpeg'); + // $idxRelation++; } } - // ++$idxRelation $objWriter->endElement(); diff --git a/src/PhpPresentation/Writer/Serialized.php b/src/PhpPresentation/Writer/Serialized.php index 72ac2790a..34acb7d2e 100644 --- a/src/PhpPresentation/Writer/Serialized.php +++ b/src/PhpPresentation/Writer/Serialized.php @@ -66,12 +66,11 @@ public function save(string $pFilename): void // Add media $slideCount = $oPresentation->getSlideCount(); for ($i = 0; $i < $slideCount; ++$i) { - for ($j = 0; $j < $oPresentation->getSlide($i)->getShapeCollection()->count(); ++$j) { - if ($oPresentation->getSlide($i)->getShapeCollection()->offsetGet($j) instanceof AbstractDrawingAdapter) { - $imgTemp = $oPresentation->getSlide($i)->getShapeCollection()->offsetGet($j); + foreach ($oPresentation->getSlide($i)->getShapeCollection() as $shape) { + if ($shape instanceof AbstractDrawingAdapter) { $objZip->addFromString( - 'media/' . $imgTemp->getImageIndex() . '/' . pathinfo($imgTemp->getPath(), PATHINFO_BASENAME), - file_get_contents($imgTemp->getPath()) + 'media/' . $shape->getImageIndex() . '/' . pathinfo($shape->getPath(), PATHINFO_BASENAME), + file_get_contents($shape->getPath()) ); } } @@ -99,14 +98,13 @@ protected function writeSerialized(?PhpPresentation $pPhpPresentation = null, $p // Update media links $slideCount = $pPhpPresentation->getSlideCount(); for ($i = 0; $i < $slideCount; ++$i) { - for ($j = 0; $j < $pPhpPresentation->getSlide($i)->getShapeCollection()->count(); ++$j) { - if ($pPhpPresentation->getSlide($i)->getShapeCollection()->offsetGet($j) instanceof AbstractDrawingAdapter) { - $imgTemp = $pPhpPresentation->getSlide($i)->getShapeCollection()->offsetGet($j); - $imgPath = 'zip://' . $pFilename . '#media/' . $imgTemp->getImageIndex() . '/' . pathinfo($imgTemp->getPath(), PATHINFO_BASENAME); - if ($imgTemp instanceof File) { - $imgTemp->setPath($imgPath, false); + foreach ($pPhpPresentation->getSlide($i)->getShapeCollection() as $shape) { + if ($shape instanceof AbstractDrawingAdapter) { + $imgPath = 'zip://' . $pFilename . '#media/' . $shape->getImageIndex() . '/' . pathinfo($shape->getPath(), PATHINFO_BASENAME); + if ($shape instanceof File) { + $shape->setPath($imgPath, false); } else { - $imgTemp->setPath($imgPath); + $shape->setPath($imgPath); } } } diff --git a/tests/PhpPresentation/Tests/DocumentPropertiesTest.php b/tests/PhpPresentation/Tests/DocumentPropertiesTest.php index 5d0b37259..dd2a4d922 100644 --- a/tests/PhpPresentation/Tests/DocumentPropertiesTest.php +++ b/tests/PhpPresentation/Tests/DocumentPropertiesTest.php @@ -46,6 +46,8 @@ public function testGetSet(): void 'keywords' => '', 'category' => '', 'company' => '', + 'revision' => '', + 'status' => '', ]; foreach ($properties as $key => $val) { diff --git a/tests/PhpPresentation/Tests/PresentationPropertiesTest.php b/tests/PhpPresentation/Tests/PresentationPropertiesTest.php index db361430e..88b0920d7 100644 --- a/tests/PhpPresentation/Tests/PresentationPropertiesTest.php +++ b/tests/PhpPresentation/Tests/PresentationPropertiesTest.php @@ -130,14 +130,36 @@ public function testThumbnail(): void $object = new PresentationProperties(); self::assertNull($object->getThumbnailPath()); - self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath('AAAA')); + self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath('AAAA', PresentationProperties::THUMBNAIL_FILE)); self::assertNull($object->getThumbnailPath()); self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath()); self::assertNull($object->getThumbnailPath()); - self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath($imagePath)); + self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath($imagePath, PresentationProperties::THUMBNAIL_FILE)); self::assertEquals($imagePath, $object->getThumbnailPath()); + self::assertIsString($object->getThumbnail()); self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath()); self::assertEquals($imagePath, $object->getThumbnailPath()); + self::assertIsString($object->getThumbnail()); + } + + public function testThumbnailFileNotExisting(): void + { + $imagePath = PHPPRESENTATION_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'NotExistingFile.png'; + + $object = new PresentationProperties(); + self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath($imagePath, PresentationProperties::THUMBNAIL_FILE)); + self::assertNull($object->getThumbnailPath()); + self::assertNull($object->getThumbnail()); + } + + public function testThumbnailFileData(): void + { + $imagePath = PHPPRESENTATION_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'PhpPresentationLogo.png'; + + $object = new PresentationProperties(); + self::assertInstanceOf(PresentationProperties::class, $object->setThumbnailPath($imagePath, PresentationProperties::THUMBNAIL_DATA, file_get_contents($imagePath))); + self::assertEquals('', $object->getThumbnailPath()); + self::assertIsString($object->getThumbnail()); } public function testZoom(): void diff --git a/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php b/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php index 8d04038ef..51b6ac3bf 100644 --- a/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php +++ b/tests/PhpPresentation/Tests/Reader/PowerPoint2007Test.php @@ -101,6 +101,8 @@ public function testLoadFile01(): void self::assertEquals('Sample 02 Description', $oPhpPresentation->getDocumentProperties()->getDescription()); self::assertEquals('office 2007 openxml libreoffice odt php', $oPhpPresentation->getDocumentProperties()->getKeywords()); self::assertEquals('Sample Category', $oPhpPresentation->getDocumentProperties()->getCategory()); + self::assertEquals('', $oPhpPresentation->getDocumentProperties()->getRevision()); + self::assertEquals('', $oPhpPresentation->getDocumentProperties()->getStatus()); self::assertIsArray($oPhpPresentation->getDocumentProperties()->getCustomProperties()); self::assertCount(0, $oPhpPresentation->getDocumentProperties()->getCustomProperties()); diff --git a/tests/PhpPresentation/Tests/Shape/GroupTest.php b/tests/PhpPresentation/Tests/Shape/GroupTest.php index 93cbbf7d7..f5b0eefc5 100644 --- a/tests/PhpPresentation/Tests/Shape/GroupTest.php +++ b/tests/PhpPresentation/Tests/Shape/GroupTest.php @@ -38,7 +38,7 @@ public function testConstruct(): void self::assertEquals(0, $object->getOffsetY()); self::assertEquals(0, $object->getExtentX()); self::assertEquals(0, $object->getExtentY()); - self::assertEquals(0, $object->getShapeCollection()->count()); + self::assertCount(0, $object->getShapeCollection()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\Group', $object->setWidth(mt_rand(1, 100))); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\Group', $object->setHeight(mt_rand(1, 100))); } @@ -52,7 +52,7 @@ public function testAdd(): void self::assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\Line', $object->createLineShape(10, 10, 10, 10)); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\RichText', $object->createRichTextShape()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\Table', $object->createTableShape()); - self::assertEquals(5, $object->getShapeCollection()->count()); + self::assertCount(5, $object->getShapeCollection()); } public function testExtentX(): void diff --git a/tests/PhpPresentation/Tests/Shape/RichTextTest.php b/tests/PhpPresentation/Tests/Shape/RichTextTest.php index 4fd697574..e75137a1e 100644 --- a/tests/PhpPresentation/Tests/Shape/RichTextTest.php +++ b/tests/PhpPresentation/Tests/Shape/RichTextTest.php @@ -277,7 +277,7 @@ public function testHashCode(): void $object = new RichText(); $hash = $object->getActiveParagraph()->getHashCode(); - $hash .= RichText::WRAP_SQUARE . RichText::AUTOFIT_DEFAULT . RichText::OVERFLOW_OVERFLOW . RichText::OVERFLOW_OVERFLOW . '00104.89.69.64.8'; + $hash .= RichText::WRAP_SQUARE . RichText::AUTOFIT_DEFAULT . RichText::OVERFLOW_OVERFLOW . RichText::OVERFLOW_OVERFLOW . '00104.89.69.64.80'; $hash .= md5('00000' . $object->getFill()->getHashCode() . $object->getShadow()->getHashCode() . '' . get_parent_class($object)); $hash .= get_class($object); self::assertEquals(md5($hash), $object->getHashCode()); diff --git a/tests/PhpPresentation/Tests/Slide/AbstractSlideTest.php b/tests/PhpPresentation/Tests/Slide/AbstractSlideTest.php index d8d67a56f..bb93cc756 100644 --- a/tests/PhpPresentation/Tests/Slide/AbstractSlideTest.php +++ b/tests/PhpPresentation/Tests/Slide/AbstractSlideTest.php @@ -19,7 +19,9 @@ namespace PhpOffice\PhpPresentation\Tests\Slide; +use PhpOffice\PhpPresentation\Shape\Chart; use PhpOffice\PhpPresentation\Shape\RichText; +use PhpOffice\PhpPresentation\Shape\Table; use PhpOffice\PhpPresentation\Slide\AbstractSlide; use PHPUnit\Framework\TestCase; @@ -49,4 +51,36 @@ public function testCollection(): void self::assertIsArray($stub->getShapeCollection()); self::assertCount(count($array), $stub->getShapeCollection()); } + + public function testsearchShapes(): void + { + /** @var AbstractSlide $stub */ + $stub = $this->getMockForAbstractClass('PhpOffice\\PhpPresentation\\Slide\\AbstractSlide'); + + $array = [ + (new RichText())->setName('AAA'), + (new Table())->setName('BBB'), + (new Chart())->setName('AAA'), + ]; + self::assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\AbstractSlide', $stub->setShapeCollection($array)); + + // Search by Name + $result = $stub->searchShapes('AAA', null); + self::assertIsArray($result); + self::assertCount(2, $result); + self::assertInstanceOf(RichText::class, $result[0]); + self::assertInstanceOf(Chart::class, $result[1]); + + // Search by Name && Type + $result = $stub->searchShapes('AAA', Chart::class); + self::assertIsArray($result); + self::assertCount(1, $result); + self::assertInstanceOf(Chart::class, $result[0]); + + // Search by Type + $result = $stub->searchShapes(null, Table::class); + self::assertIsArray($result); + self::assertCount(1, $result); + self::assertInstanceOf(Table::class, $result[0]); + } } diff --git a/tests/PhpPresentation/Tests/Slide/NoteTest.php b/tests/PhpPresentation/Tests/Slide/NoteTest.php index 5cf4ce020..145b864a0 100644 --- a/tests/PhpPresentation/Tests/Slide/NoteTest.php +++ b/tests/PhpPresentation/Tests/Slide/NoteTest.php @@ -69,13 +69,13 @@ public function testOffset(): void public function testShape(): void { $object = new Note(); - self::assertEquals(0, $object->getShapeCollection()->count()); + self::assertCount(0, $object->getShapeCollection()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\RichText', $object->createRichTextShape()); - self::assertEquals(1, $object->getShapeCollection()->count()); + self::assertCount(1, $object->getShapeCollection()); $oRichText = new RichText(); - self::assertInstanceOf('PhpOffice\\PhpPresentation\\Shape\\RichText', $object->addShape($oRichText)); - self::assertEquals(2, $object->getShapeCollection()->count()); + self::assertInstanceOf(Note::class, $object->addShape($oRichText)); + self::assertCount(2, $object->getShapeCollection()); } /** diff --git a/tests/PhpPresentation/Tests/Slide/SlideLayoutTest.php b/tests/PhpPresentation/Tests/Slide/SlideLayoutTest.php index b3d23a42d..daea51b22 100644 --- a/tests/PhpPresentation/Tests/Slide/SlideLayoutTest.php +++ b/tests/PhpPresentation/Tests/Slide/SlideLayoutTest.php @@ -37,7 +37,7 @@ public function testBase(): void $object = new SlideLayout($mockSlideMaster); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\AbstractSlide', $object); - self::assertInstanceOf('\\ArrayObject', $object->getShapeCollection()); + self::assertIsArray($object->getShapeCollection()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\ColorMap', $object->colorMap); } diff --git a/tests/PhpPresentation/Tests/Slide/SlideMasterTest.php b/tests/PhpPresentation/Tests/Slide/SlideMasterTest.php index e910ae79a..b79cc1c31 100644 --- a/tests/PhpPresentation/Tests/Slide/SlideMasterTest.php +++ b/tests/PhpPresentation/Tests/Slide/SlideMasterTest.php @@ -38,7 +38,7 @@ public function testBase(): void $object = new SlideMaster(); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Slide\\AbstractSlide', $object); self::assertNull($object->getParent()); - self::assertInstanceOf('\\ArrayObject', $object->getShapeCollection()); + self::assertIsArray($object->getShapeCollection()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\ColorMap', $object->colorMap); /** @var Color $background */ $background = $object->getBackground(); diff --git a/tests/PhpPresentation/Tests/Style/BorderTest.php b/tests/PhpPresentation/Tests/Style/BorderTest.php index 80b4d3498..279f0b345 100644 --- a/tests/PhpPresentation/Tests/Style/BorderTest.php +++ b/tests/PhpPresentation/Tests/Style/BorderTest.php @@ -51,7 +51,7 @@ public function testSetGetColor(): void $object = new Border(); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setColor()); self::assertNull($object->getColor()); - self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setColor(new Color(COLOR::COLOR_BLUE))); + self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setColor(new Color(Color::COLOR_BLUE))); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Color', $object->getColor()); self::assertEquals('FF0000FF', $object->getColor()->getARGB()); } @@ -66,7 +66,7 @@ public function testSetGetDashStyle(): void self::assertEquals(Border::DASH_SOLID, $object->getDashStyle()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setDashStyle('')); self::assertEquals(Border::DASH_SOLID, $object->getDashStyle()); - self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setDashStyle(BORDER::DASH_DASH)); + self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setDashStyle(Border::DASH_DASH)); self::assertEquals(Border::DASH_DASH, $object->getDashStyle()); } @@ -91,7 +91,7 @@ public function testSetGetLineStyle(): void self::assertEquals(Border::LINE_SINGLE, $object->getLineStyle()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setLineStyle('')); self::assertEquals(Border::LINE_SINGLE, $object->getLineStyle()); - self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setLineStyle(BORDER::LINE_DOUBLE)); + self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Border', $object->setLineStyle(Border::LINE_DOUBLE)); self::assertEquals(Border::LINE_DOUBLE, $object->getLineStyle()); } diff --git a/tests/PhpPresentation/Tests/Style/ColorTest.php b/tests/PhpPresentation/Tests/Style/ColorTest.php index 97485b57d..c4b5055f5 100644 --- a/tests/PhpPresentation/Tests/Style/ColorTest.php +++ b/tests/PhpPresentation/Tests/Style/ColorTest.php @@ -36,7 +36,7 @@ public function testConstruct(): void { $object = new Color(); self::assertEquals(Color::COLOR_BLACK, $object->getARGB()); - $object = new Color(COLOR::COLOR_BLUE); + $object = new Color(Color::COLOR_BLUE); self::assertEquals(Color::COLOR_BLUE, $object->getARGB()); } diff --git a/tests/PhpPresentation/Tests/Style/FillTest.php b/tests/PhpPresentation/Tests/Style/FillTest.php index 3430b430e..676156ed3 100644 --- a/tests/PhpPresentation/Tests/Style/FillTest.php +++ b/tests/PhpPresentation/Tests/Style/FillTest.php @@ -50,9 +50,9 @@ public function testConstruct(): void public function testSetGetEndColor(): void { $object = new Fill(); - self::assertInstanceOf(Fill::class, $object->setEndColor(new Color(COLOR::COLOR_BLUE))); + self::assertInstanceOf(Fill::class, $object->setEndColor(new Color(Color::COLOR_BLUE))); self::assertInstanceOf(Color::class, $object->getEndColor()); - self::assertEquals(COLOR::COLOR_BLUE, $object->getEndColor()->getARGB()); + self::assertEquals(Color::COLOR_BLUE, $object->getEndColor()->getARGB()); } /** @@ -86,9 +86,9 @@ public function testSetGetRotation(): void public function testSetGetStartColor(): void { $object = new Fill(); - self::assertInstanceOf(Fill::class, $object->setStartColor(new Color(COLOR::COLOR_BLUE))); + self::assertInstanceOf(Fill::class, $object->setStartColor(new Color(Color::COLOR_BLUE))); self::assertInstanceOf(Color::class, $object->getStartColor()); - self::assertEquals(COLOR::COLOR_BLUE, $object->getStartColor()->getARGB()); + self::assertEquals(Color::COLOR_BLUE, $object->getStartColor()->getARGB()); } /** diff --git a/tests/PhpPresentation/Tests/Style/FontTest.php b/tests/PhpPresentation/Tests/Style/FontTest.php index 711c2da53..6eabdd74b 100644 --- a/tests/PhpPresentation/Tests/Style/FontTest.php +++ b/tests/PhpPresentation/Tests/Style/FontTest.php @@ -19,6 +19,7 @@ namespace PhpOffice\PhpPresentation\Tests\Style; +use PhpOffice\PhpPresentation\Exception\InvalidParameterException; use PhpOffice\PhpPresentation\Exception\NotAllowedValueException; use PhpOffice\PhpPresentation\Style\Color; use PhpOffice\PhpPresentation\Style\Font; @@ -49,6 +50,18 @@ public function testConstruct(): void self::assertEquals(Font::CAPITALIZATION_NONE, $object->getCapitalization()); self::assertInstanceOf('PhpOffice\\PhpPresentation\\Style\\Color', $object->getColor()); self::assertEquals(Color::COLOR_BLACK, $object->getColor()->getARGB()); + self::assertEquals(0, $object->getBaseline()); + } + + /** + * Test get/set Baseline. + */ + public function testBaseline(): void + { + $object = new Font(); + self::assertEquals(0, $object->getBaseline()); + self::assertInstanceOf(Font::class, $object->setBaseline(Font::BASELINE_SUBSCRIPT)); + self::assertEquals(Font::BASELINE_SUBSCRIPT, $object->getBaseline()); } /** @@ -76,6 +89,17 @@ public function testCapitalizationException(): void $object->setCapitalization('Invalid'); } + /** + * Test get/set charset. + */ + public function testCharset(): void + { + $object = new Font(); + self::assertEquals(Font::CHARSET_DEFAULT, $object->getCharset()); + self::assertInstanceOf(Font::class, $object->setCharset(12)); + self::assertEquals(12, $object->getCharset()); + } + /** * Test get/set Character Spacing. */ @@ -134,6 +158,52 @@ public function testName(): void self::assertEquals('Arial', $object->getName()); } + /** + * Test get/set panose. + */ + public function testPanose(): void + { + $object = new Font(); + self::assertEquals('', $object->getPanose()); + self::assertInstanceOf(Font::class, $object->setPanose('4494D72242')); + self::assertEquals('4494D72242', $object->getPanose()); + } + + /** + * Test get/set panose (Exception : Invalid Length). + */ + public function testPanoseExceptionInvalidLength(): void + { + $this->expectException(InvalidParameterException::class); + $this->expectExceptionMessage('The parameter pValue can\'t have the value "12345" (Validation: The length is not equals to 10)'); + + $object = new Font(); + $object->setPanose('12345'); + } + + /** + * Test get/set panose (Exception : Invalid Char). + */ + public function testPanoseExceptionInvalidChar(): void + { + $this->expectException(InvalidParameterException::class); + $this->expectExceptionMessage('The parameter pValue can\'t have the value "4494D7224X" (Validation: The character "X" is not allowed)'); + + $object = new Font(); + $object->setPanose('4494D7224X'); + } + + /** + * Test get/set pitch family. + */ + public function testPitchFamily(): void + { + $object = new Font(); + self::assertEquals(0, $object->getPitchFamily()); + self::assertInstanceOf(Font::class, $object->setPitchFamily(12)); + self::assertEquals(12, $object->getPitchFamily()); + } + /** * Test get/set size. */ @@ -154,11 +224,11 @@ public function testUnderline(): void { $object = new Font(); self::assertInstanceOf(Font::class, $object->setUnderline()); - self::assertEquals(FONT::UNDERLINE_NONE, $object->getUnderline()); + self::assertEquals(Font::UNDERLINE_NONE, $object->getUnderline()); self::assertInstanceOf(Font::class, $object->setUnderline('')); - self::assertEquals(FONT::UNDERLINE_NONE, $object->getUnderline()); - self::assertInstanceOf(Font::class, $object->setUnderline(FONT::UNDERLINE_DASH)); - self::assertEquals(FONT::UNDERLINE_DASH, $object->getUnderline()); + self::assertEquals(Font::UNDERLINE_NONE, $object->getUnderline()); + self::assertInstanceOf(Font::class, $object->setUnderline(Font::UNDERLINE_DASH)); + self::assertEquals(Font::UNDERLINE_DASH, $object->getUnderline()); } /** @@ -197,10 +267,18 @@ public function testSetIsStriketrough(): void $object = new Font(); self::assertInstanceOf(Font::class, $object->setStrikethrough()); self::assertFalse($object->isStrikethrough()); + self::assertEquals(Font::STRIKE_NONE, $object->getStrikethrough()); + // boolean self::assertInstanceOf(Font::class, $object->setStrikethrough(false)); self::assertFalse($object->isStrikethrough()); + self::assertEquals(Font::STRIKE_NONE, $object->getStrikethrough()); self::assertInstanceOf(Font::class, $object->setStrikethrough(true)); self::assertTrue($object->isStrikethrough()); + self::assertEquals(Font::STRIKE_SINGLE, $object->getStrikethrough()); + // string + self::assertInstanceOf(Font::class, $object->setStrikethrough(Font::STRIKE_DOUBLE)); + self::assertTrue($object->isStrikethrough()); + self::assertEquals(Font::STRIKE_DOUBLE, $object->getStrikethrough()); } /** diff --git a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsCoreTest.php b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsCoreTest.php index 3a87a2613..5c79a1ee8 100644 --- a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsCoreTest.php +++ b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsCoreTest.php @@ -25,13 +25,6 @@ class DocPropsCoreTest extends PhpPresentationTestCase { protected $writerName = 'PowerPoint2007'; - public function testRender(): void - { - $this->assertZipFileExists('docProps/core.xml'); - $this->assertZipXmlElementNotExists('docProps/core.xml', '/cp:coreProperties/cp:contentStatus'); - $this->assertIsSchemaECMA376Valid(); - } - public function testDocumentProperties(): void { $expected = 'aAbBcDeE'; @@ -42,7 +35,9 @@ public function testDocumentProperties(): void ->setDescription($expected) ->setSubject($expected) ->setKeywords($expected) - ->setCategory($expected); + ->setCategory($expected) + ->setRevision($expected) + ->setStatus($expected); $this->assertZipFileExists('docProps/core.xml'); $this->assertZipXmlElementExists('docProps/core.xml', '/cp:coreProperties/dc:creator'); @@ -57,6 +52,10 @@ public function testDocumentProperties(): void $this->assertZipXmlElementEquals('docProps/core.xml', '/cp:coreProperties/cp:keywords', $expected); $this->assertZipXmlElementExists('docProps/core.xml', '/cp:coreProperties/cp:category'); $this->assertZipXmlElementEquals('docProps/core.xml', '/cp:coreProperties/cp:category', $expected); + $this->assertZipXmlElementExists('docProps/core.xml', '/cp:coreProperties/cp:revision'); + $this->assertZipXmlElementEquals('docProps/core.xml', '/cp:coreProperties/cp:revision', $expected); + $this->assertZipXmlElementExists('docProps/core.xml', '/cp:coreProperties/cp:contentStatus'); + $this->assertZipXmlElementEquals('docProps/core.xml', '/cp:coreProperties/cp:contentStatus', $expected); $this->assertIsSchemaECMA376Valid(); } @@ -73,7 +72,8 @@ public function testMarkAsFinalFalse(): void { $this->oPresentation->getPresentationProperties()->markAsFinal(false); - $this->assertZipXmlElementNotExists('docProps/core.xml', '/cp:coreProperties/cp:contentStatus'); + $this->assertZipXmlElementExists('docProps/core.xml', '/cp:coreProperties/cp:contentStatus'); + $this->assertZipXmlElementEquals('docProps/core.xml', '/cp:coreProperties/cp:contentStatus', ''); $this->assertIsSchemaECMA376Valid(); } } diff --git a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsThumbnailTest.php b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsThumbnailTest.php index cd29a9733..ddab8a1cc 100644 --- a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsThumbnailTest.php +++ b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/DocPropsThumbnailTest.php @@ -19,6 +19,7 @@ namespace PhpPresentation\Tests\Writer\PowerPoint2007; +use PhpOffice\PhpPresentation\PresentationProperties; use PhpOffice\PhpPresentation\Tests\PhpPresentationTestCase; /** @@ -31,15 +32,40 @@ class DocPropsThumbnailTest extends PhpPresentationTestCase public function testRender(): void { $this->assertZipFileNotExists('docProps/thumbnail.jpeg'); + $this->assertZipXmlElementNotExists('_rels/.rels', '/Relationships/Relationship[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); $this->assertIsSchemaECMA376Valid(); } - public function testFeatureThumbnail(): void + public function testFeatureThumbnailFile(): void { $imagePath = PHPPRESENTATION_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'PhpPresentationLogo.png'; - $this->oPresentation->getPresentationProperties()->setThumbnailPath($imagePath); + $this->oPresentation->getPresentationProperties() + ->setThumbnailPath($imagePath, PresentationProperties::THUMBNAIL_FILE); $this->assertZipFileExists('docProps/thumbnail.jpeg'); + $this->assertZipXmlElementExists('_rels/.rels', '/Relationships/Relationship[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); + $this->assertIsSchemaECMA376Valid(); + } + + public function testFeatureThumbnailFileNotExisting(): void + { + $imagePath = PHPPRESENTATION_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'NotExistingFile.png'; + + $this->oPresentation->getPresentationProperties() + ->setThumbnailPath($imagePath, PresentationProperties::THUMBNAIL_FILE); + $this->assertZipFileNotExists('docProps/thumbnail.jpeg'); + $this->assertZipXmlElementNotExists('_rels/.rels', '/Relationships/Relationship[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); + $this->assertIsSchemaECMA376Valid(); + } + + public function testFeatureThumbnailData(): void + { + $imagePath = PHPPRESENTATION_TESTS_BASE_DIR . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'PhpPresentationLogo.png'; + + $this->oPresentation->getPresentationProperties() + ->setThumbnailPath('', PresentationProperties::THUMBNAIL_DATA, file_get_contents($imagePath)); + $this->assertZipFileExists('docProps/thumbnail.jpeg'); + $this->assertZipXmlElementExists('_rels/.rels', '/Relationships/Relationship[@Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"]'); $this->assertIsSchemaECMA376Valid(); } } diff --git a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlideMastersTest.php b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlideMastersTest.php index c4374b6d1..67181ac06 100644 --- a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlideMastersTest.php +++ b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlideMastersTest.php @@ -62,7 +62,7 @@ public function testWriteSlideMasterRelationships(): void ->willReturn($layouts); /** @var ArrayObject $collection */ - $collection = new ArrayObject(); + $collection = []; $collection[] = new ShapeDrawingFile(); $collection[] = new ShapeDrawingFile(); $collection[] = new ShapeDrawingFile(); diff --git a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlidesTest.php b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlidesTest.php index 9e0640477..652ebd5b4 100644 --- a/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlidesTest.php +++ b/tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptSlidesTest.php @@ -868,6 +868,53 @@ public function testRichTextHyperlink(): void $this->assertIsSchemaECMA376Valid(); } + public function testRichTextRunFontCharset(): void + { + $latinElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:latin'; + $eastAsianElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:ea'; + $complexScriptElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:cs'; + + $oSlide = $this->oPresentation->getActiveSlide(); + $oRichText = $oSlide->createRichTextShape(); + $oRun = $oRichText->createTextRun('MyText'); + $oRun->getFont()->setCharset(18); + + $oRun->getFont()->setFormat(Font::FORMAT_LATIN); + + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $latinElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $latinElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $latinElement, 'charset'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $latinElement, 'charset', '12'); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertIsSchemaECMA376Valid(); + + $oRun->getFont()->setFormat(Font::FORMAT_EAST_ASIAN); + $this->resetPresentationFile(); + + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $eastAsianElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $eastAsianElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $eastAsianElement, 'charset'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $eastAsianElement, 'charset', '12'); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertIsSchemaECMA376Valid(); + + $oRun->getFont()->setFormat(Font::FORMAT_COMPLEX_SCRIPT); + $this->resetPresentationFile(); + + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $complexScriptElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $complexScriptElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $complexScriptElement, 'charset'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $complexScriptElement, 'charset', '12'); + $this->assertIsSchemaECMA376Valid(); + } + public function testRichTextRunFontFormat(): void { $latinElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:latin'; @@ -907,6 +954,100 @@ public function testRichTextRunFontFormat(): void $this->assertIsSchemaECMA376Valid(); } + public function testRichTextRunFontPanose(): void + { + $latinElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:latin'; + $eastAsianElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:ea'; + $complexScriptElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:cs'; + + $oSlide = $this->oPresentation->getActiveSlide(); + $oRichText = $oSlide->createRichTextShape(); + $oRun = $oRichText->createTextRun('MyText'); + $oRun->getFont()->setPanose('4494D72242'); + + $oRun->getFont()->setFormat(Font::FORMAT_LATIN); + + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $latinElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $latinElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $latinElement, 'panose'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $latinElement, 'panose', '040409040D0702020402'); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertIsSchemaECMA376Valid(); + + $oRun->getFont()->setFormat(Font::FORMAT_EAST_ASIAN); + $this->resetPresentationFile(); + + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $eastAsianElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $eastAsianElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $eastAsianElement, 'panose'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $eastAsianElement, 'panose', '040409040D0702020402'); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertIsSchemaECMA376Valid(); + + $oRun->getFont()->setFormat(Font::FORMAT_COMPLEX_SCRIPT); + $this->resetPresentationFile(); + + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $complexScriptElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $complexScriptElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $complexScriptElement, 'panose'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $complexScriptElement, 'panose', '040409040D0702020402'); + $this->assertIsSchemaECMA376Valid(); + } + + public function testRichTextRunFontPitchFamily(): void + { + $latinElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:latin'; + $eastAsianElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:ea'; + $complexScriptElement = '/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr/a:cs'; + + $oSlide = $this->oPresentation->getActiveSlide(); + $oRichText = $oSlide->createRichTextShape(); + $oRun = $oRichText->createTextRun('MyText'); + $oRun->getFont()->setPitchFamily(42); + + $oRun->getFont()->setFormat(Font::FORMAT_LATIN); + + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $latinElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $latinElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $latinElement, 'pitchFamily'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $latinElement, 'pitchFamily', '42'); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertIsSchemaECMA376Valid(); + + $oRun->getFont()->setFormat(Font::FORMAT_EAST_ASIAN); + $this->resetPresentationFile(); + + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $eastAsianElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $eastAsianElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $eastAsianElement, 'pitchFamily'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $eastAsianElement, 'pitchFamily', '42'); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertIsSchemaECMA376Valid(); + + $oRun->getFont()->setFormat(Font::FORMAT_COMPLEX_SCRIPT); + $this->resetPresentationFile(); + + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $latinElement); + $this->assertZipXmlElementNotExists('ppt/slides/slide1.xml', $eastAsianElement); + $this->assertZipXmlElementExists('ppt/slides/slide1.xml', $complexScriptElement); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $complexScriptElement, 'typeface'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $complexScriptElement, 'typeface', 'Calibri'); + $this->assertZipXmlAttributeExists('ppt/slides/slide1.xml', $complexScriptElement, 'pitchFamily'); + $this->assertZipXmlAttributeEquals('ppt/slides/slide1.xml', $complexScriptElement, 'pitchFamily', '42'); + $this->assertIsSchemaECMA376Valid(); + } + public function testRichTextRunLanguage(): void { $oSlide = $this->oPresentation->getActiveSlide(); diff --git a/tests/PhpPresentation/Tests/_includes/PhpPresentationTestCase.php b/tests/PhpPresentation/Tests/_includes/PhpPresentationTestCase.php index 0fc395d3a..120ffe0c9 100644 --- a/tests/PhpPresentation/Tests/_includes/PhpPresentationTestCase.php +++ b/tests/PhpPresentation/Tests/_includes/PhpPresentationTestCase.php @@ -320,6 +320,18 @@ public function assertZipXmlElementEquals($filePath, $xPath, $value): void self::assertEquals($nodeList->item(0)->nodeValue, $value); } + /** + * @param string $filePath + * @param string $xPath + * @param mixed $value + */ + public function assertZipXmlElementNotEquals($filePath, $xPath, $value): void + { + $this->writePresentationFile($this->oPresentation, $this->writerName); + $nodeList = $this->getXmlNodeList($filePath, $xPath); + self::assertNotEquals($nodeList->item(0)->nodeValue, $value); + } + /** * @param mixed $value */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 8d83f9d83..b674b39bd 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -51,4 +51,4 @@ }); require_once __DIR__ . '/../src/PhpPresentation/Autoloader.php'; -\PhpOffice\PhpPresentation\Autoloader::register(); +PhpOffice\PhpPresentation\Autoloader::register(); diff --git a/tests/resources/files/serialized.phppt b/tests/resources/files/serialized.phppt index 828ad826e1d9b31608d88ea1e331f153903e5d42..8c213110fa7cae259def2c0af958aeae19e7ef50 100644 GIT binary patch delta 6980 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 WpGKh?008x&lO#Ad2K+Yw0002PE@6iN delta 6917 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 LHwL~p00000`5jPQ